Skip to content

new warnings about #[inline(always)] functions missing #[target_feature(enable="sse")] #141848

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
oconnor663 opened this issue Jun 1, 2025 · 7 comments · Fixed by #141309
Closed
Labels
A-ABI Area: Concerning the application binary interface (ABI) A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. C-discussion Category: Discussion or questions that doesn't represent real issues. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@oconnor663
Copy link
Contributor

Apologies if this code was always broken and I just don't know it yet :) Here's a CI run that recently started failing, due to new warnings plus our usual RUSTFLAGS: "-D warnings": https://github.com/BLAKE3-team/BLAKE3/actions/runs/15326026728/job/43120654065. Reproducing that locally:

$ git clone https://github.com/BLAKE3-team/BLAKE3                                                                                                  
...
$ cd BLAKE3                                                                                                                                        
$ cross rustc --release --target i686-unknown-linux-musl -- -C target-cpu=i386                                                                     
...
warning: this function definition uses SIMD vector type `std::arch::x86::__m128i` which (with the chosen ABI) requires the `sse` target feature, wh
ich is not enabled                                                                                                                                 
  --> src/rust_sse2.rs:75:1                                                                                                                        
   |                                                                                                                                               
75 | / unsafe fn g1(                                                                                                                               
76 | |     row0: &mut __m128i,                                                                                                                     
77 | |     row1: &mut __m128i,                                                                                                                     
78 | |     row2: &mut __m128i,                                                                                                                     
79 | |     row3: &mut __m128i,                                                                                                                     
80 | |     m: __m128i,                                                                                                                             
81 | | ) {                                                                                                                                         
   | |_^ function defined here
   |
   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
   = note: for more information, see issue #116558 <https://github.com/rust-lang/rust/issues/116558>
   = help: consider enabling it globally (`-C target-feature=+sse`) or locally (`#[target_feature(enable="sse")]`)
...

The code in that file is divided into two types of functions, public ones annotated with #[target_feature(enable = "sse2")], and private ones annotated with #[inline(always)]. I had thought (or read somewhere) that inline(always) functions assumed the CPU features of their caller and didn't need to be annotated. Either way it seems to be incompatible with target_feature. What's should this code be doing differently?

@oconnor663 oconnor663 added C-bug Category: This is a bug. regression-untriaged Untriaged performance or correctness regression. labels Jun 1, 2025
@rustbot rustbot added needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. I-prioritize Issue: Indicates that prioritization has been requested for this issue. labels Jun 1, 2025
@RalfJung

This comment has been minimized.

@RalfJung
Copy link
Member

RalfJung commented Jun 1, 2025

Uh, wait, something is very strange here. You are not using the "C" ABI it seems? It shouldn't be possible to hit this warning with the "Rust" ABI...

Oh. You are using -C target-cpu=i386. That should lead to warnings by itself. You can't disable the SSE/SSE2 target features on i686 targets.

@RalfJung
Copy link
Member

RalfJung commented Jun 1, 2025

So the actual problem is this:

warning: target feature `sse2` must be enabled to ensure that the ABI of the current target can be implemented correctly
  |
  = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
  = note: for more information, see issue #116344 <https://github.com/rust-lang/rust/issues/116344>

This warning is emitted so early it's not affected by -D warnings.

That also explains why you only started seeing this recently.

The "good" news is that #141309 will make the errors go away.

But the warning I just quoted will stay, and we do plan to make it a hard error eventually. Building code without SSE2 should use an i586 target, which are generally lower-tier reflecting the fact that our support for such CPUs is not great (not least because LLVM has a long-standing soundness issue for such targets caused by use of the x87 FPU -- there's apparently not enough people interested in such retro chips to keep them well-supported).

@saethlin saethlin added A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. C-discussion Category: Discussion or questions that doesn't represent real issues. A-ABI Area: Concerning the application binary interface (ABI) and removed C-bug Category: This is a bug. I-prioritize Issue: Indicates that prioritization has been requested for this issue. regression-untriaged Untriaged performance or correctness regression. needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. labels Jun 1, 2025
@oconnor663
Copy link
Contributor Author

oconnor663 commented Jun 1, 2025

Thanks for looking at this so closely. As you can probably tell, I'm a bit out of my depth here :)

I'm only just now understanding that this top-level warning (which you said will become an error?) has nothing really to do with my code, and actually repros for an empty project:

$ cd `mktemp -d`
$ cargo init --name example
    Creating binary (application) package
note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
$ cargo rustc --target i686-unknown-linux-gnu -- -C target-cpu=i686
   Compiling example v0.1.0 (/tmp/tmp.SPdeAQRw5g)
warning: target feature `sse2` must be enabled to ensure that the ABI of the current target can be implemented correctly
  |
  = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
  = note: for more information, see issue #116344 <https://github.com/rust-lang/rust/issues/116344>

warning: `example` (bin "example") generated 1 warning
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.28s

This happens regardless of whether the target-cpu is i386, i586, or i686. But (I think this is what you're trying to tell me above) the warning goes away if I use --target i586-unknown-linux-gnu instead of --target i686-unknown-linux-gnu. Is that the change you'd recommend for my case? (EDIT: Ah actually our CI is currently doing both, so I'd just delete the i686-unknown-linux-gnu case and leave the i586-unknown-linux-gnu case unchanged.)

For context, I added this particular test target long ago, and I can't even remember how I picked it. We might have other options for working around this issue, including:

  • Stop denying warnings in this particular corner of CI and forget about it.
    • You mentioned that this top-level one might become an error, so I'm not sure this is actually an option. Also it's not clear to me whether this warning is entirely spurious (because we do runtime feature detection before calling any of these functions) or whether it actually indicates a soundness/UB issue.
  • Assume SSE2 is supported in practice and stop trying to test target CPUs that don't support it.
    • That means our binaries aren't actually compatible with pre-pentium4 CPUs, but that's so old maybe no one on earth is trying to run new code (like the Rust blake3 crate) on those?

Just switching to --target i586-unknown-linux-gnu for this test build target, and leaving all our other build and runtime logic alone, seems preferable to any of those other options, but I want to make sure I'm not missing something.

oconnor663 added a commit to BLAKE3-team/BLAKE3 that referenced this issue Jun 1, 2025
This started emitting warnings recently, and in the future those will be
hard errors. See rust-lang/rust#141848. The
i586 target triple still works, and it's sufficient for exercising the
non-SSE2 case.

Fixes #489.
@RalfJung
Copy link
Member

RalfJung commented Jun 1, 2025

I have to answer this with a counter-question -- what are you trying to achieve by setting that target CPU?

If you truly want to support CPUs that don't have SSE2, then yes the recommendation is to switch to an i586* target. i586-unknown-linux-musl is tier 2 so you can easily use it -- but it has no target maintainer so who knows how long it'll keep that status. From what I heard even Debian will drop support for such ancient CPUs in the next cycle.

If you just want to test those codepaths, you could have a cargo feature flag or cfg option that disables runtime feature detection (or however you are doing your feature detection) and forces the use of the fallback paths.

@oconnor663
Copy link
Contributor Author

Fair question. My instinct for now is that we want to keep actually building for this ancient target, so that at least we'll find out if/when something else breaks? I've landed BLAKE3-team/BLAKE3@acf7a54, which fixes our CI.

@RalfJung
Copy link
Member

RalfJung commented Jun 1, 2025

Yeah that makes sense. If that becomes difficult at some point (e.g. if there's no tier 2 target left that supports non-SSE-compilation) you may just want to assert the presence of SSE2 and declare older chips unsupported.

If you are distributing binaries those absolutely should be built with SSE2, or else you are risking correctness issues (that would affect all systems, not just the old ones) -- that's what led to people pushing dropping support in Debian.

matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Jun 2, 2025
…nikic

x86 (32/64): go back to passing SIMD vectors by-ptr

Fixes rust-lang#139029 by partially reverting rust-lang#135408 and going back to passing SIMD vectors by-ptr on x86. Sadly, by-val confuses the LLVM inliner so much that it's not worth it...

Also fixes rust-lang#141848 by no longer actually using vector registers with the "Rust" ABI.

r? `@tgross35`
Cc `@nikic`

try-job: `test-various*`
try-job: x86_64-gnu-nopt
try-job: dist-i586-gnu-i586-i686-musl
try-job: x86_64-msvc-1
rust-bors bot added a commit that referenced this issue Jun 3, 2025
x86 (32/64): go back to passing SIMD vectors by-ptr

Fixes #139029 by partially reverting #135408 and going back to passing SIMD vectors by-ptr on x86. Sadly, by-val confuses the LLVM inliner so much that it's not worth it...

Also fixes #141848 by no longer actually using vector registers with the "Rust" ABI.

r? `@tgross35`
Cc `@nikic`

try-job: `test-various*`
try-job: dist-i586-gnu-i586-i686-musl
try-job: `x86_64-*`
try-job: `i686-*`
bors added a commit that referenced this issue Jun 3, 2025
x86 (32/64): go back to passing SIMD vectors by-ptr

Fixes #139029 by partially reverting #135408 and going back to passing SIMD vectors by-ptr on x86. Sadly, by-val confuses the LLVM inliner so much that it's not worth it...

Also fixes #141848 by no longer actually using vector registers with the "Rust" ABI.

r? `@tgross35`
Cc `@nikic`

try-job: `test-various*`
try-job: dist-i586-gnu-i586-i686-musl
try-job: `x86_64-*`
try-job: `i686-msvc*`
rust-bors bot added a commit that referenced this issue Jun 3, 2025
x86 (32/64): go back to passing SIMD vectors by-ptr

Fixes #139029 by partially reverting #135408 and going back to passing SIMD vectors by-ptr on x86. Sadly, by-val confuses the LLVM inliner so much that it's not worth it...

Also fixes #141848 by no longer actually using vector registers with the "Rust" ABI.

r? `@tgross35`
Cc `@nikic`

try-job: `test-various*`
try-job: dist-i586-gnu-i586-i686-musl
try-job: x86_64-gnu-nopt
try-job: `x86_64-msvc*`
try-job: `i686-msvc*`
@bors bors closed this as completed in ff223d3 Jun 5, 2025
github-actions bot pushed a commit to rust-lang/miri that referenced this issue Jun 5, 2025
…ngjubilee

x86 (32/64): go back to passing SIMD vectors by-ptr

Fixes rust-lang/rust#139029 by partially reverting rust-lang/rust#135408 and going back to passing SIMD vectors by-ptr on x86. Sadly, by-val confuses the LLVM inliner so much that it's not worth it...

Also fixes rust-lang/rust#141848 by no longer actually using vector registers with the "Rust" ABI.

r? `@tgross35`
Cc `@nikic`

try-job: `test-various*`
try-job: dist-i586-gnu-i586-i686-musl
try-job: x86_64-gnu-nopt
try-job: `x86_64-msvc*`
try-job: `i686-msvc*`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-ABI Area: Concerning the application binary interface (ABI) A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. C-discussion Category: Discussion or questions that doesn't represent real issues. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants