Find out what features are supported by what CPU

I'm wondering about making better use of available CPU features I'm working on. While I currently use target-cpu=native in my development environment and in my staging environment (different kinds of macOS machines), I deploy into GCP on N2D instances (2nd-gen AMD Zen).

As I understand it, there's no good way to build docker images that abstract over this difference, so I'm wondering what the best way forward is. I found Using RUSTFLAGS - Rust SIMD Performance Guide which was quite helpful; it contains the text "The compiler will translate this into a list of target features.".

Is there some way of inspecting what features the compiler will enable for a given target CPU, so that I could define a list of "least common denominator" features available on both, say, znver2 and skylake? And does anyone have a sense of how impactful optimizations the compiler can make beyond the availability of features (for example, it looks like LLVM has a cost model for different processors)?

Rustc directly gets this information from LLVM:

https://github.com/rust-lang/rust/blob/4940dd483a8448c0f1ef28d304fad88a9d983c4e/compiler/rustc_codegen_llvm/src/llvm_util.rs#L167

For example for Zen2 LLVM has:

https://github.com/llvm/llvm-project/blob/c2c83e97c3ac98ddf5bd685cbfba3f620f59fa51/llvm/lib/Target/X86/X86.td#L1028-L1073

Skylake has the following in addition to what is available on Broadwell:

https://github.com/llvm/llvm-project/blob/c2c83e97c3ac98ddf5bd685cbfba3f620f59fa51/llvm/lib/Target/X86/X86.td#L652-L670

Be sure to look at the output of these two commands, it can be quite helpful, the target features are among the target cfgs being shown here:

rustc --print cfg
rustc --print cfg -C target-cpu=native

And the output can be different depending on stable vs nightly as well - with more cfgs being activated on nightly.

Thanks, this is also very useful! Is this stuff documented anywhere in the rust-lang docs? And I presume CPU features do not vary across the OS part of a target triple, is that a safe assumption?

After comparing a list based on LLVM sources compared to what rustc --print cfg -C target-cpu=native gives me on skylake, quite a few things are missing (like x87, lahfsah or ermsb) from the output of the rustc command. I also see some inconsistency between the list printed by rustc for print --target-features vs print --cfg (like bmi vs bmi1 and pclmulqdq), any thoughts on that?

What kind of inconsistency?

This seems weird: when passing the bmi1, pclmulqdq or rdrand options as a -Ctarget-feature value, I get a warning like '+bmi1' is not a recognized feature for this target (ignoring feature). Opened an issue about this: https://github.com/rust-lang/rust/issues/81881/.

When I was going through the process I found it useful to ground/validate what the compiler was reporting with what I knew about my local CPU running OSX. In my case, I used

sysctl -a | grep machdep.cpu.features

... to get most of the features supported by my CPU. The full feature set I was expecting could all be found under the machdep.cpu register/setting.