diff options
| author | bors <bors@rust-lang.org> | 2023-02-19 18:17:26 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-02-19 18:17:26 +0000 |
| commit | 7aa413d59206fd511137728df3d9e0fd377429bd (patch) | |
| tree | a65a0c418211c9e35c42d07245bbf42d5f1469c1 /compiler/rustc_codegen_ssa/src | |
| parent | dc89a803d64fb6172c8406996831353bee18c3a7 (diff) | |
| parent | 9f6c1df8723504d7d468c87af02670dd0067cc7b (diff) | |
| download | rust-7aa413d59206fd511137728df3d9e0fd377429bd.tar.gz rust-7aa413d59206fd511137728df3d9e0fd377429bd.zip | |
Auto merge of #107921 - cjgillot:codegen-overflow-check, r=tmiasko
Make codegen choose whether to emit overflow checks ConstProp and DataflowConstProp currently have a specific code path not to propagate constants when they overflow. This is meant to have the correct behaviour when inlining from a crate with overflow checks (like `core`) into a crate compiled without. This PR shifts the behaviour change to the `Assert(Overflow*)` MIR terminators: if the crate is compiled without overflow checks, just skip emitting the assertions. This is already what happens with `OverflowNeg`. This allows ConstProp and DataflowConstProp to transform `CheckedBinaryOp(Add, u8::MAX, 1)` into `const (0, true)`, and let codegen ignore the `true`. The interpreter is modified to conform to this behaviour. Fixes #35310
Diffstat (limited to 'compiler/rustc_codegen_ssa/src')
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/mir/block.rs | 12 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/mir/intrinsic.rs | 25 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/mir/rvalue.rs | 9 |
3 files changed, 7 insertions, 39 deletions
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index daaa4de1a7c..e105322a0b4 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -563,11 +563,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // with #[rustc_inherit_overflow_checks] and inlined from // another crate (mostly core::num generic/#[inline] fns), // while the current crate doesn't use overflow checks. - // NOTE: Unlike binops, negation doesn't have its own - // checked operation, just a comparison with the minimum - // value, so we have to check for the assert message. - if !bx.check_overflow() { - if let AssertKind::OverflowNeg(_) = *msg { + if !bx.cx().check_overflow() { + let overflow_not_to_check = match msg { + AssertKind::OverflowNeg(..) => true, + AssertKind::Overflow(op, ..) => op.is_checkable(), + _ => false, + }; + if overflow_not_to_check { const_cond = Some(expected); } } diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs index 766dc74cbbb..7af7fc92dbc 100644 --- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs @@ -218,9 +218,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { args[1].val.unaligned_volatile_store(bx, dst); return; } - sym::add_with_overflow - | sym::sub_with_overflow - | sym::mul_with_overflow | sym::unchecked_div | sym::unchecked_rem | sym::unchecked_shl @@ -232,28 +229,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let ty = arg_tys[0]; match int_type_width_signed(ty, bx.tcx()) { Some((_width, signed)) => match name { - sym::add_with_overflow - | sym::sub_with_overflow - | sym::mul_with_overflow => { - let op = match name { - sym::add_with_overflow => OverflowOp::Add, - sym::sub_with_overflow => OverflowOp::Sub, - sym::mul_with_overflow => OverflowOp::Mul, - _ => bug!(), - }; - let (val, overflow) = - bx.checked_binop(op, ty, args[0].immediate(), args[1].immediate()); - // Convert `i1` to a `bool`, and write it to the out parameter - let val = bx.from_immediate(val); - let overflow = bx.from_immediate(overflow); - - let dest = result.project_field(bx, 0); - bx.store(val, dest.llval, dest.align); - let dest = result.project_field(bx, 1); - bx.store(overflow, dest.llval, dest.align); - - return; - } sym::exact_div => { if signed { bx.exactsdiv(args[0].immediate(), args[1].immediate()) diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 7c8d23a3329..41cd1c09a4e 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -652,15 +652,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { rhs: Bx::Value, input_ty: Ty<'tcx>, ) -> OperandValue<Bx::Value> { - // This case can currently arise only from functions marked - // with #[rustc_inherit_overflow_checks] and inlined from - // another crate (mostly core::num generic/#[inline] fns), - // while the current crate doesn't use overflow checks. - if !bx.cx().check_overflow() { - let val = self.codegen_scalar_binop(bx, op, lhs, rhs, input_ty); - return OperandValue::Pair(val, bx.cx().const_bool(false)); - } - let (val, of) = match op { // These are checked using intrinsics mir::BinOp::Add | mir::BinOp::Sub | mir::BinOp::Mul => { |
