(This post is a logical continuation of https://internals.rust-lang.org/t/x86-64-v2-and-x86-64-v3-targets-for-linux-and-windows/14030.)
The X86-64 System V ABI working group has defined x86-64-v2, x86-64-v3, and x86-64-v4 microarchitecture levels so you can target more modern CPUs instead of limiting compiled instructions to the ~2003 era x86-64 instruction set (the default for ~all compilers targeting x86-64). These are conceptually distinct target triples because the target CPU is different and produced binaries would (likely) be incompatible with older CPUs since they would contain modern instructions (like AVX) not understood by older CPUs.
Modern versions of Clang and GCC support these CPU targets and triples. And some Linux distros (e.g. RedHat) are moving to support x86-64-v2 (and maybe -v3) precompiled packages out-of-the-box.
Discussion in Add x86-64-v2, x86-64-v3, and x86-64-v4 as available target_cpus · Issue #82024 · rust-lang/rust · GitHub and an experiment at Build the compiler with -Ctarget-cpu=x86-64-v2 by est31 · Pull Request #79043 · rust-lang/rust · GitHub demonstrate that Rust today supports the x86-64-v2, x86-64-v3, and x86-64-v4 CPU targets by passing e.g. -Ctarget-cpu=x86-64-v3
as a compiler flag.
I think it is only a matter of time before industry realizes that the default of building x86-64 binaries not leveraging ~20 years of x86-64 ISA innovation is sacrificing a lot of performance potential and we start seeing a shift to ditch the original x86-64 ISA as the default compiler target. (The Clear Linux distro and its superior performance partially enabled by aggressive ISA targeting defaults is an existence proof that a lot of software is artificially limited in performance due to legacy ISA targeting.)
While it is possible to tell Rust today to emit more modern x86-64 instructions using flags like -Ctarget-cpu
, the lack of formally defined triples for x86-64-v*
causes real problems. For example:
-
cargo build --target x86_64_v3-unknown-linux-gnu
don't just work because thex86_64_v*
variants aren't recognized. -
rustup
can't install a [default] toolchain that targets a modern CPU level (presumably because Rust toolchains for these targets aren't published). - Relying on
.cargo/config
files to override the default CPU via e.g.build.rustflags
is brittle since other config files may override this field and undo default targeting. (This is obviously part of a general problem with how these config files work.) - The ubiquitous
platforms
crate doesn't recognize triples likex86_64_v2-unknown-linux-gnu
since this triple is not published to https://raw.githubusercontent.com/rust-lang/rust/master/src/doc/rustc/src/platform-support.md.
I feel like the current ergonomics of x86-64-v* targeting in Rust are sub-optimal. And this will likely get worse over time as x86-64-v2+ targeting becomes the norm and more and more people get tripped up by Rust not doing/supporting what their C/C++ toolchain does. We could even see situations where Linux distros are shipping Clang/GCC compilers that emit x86-64-v2 or x86-64-v3 by default but a rustup installed Rust is still targeting x86-64 by default. Blog posts claiming poor Rust performance vs C/C++/Go/etc due to ISA targeting differences ensue.
From my perspective as an end-user, it seems like Rust having some native support for x86_64_v2-*
, x86_64_v3-*
, and x86_64_v4-*
target triples seems to make a lot of the ergonomic issues with modern ISA targeting go away.
Support for x86-64 microarchitecture levels in Rust target triples could take various forms. Perhaps Rust could internally normalize to an existing x86_64-*
Rust toolchain but thread the newer target CPU to LLVM for codegen. Or maybe Rust goes all in and publishes actual x86_64_v*-*
Rust toolchains. Maybe someday rustup sniffs for CPU features and automatically installs an e.g. x86_64_v3-unknown-linux-gnu
toolchain when running on a modern CPU. There's a lot of room for partial and incremental changes towards better x86-64 targeting support in Rust.
(If you squint hard enough, similar problems exist for other CPU types. ARM, notably, has many CPU/ISA variants. And Rust today seems to define triple variants for many of them. Although this is arguably due to copying LLVM triples and LLVM likely did it out of necessity given lack of ISA compatibility between many ARM variants. But within what Rust/LLVM calls aarch64 there could be room to introduce better triple support for CPU targets to enable features like SVE.)
Should Rust have better support for x86-64 microarchitecture targeting and what form should that take, if any? And since I feel passionately about the topic (and the potential for the software industry to reduce its carbon footprint by improving efficiency through modern ISA targeting), how can I help?