about summary refs log tree commit diff
path: root/compiler/rustc_codegen_llvm/src/builder.rs
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-08-12 16:31:22 +0000
committerbors <bors@rust-lang.org>2024-08-12 16:31:22 +0000
commit91376f416222a238227c84a848d168835ede2cc3 (patch)
tree0dc7b9f6c09c2de39e702cb4751563c12b254835 /compiler/rustc_codegen_llvm/src/builder.rs
parente08b80c0fb7667bdcd040761891701e576c42ec8 (diff)
parent99a785d62d8414e5db435f4e699eabd185257d49 (diff)
downloadrust-91376f416222a238227c84a848d168835ede2cc3.tar.gz
rust-91376f416222a238227c84a848d168835ede2cc3.zip
Auto merge of #129008 - GuillaumeGomez:rollup-6citttb, r=GuillaumeGomez
Rollup of 10 pull requests

Successful merges:

 - #128149 (nontemporal_store: make sure that the intrinsic is truly just a hint)
 - #128394 (Unify run button display with "copy code" button and with mdbook buttons)
 - #128537 (const vector passed through to codegen)
 - #128632 (std: do not overwrite style in `get_backtrace_style`)
 - #128878 (Slightly refactor `Flags` in bootstrap)
 - #128886 (Get rid of some `#[allow(rustc::untranslatable_diagnostic)]`)
 - #128929 (Fix codegen-units tests that were disabled 8 years ago)
 - #128937 (Fix warnings in rmake tests on `x86_64-unknown-linux-gnu`)
 - #128978 (Use `assert_matches` around the compiler more)
 - #128994 (Fix bug in `Parser::look_ahead`.)

r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'compiler/rustc_codegen_llvm/src/builder.rs')
-rw-r--r--compiler/rustc_codegen_llvm/src/builder.rs33
1 files changed, 26 insertions, 7 deletions
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index 0f44c5dba5e..cc081f29e12 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -728,13 +728,32 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
                 llvm::LLVMSetVolatile(store, llvm::True);
             }
             if flags.contains(MemFlags::NONTEMPORAL) {
-                // According to LLVM [1] building a nontemporal store must
-                // *always* point to a metadata value of the integer 1.
-                //
-                // [1]: https://llvm.org/docs/LangRef.html#store-instruction
-                let one = self.cx.const_i32(1);
-                let node = llvm::LLVMMDNodeInContext(self.cx.llcx, &one, 1);
-                llvm::LLVMSetMetadata(store, llvm::MD_nontemporal as c_uint, node);
+                // Make sure that the current target architectures supports "sane" non-temporal
+                // stores, i.e., non-temporal stores that are equivalent to regular stores except
+                // for performance. LLVM doesn't seem to care about this, and will happily treat
+                // `!nontemporal` stores as-if they were normal stores (for reordering optimizations
+                // etc) even on x86, despite later lowering them to MOVNT which do *not* behave like
+                // regular stores but require special fences.
+                // So we keep a list of architectures where `!nontemporal` is known to be truly just
+                // a hint, and use regular stores everywhere else.
+                // (In the future, we could alternatively ensure that an sfence gets emitted after a sequence of movnt
+                // before any kind of synchronizing operation. But it's not clear how to do that with LLVM.)
+                // For more context, see <https://github.com/rust-lang/rust/issues/114582> and
+                // <https://github.com/llvm/llvm-project/issues/64521>.
+                const WELL_BEHAVED_NONTEMPORAL_ARCHS: &[&str] =
+                    &["aarch64", "arm", "riscv32", "riscv64"];
+
+                let use_nontemporal =
+                    WELL_BEHAVED_NONTEMPORAL_ARCHS.contains(&&*self.cx.tcx.sess.target.arch);
+                if use_nontemporal {
+                    // According to LLVM [1] building a nontemporal store must
+                    // *always* point to a metadata value of the integer 1.
+                    //
+                    // [1]: https://llvm.org/docs/LangRef.html#store-instruction
+                    let one = self.cx.const_i32(1);
+                    let node = llvm::LLVMMDNodeInContext(self.cx.llcx, &one, 1);
+                    llvm::LLVMSetMetadata(store, llvm::MD_nontemporal as c_uint, node);
+                }
             }
             store
         }