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)?

2 Likes

Rustc directly gets this information from LLVM:

For example for Zen2 LLVM has:

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

3 Likes

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.

4 Likes

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: rustc --print cfg prints features that are invalid for `-Ctarget-feature` · Issue #81881 · rust-lang/rust · GitHub.

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.