From 4ee1602eab2cdc88172d4a98f927613ab64b4cf0 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Mon, 20 Jan 2025 00:00:44 -0800 Subject: Override `disjoint_or` in the LLVM backend --- compiler/rustc_codegen_llvm/src/builder.rs | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'compiler/rustc_codegen_llvm/src/builder.rs') diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 2d007416263..6e1eec4f0fc 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -421,6 +421,14 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { unchecked_umul(x, y) => LLVMBuildNUWMul, } + 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); + or + } + } + set_math_builder_methods! { fadd_fast(x, y) => (LLVMBuildFAdd, LLVMRustSetFastMath), fsub_fast(x, y) => (LLVMBuildFSub, LLVMRustSetFastMath), -- cgit 1.4.1-3-g733a5 From f46e6be1908c7ed729655c8f601548f732ef49f4 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sun, 2 Feb 2025 19:23:44 -0800 Subject: Handle the case where the `or disjoint` folds immediately to a constant --- compiler/rustc_codegen_llvm/src/builder.rs | 8 +++++++- tests/codegen/intrinsics/disjoint_bitor.rs | 12 +++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) (limited to 'compiler/rustc_codegen_llvm/src/builder.rs') 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) +} -- cgit 1.4.1-3-g733a5