about summary refs log tree commit diff
path: root/tests/codegen
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume1.gomez@gmail.com>2024-08-12 17:09:14 +0200
committerGitHub <noreply@github.com>2024-08-12 17:09:14 +0200
commit095ca33bb6da3c1dd789eaf59461c99f4023b626 (patch)
tree383f3050fba9cdd09bcae84bad4bfd6f098ff944 /tests/codegen
parente08b80c0fb7667bdcd040761891701e576c42ec8 (diff)
parent75743dc5a057cdc0678d88523edbbf3fdd1bf901 (diff)
downloadrust-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.rs30
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);
     }
 }