diff options
| author | Guillaume Gomez <guillaume1.gomez@gmail.com> | 2024-08-12 17:09:14 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-08-12 17:09:14 +0200 |
| commit | 095ca33bb6da3c1dd789eaf59461c99f4023b626 (patch) | |
| tree | 383f3050fba9cdd09bcae84bad4bfd6f098ff944 /tests/codegen | |
| parent | e08b80c0fb7667bdcd040761891701e576c42ec8 (diff) | |
| parent | 75743dc5a057cdc0678d88523edbbf3fdd1bf901 (diff) | |
| download | rust-095ca33bb6da3c1dd789eaf59461c99f4023b626.tar.gz rust-095ca33bb6da3c1dd789eaf59461c99f4023b626.zip | |
Rollup merge of #128149 - RalfJung:nontemporal_store, r=jieyouxu,Amanieu,Jubilee
nontemporal_store: make sure that the intrinsic is truly just a hint The `!nontemporal` flag for stores in LLVM *sounds* like it is just a hint, but actually, it is not -- at least on x86, non-temporal stores need very special treatment by the programmer or else the Rust memory model breaks down. LLVM still treats these stores as-if they were normal stores for optimizations, which is [highly dubious](https://github.com/llvm/llvm-project/issues/64521). Let's avoid all that dubiousness by making our own non-temporal stores be truly just a hint, which is possible on some targets (e.g. ARM). On all other targets, non-temporal stores become regular stores. ~~Blocked on https://github.com/rust-lang/stdarch/pull/1541 propagating to the rustc repo, to make sure the `_mm_stream` intrinsics are unaffected by this change.~~ Fixes https://github.com/rust-lang/rust/issues/114582 Cc `@Amanieu` `@workingjubilee`
Diffstat (limited to 'tests/codegen')
| -rw-r--r-- | tests/codegen/intrinsics/nontemporal.rs | 30 |
1 files changed, 27 insertions, 3 deletions
diff --git a/tests/codegen/intrinsics/nontemporal.rs b/tests/codegen/intrinsics/nontemporal.rs index 076d6d6d9da..ff2d6296066 100644 --- a/tests/codegen/intrinsics/nontemporal.rs +++ b/tests/codegen/intrinsics/nontemporal.rs @@ -1,13 +1,37 @@ //@ compile-flags: -O +//@revisions: with_nontemporal without_nontemporal +//@[with_nontemporal] compile-flags: --target aarch64-unknown-linux-gnu +//@[with_nontemporal] needs-llvm-components: aarch64 +//@[without_nontemporal] compile-flags: --target x86_64-unknown-linux-gnu +//@[without_nontemporal] needs-llvm-components: x86 -#![feature(core_intrinsics)] +// Ensure that we *do* emit the `!nontemporal` flag on architectures where it +// is well-behaved, but do *not* emit it on architectures where it is ill-behaved. +// For more context, see <https://github.com/rust-lang/rust/issues/114582> and +// <https://github.com/llvm/llvm-project/issues/64521>. + +#![feature(no_core, lang_items, intrinsics)] +#![no_core] #![crate_type = "lib"] +#[lang = "sized"] +pub trait Sized {} +#[lang = "copy"] +pub trait Copy {} + +impl Copy for u32 {} +impl<T> Copy for *mut T {} + +extern "rust-intrinsic" { + pub fn nontemporal_store<T>(ptr: *mut T, val: T); +} + #[no_mangle] pub fn a(a: &mut u32, b: u32) { // CHECK-LABEL: define{{.*}}void @a - // CHECK: store i32 %b, ptr %a, align 4, !nontemporal + // with_nontemporal: store i32 %b, ptr %a, align 4, !nontemporal + // without_nontemporal-NOT: nontemporal unsafe { - std::intrinsics::nontemporal_store(a, b); + nontemporal_store(a, b); } } |
