Skip to content

Commit

Permalink
Don't use usub.with.overflow intrinsic
Browse files Browse the repository at this point in the history
The canonical form of a usub.with.overflow check in LLVM are
separate sub + icmp instructions, rather than a usub.with.overflow
intrinsic. Using usub.with.overflow will generally result in worse
optimization potential.

The backend will attempt to form usub.with.overflow when it comes
to actual instruction selection. This is not fully reliable, but
I believe this is a better tradeoff than using the intrinsic in
IR.

Fixes rust-lang#103285.
  • Loading branch information
nikic committed Oct 20, 2022
1 parent 4b3b731 commit 7833012
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 5 deletions.
13 changes: 8 additions & 5 deletions compiler/rustc_codegen_llvm/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -365,11 +365,14 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
Int(I64) => "llvm.ssub.with.overflow.i64",
Int(I128) => "llvm.ssub.with.overflow.i128",

Uint(U8) => "llvm.usub.with.overflow.i8",
Uint(U16) => "llvm.usub.with.overflow.i16",
Uint(U32) => "llvm.usub.with.overflow.i32",
Uint(U64) => "llvm.usub.with.overflow.i64",
Uint(U128) => "llvm.usub.with.overflow.i128",
Uint(_) => {
// Emit sub and icmp instead of llvm.usub.with.overflow. LLVM considers these
// to be the canonical form. It will attempt to reform llvm.usub.with.overflow
// in the backend if profitable.
let sub = self.sub(lhs, rhs);
let cmp = self.icmp(IntPredicate::IntULT, lhs, rhs);
return (sub, cmp);
}

_ => unreachable!(),
},
Expand Down
16 changes: 16 additions & 0 deletions src/test/codegen/issue-103285-ptr-addr-overflow-check.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// compile-flags: -O -C debug-assertions=yes

#![crate_type = "lib"]
#![feature(strict_provenance)]

#[no_mangle]
pub fn test(src: *const u8, dst: *const u8) -> usize {
// CHECK-LABEL: @test(
// CHECK-NOT: panic
let src_usize = src.addr();
let dst_usize = dst.addr();
if src_usize > dst_usize {
return src_usize - dst_usize;
}
return 0;
}

0 comments on commit 7833012

Please sign in to comment.