Skip to content

Commit 68e4c3c

Browse files
committed
Override disjoint_or in the LLVM backend
1 parent 2332998 commit 68e4c3c

File tree

6 files changed

+54
-0
lines changed

6 files changed

+54
-0
lines changed

compiler/rustc_codegen_llvm/src/builder.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,14 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
313313
unchecked_umul(x, y) => LLVMBuildNUWMul,
314314
}
315315

316+
fn or_disjoint(&mut self, a: &'ll Value, b: &'ll Value) -> &'ll Value {
317+
unsafe {
318+
let or = llvm::LLVMBuildOr(self.llbuilder, a, b, UNNAMED);
319+
llvm::LLVMSetIsDisjoint(or, True);
320+
or
321+
}
322+
}
323+
316324
set_math_builder_methods! {
317325
fadd_fast(x, y) => (LLVMBuildFAdd, LLVMRustSetFastMath),
318326
fsub_fast(x, y) => (LLVMBuildFSub, LLVMRustSetFastMath),

compiler/rustc_codegen_llvm/src/llvm/ffi.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1288,6 +1288,9 @@ unsafe extern "C" {
12881288
pub fn LLVMBuildFNeg<'a>(B: &Builder<'a>, V: &'a Value, Name: *const c_char) -> &'a Value;
12891289
pub fn LLVMBuildNot<'a>(B: &Builder<'a>, V: &'a Value, Name: *const c_char) -> &'a Value;
12901290

1291+
// Extra flags on arithmetic
1292+
pub fn LLVMSetIsDisjoint(Instr: &Value, IsDisjoint: Bool);
1293+
12911294
// Memory
12921295
pub fn LLVMBuildAlloca<'a>(B: &Builder<'a>, Ty: &'a Type, Name: *const c_char) -> &'a Value;
12931296
pub fn LLVMBuildArrayAlloca<'a>(

compiler/rustc_codegen_ssa/src/mir/intrinsic.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
225225
args[1].val.unaligned_volatile_store(bx, dst);
226226
return Ok(());
227227
}
228+
sym::disjoint_bitor => {
229+
let a = args[0].immediate();
230+
let b = args[1].immediate();
231+
bx.or_disjoint(a, b)
232+
}
228233
sym::exact_div => {
229234
let ty = arg_tys[0];
230235
match int_type_width_signed(ty, bx.tcx()) {

compiler/rustc_codegen_ssa/src/traits/builder.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,11 @@ pub trait BuilderMethods<'a, 'tcx>:
167167
fn unchecked_umul(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
168168
fn and(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
169169
fn or(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
170+
/// Defaults to [`Self::or`], but guarantees `(lhs & rhs) == 0` so some backends
171+
/// can emit something more helpful for optimizations.
172+
fn or_disjoint(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
173+
self.or(lhs, rhs)
174+
}
170175
fn xor(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
171176
fn neg(&mut self, v: Self::Value) -> Self::Value;
172177
fn fneg(&mut self, v: Self::Value) -> Self::Value;

tests/codegen/bigint-helpers.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//@ compile-flags: -C opt-level=3
2+
3+
#![crate_type = "lib"]
4+
#![feature(bigint_helper_methods)]
5+
6+
// CHECK-LABEL: @u32_carrying_add
7+
#[no_mangle]
8+
pub fn u32_carrying_add(a: u32, b: u32, c: bool) -> (u32, bool) {
9+
// CHECK: @llvm.uadd.with.overflow.i32
10+
// CHECK: @llvm.uadd.with.overflow.i32
11+
// CHECK: or disjoint i1
12+
u32::carrying_add(a, b, c)
13+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//@ compile-flags: -C no-prepopulate-passes
2+
3+
#![crate_type = "lib"]
4+
#![feature(core_intrinsics)]
5+
6+
use std::intrinsics::disjoint_bitor;
7+
8+
// CHECK-LABEL: @disjoint_bitor_signed
9+
#[no_mangle]
10+
pub unsafe fn disjoint_bitor_signed(x: i32, y: i32) -> i32 {
11+
// CHECK: or disjoint i32 %x, %y
12+
disjoint_bitor(x, y)
13+
}
14+
15+
// CHECK-LABEL: @disjoint_bitor_unsigned
16+
#[no_mangle]
17+
pub unsafe fn disjoint_bitor_unsigned(x: u64, y: u64) -> u64 {
18+
// CHECK: or disjoint i64 %x, %y
19+
disjoint_bitor(x, y)
20+
}

0 commit comments

Comments
 (0)