about summary refs log tree commit diff
diff options
context:
space:
mode:
authorScott McMurray <scottmcm@users.noreply.github.com>2025-02-02 19:23:44 -0800
committerScott McMurray <scottmcm@users.noreply.github.com>2025-02-02 21:04:10 -0800
commitf46e6be1908c7ed729655c8f601548f732ef49f4 (patch)
tree5d070451c3664dedadbb74a0f3b0cbcafdaef473
parent5e6ae8bb5c884deea85c6f18cfba79fe48ccafa0 (diff)
downloadrust-f46e6be1908c7ed729655c8f601548f732ef49f4.tar.gz
rust-f46e6be1908c7ed729655c8f601548f732ef49f4.zip
Handle the case where the `or disjoint` folds immediately to a constant
-rw-r--r--compiler/rustc_codegen_llvm/src/builder.rs8
-rw-r--r--tests/codegen/intrinsics/disjoint_bitor.rs12
2 files changed, 18 insertions, 2 deletions
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index 6e1eec4f0fc..264d43c6d46 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -424,7 +424,13 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
     fn or_disjoint(&mut self, a: &'ll Value, b: &'ll Value) -> &'ll Value {
         unsafe {
             let or = llvm::LLVMBuildOr(self.llbuilder, a, b, UNNAMED);
-            llvm::LLVMSetIsDisjoint(or, True);
+
+            // If a and b are both values, then `or` is a value, rather than
+            // an instruction, so we need to check before setting the flag.
+            // (See also `LLVMBuildNUWNeg` which also needs a check.)
+            if llvm::LLVMIsAInstruction(or).is_some() {
+                llvm::LLVMSetIsDisjoint(or, True);
+            }
             or
         }
     }
diff --git a/tests/codegen/intrinsics/disjoint_bitor.rs b/tests/codegen/intrinsics/disjoint_bitor.rs
index be9954507b3..fc45439ee0b 100644
--- a/tests/codegen/intrinsics/disjoint_bitor.rs
+++ b/tests/codegen/intrinsics/disjoint_bitor.rs
@@ -1,4 +1,4 @@
-//@ compile-flags: -C no-prepopulate-passes
+//@ compile-flags: -C no-prepopulate-passes -Z mir-opt-level=0
 
 #![crate_type = "lib"]
 #![feature(core_intrinsics)]
@@ -18,3 +18,13 @@ pub unsafe fn disjoint_bitor_unsigned(x: u64, y: u64) -> u64 {
     // CHECK: or disjoint i64 %x, %y
     disjoint_bitor(x, y)
 }
+
+// CHECK-LABEL: @disjoint_bitor_literal
+#[no_mangle]
+pub unsafe fn disjoint_bitor_literal() -> u8 {
+    // This is a separate check because even without any passes,
+    // LLVM will fold so it's not an instruction, which can assert in LLVM.
+
+    // CHECK: store i8 3
+    disjoint_bitor(1, 2)
+}