Changing the default x86-64 compilation target to v2 or v3

OS support and CPU support are different in my opinion. Old operating systems are, in a lot of cases, freely updatable (which is not always possible or easy, but often is). More importantly, old operating systems come with all sorts of problems (security) that mean that no one should be using them anyways. But old CPUs have no such problems, they're slow but run perfectly fine. I think we should be quite conservative with CPU support, and I'd rather see us look more towards making multiversioning and target feature detection easier than raising the baseline.

8 Likes

that's not quite true, e.g. a lot of older cpus have Spectre-style bugs that were never fixed because they're so old the manufacturer didn't bother, e.g. as far as they can tell the Pentium II should be vulnerable to Meltdown but is so ancient that I expect no one bothered to try to produce updated Microcode to fix that. I'd guess the same thing happened for the 64-bit versions of the Pentium 4 which uses the x86-64-v1 ISA.

3 Likes

It may depend on the OS too. I imagine that many people are still running old hardware with Linux, but Windows 10 probably requires x86-64-v2, so if it is actually the case, it would be possible to enable it on x86_64-pc-windows-*.

4 Likes

Windows baseline features were already bumped in Enable CMPXCHG16B, SSE3, SAHF/LAHF and 128-bit Atomics (in nightly) in Windows x64 by CKingX · Pull Request #120820 · rust-lang/rust · GitHub Apparently SSE4 is not a requirement, so that's not -v2 either.

1 Like

Which is an interesting challenge for Linux - Rust Windows will generate faster binaries in some cases just because Windows mandates a minimum CPU version.

I think the argument about what percentage use a given CPU is a side track. It's clearly going to be an overwhelming majority regardless of the skew in your data collection (you could argue that no one is trying to run Rust programs on older CPUs). The more important thing is that this doesn't drop support for older CPUs. Developers targeting those CPUs can change a flag and rebuild.

The question about the stdlib is interesting and I don't have a good answer. I think ideally it would make the most sense to have separate prebuilt stdlibs rather than targeting the lowest common denominator.

1 Like

That same argument can be made in either direction though. You can just change to a newer architecture if it is beneficial to your program.

1 Like

You could argue that, but you would be wrong. I checked and the CPU I had in mind is v1. I do run Rust programs on it and it does its job just fine, so there's no reason to replace it. Sample size of one, but one is greater than none.

My binaries are distro supplied or compiled locally, and I pay attention to changes such as this one, so it's not going to be a problem for me personally. But after looking for other projects that have made such a change,[1] I'm pretty confident it will end up breaking things for other people.

Trying to gauge the extent of the breakage is entirely reasonable.


  1. 1 2 3 4 ↩︎

I know this is an old thread but to add to this, zig defaults to native and I haven't heard of any issues yet. I'd make the assumption majority of developers are at v3 right now.

I've had this discussion at $work. Bumping company-wide default to v2 was easy, with no objections once explained how old and conservative this baseline really is.

v3 was concerning, and didn't make it as a default. It's okay for developers themselves, and running code in controlled environments, but was deemed too risky for releasing binaries to the general public. For example, there are relatively recent Atom/Celeron CPUs that aren't compatible, and it's hard to say who would be cut off. It's especially problematic that new instructions cause crashes, harming reputation of the software (programs could check at startup and explain, but that's not the default).

10 Likes

I’d really like to see the default compilation target increased to v2 or v3.

One benefit of having a newer default is that it has a positive impact across the Rust ecosystem of encouraging use of instructions that nearly all x86-64 CPUs support, but which aren’t statically guaranteed by the current x86-64 target. It is possible to dynamically dispatch based on the available CPU instructions, but it requires unsafe code and jumping through some hoops to get rustc to generate multiple copies of methods. There’s also overhead associated with the dynamic dispatch which sometimes outweighs the speedup better instructions could provide.

This is particularly relevant for std::simd which by default only uses SIMD instructions from x86-64-v1 and not anything newer.

Based on the links shared above (1 2 3 4), even bumping the baseline to v2 will still cause breakage for a good chunk of people.

1 Like

The first two seem to be caused by qemu being configured to emulate a v1 CPU and reject newer instructions (which it would support otherwise). This seems like a catch22, because users won't notice such configuration issues for as long as it doesn't cause them any problems.

The other cases are people actually using pre-2011 hardware.

Then it's a matter of somehow quantifying how many users will be affected, and deciding where to draw the line. Rust isn't removing v1 CPU support, so this isn't a dead-end, but an annoyance. It's very subjective, even philosophical problem, where is the right balance between making optimizations easier for the majority vs compatibility harder for a minority.

3 Likes

It is a dead-end, indirectly: being the default means people will build for it, so those people using old hardware will be unable to use that software. Although probably most software where authors will just use the default is open source, so said people could build from source, so again not a dead-end.

1 Like

Windows 11 seems to effectively require x86_64-v2[1], and Windows 10 is entering its last legs of extended support, so that's some precedent suggesting requiring v2 by default is reasonable.

It's worth noting additionally that if Rust is compiled targeting v2, that Rust code cannot safely perform the check that v2 is actually satisfied; target feature support cannot be hidden after it's been observed to be available[2]. The best you'd be able to do likely is to compile the binary crate with the minimal target, do the check, then call into library code built with the full target and hope inlining doesn't break anything.

I could see stdlib doing a check and rtabort! if the target doesn't have the enabled features for hosted targets, though. That'd even solve some of the perf complaints for feature detection, since then startup would initialize the detection instead of needing to check lazy initialization. (I think, more specifically, it makes sense for std to do such precheck when the target process start convention provides the target feature information without need to directly call the CPU feature detection instruction.)

I get that's complex and splits hosted from unhosted targets even more, which isn't great.


  1. Windows 11 requires SSE4.2 and only officially supports Intel Gen 8+ / AMD Zen+, which both satisfy x86_64-v2. ↩︎

  2. Actually, how do we handle big.LITTLE targets? Only enable features available on the little cores? Pin the program to the big cores? ↩︎

Sure, it's UB the moment the program starts, but the odds of the compiler not doing what we want are very small, and anyway it's just to improve the message.

1 Like

It would also cause complication for using rust code as libraries from other languages.

That might or might not be the case currently. But a memset or memcpy might be compiled into AVX code and I could see that showing up while printing a nicely formatted error.

And with the upcoming APX extension in a few years which extra general purpose registers on x86, it seems quite likely that LLVM might use them too early.

Besides you need customisation for how to show the error: a terminal program and a GUI program will want to show this in diffrent ways.

1 Like

Well, if you're using the std feature detection macro, the odds are 100% of it not working, since it checks statically enabled features first :slight_smile:.

For Windows targets, yes. That doesn't help for Linux targets.

2 Likes

The "enterprise IoT LTSC" variant of Windows 10, which despite the name is a free sidegrade for anyone with any existing W10 license, will be supported through the end of 2032; I wouldn't call that "last legs."