diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index fca43a0d86ddd..9cb36ce7f1890 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -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!(), }, diff --git a/src/test/codegen/issue-103285-ptr-addr-overflow-check.rs b/src/test/codegen/issue-103285-ptr-addr-overflow-check.rs new file mode 100644 index 0000000000000..a3499babea21b --- /dev/null +++ b/src/test/codegen/issue-103285-ptr-addr-overflow-check.rs @@ -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; +}