mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-06 04:08:40 +00:00
Make overflow flag propagation conditional
This commit is contained in:
parent
1dde908fae
commit
be9013f02b
@ -7,7 +7,7 @@ use rustc_mir_dataflow::value_analysis::{
|
|||||||
Map, ProjElem, State, ValueAnalysis, ValueOrPlace, ValueOrPlaceOrRef,
|
Map, ProjElem, State, ValueAnalysis, ValueOrPlace, ValueOrPlaceOrRef,
|
||||||
};
|
};
|
||||||
use rustc_mir_dataflow::{lattice::FlatSet, Analysis, ResultsVisitor, SwitchIntEdgeEffects};
|
use rustc_mir_dataflow::{lattice::FlatSet, Analysis, ResultsVisitor, SwitchIntEdgeEffects};
|
||||||
use rustc_span::DUMMY_SP;
|
use rustc_span::{sym, DUMMY_SP};
|
||||||
|
|
||||||
use crate::MirPass;
|
use crate::MirPass;
|
||||||
|
|
||||||
@ -38,6 +38,7 @@ struct ConstAnalysis<'tcx> {
|
|||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
ecx: InterpCx<'tcx, 'tcx, DummyMachine>,
|
ecx: InterpCx<'tcx, 'tcx, DummyMachine>,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
propagate_overflow: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'tcx> {
|
impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'tcx> {
|
||||||
@ -72,7 +73,11 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'tcx> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if value_target.is_some() || overflow_target.is_some() {
|
if value_target.is_some() || overflow_target.is_some() {
|
||||||
let (val, overflow) = self.binary_op(state, *op, left, right);
|
let (val, mut overflow) = self.binary_op(state, *op, left, right);
|
||||||
|
|
||||||
|
if !self.propagate_overflow {
|
||||||
|
overflow = FlatSet::Top;
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(value_target) = value_target {
|
if let Some(value_target) = value_target {
|
||||||
state.assign_idx(value_target, ValueOrPlaceOrRef::Value(val), self.map());
|
state.assign_idx(value_target, ValueOrPlaceOrRef::Value(val), self.map());
|
||||||
@ -202,11 +207,20 @@ impl<'tcx> std::fmt::Debug for ScalarTy<'tcx> {
|
|||||||
|
|
||||||
impl<'tcx> ConstAnalysis<'tcx> {
|
impl<'tcx> ConstAnalysis<'tcx> {
|
||||||
pub fn new(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, map: Map) -> Self {
|
pub fn new(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, map: Map) -> Self {
|
||||||
|
// It can happen that overflow will be detected even though overflow checks are disabled.
|
||||||
|
// This is caused by inlining functions that have #[rustc_inherit_overflow_checks]. Such
|
||||||
|
// overflows must not be propagated if `-C overflow-checks=off`. Also, if the function we
|
||||||
|
// are optimizing here has #[rustc_inherit_overflow_checks], the overflow checks may
|
||||||
|
// actually not be triggered by the consuming crate, so we have to ignore them too.
|
||||||
|
// Related to https://github.com/rust-lang/rust/issues/35310.
|
||||||
|
let propagate_overflow = tcx.sess.overflow_checks()
|
||||||
|
&& !tcx.has_attr(body.source.def_id(), sym::rustc_inherit_overflow_checks);
|
||||||
Self {
|
Self {
|
||||||
map,
|
map,
|
||||||
tcx,
|
tcx,
|
||||||
ecx: InterpCx::new(tcx, DUMMY_SP, ty::ParamEnv::empty(), DummyMachine),
|
ecx: InterpCx::new(tcx, DUMMY_SP, ty::ParamEnv::empty(), DummyMachine),
|
||||||
param_env: tcx.param_env(body.source.def_id()),
|
param_env: tcx.param_env(body.source.def_id()),
|
||||||
|
propagate_overflow,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,45 @@
|
|||||||
|
- // MIR for `main` before DataflowConstProp
|
||||||
|
+ // MIR for `main` after DataflowConstProp
|
||||||
|
|
||||||
|
fn main() -> () {
|
||||||
|
let mut _0: (); // return place in scope 0 at $DIR/inherit_overflow_checks_use.rs:+0:11: +0:11
|
||||||
|
let mut _1: u8; // in scope 0 at $DIR/inherit_overflow_checks_use.rs:+3:13: +3:47
|
||||||
|
let mut _2: u8; // in scope 0 at $DIR/inherit_overflow_checks_use.rs:+3:13: +3:47
|
||||||
|
let mut _3: u8; // in scope 0 at $DIR/inherit_overflow_checks_use.rs:+3:13: +3:47
|
||||||
|
scope 1 {
|
||||||
|
}
|
||||||
|
scope 2 (inlined <u8 as Add>::add) { // at $DIR/inherit_overflow_checks_use.rs:7:13: 7:47
|
||||||
|
debug self => _2; // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
|
||||||
|
debug other => _3; // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
|
||||||
|
let mut _4: u8; // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
|
||||||
|
let mut _5: u8; // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
|
||||||
|
let mut _6: (u8, bool); // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
|
||||||
|
}
|
||||||
|
|
||||||
|
bb0: {
|
||||||
|
StorageLive(_1); // scope 0 at $DIR/inherit_overflow_checks_use.rs:+3:13: +3:47
|
||||||
|
StorageLive(_2); // scope 0 at $DIR/inherit_overflow_checks_use.rs:+3:13: +3:47
|
||||||
|
_2 = const u8::MAX; // scope 0 at $DIR/inherit_overflow_checks_use.rs:+3:13: +3:47
|
||||||
|
StorageLive(_3); // scope 0 at $DIR/inherit_overflow_checks_use.rs:+3:13: +3:47
|
||||||
|
_3 = const 1_u8; // scope 0 at $DIR/inherit_overflow_checks_use.rs:+3:13: +3:47
|
||||||
|
StorageLive(_4); // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
|
||||||
|
_4 = const u8::MAX; // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
|
||||||
|
StorageLive(_5); // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
|
||||||
|
_5 = const 1_u8; // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
|
||||||
|
_6 = CheckedAdd(const u8::MAX, const 1_u8); // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
|
||||||
|
assert(!move (_6.1: bool), "attempt to compute `{} + {}`, which would overflow", const u8::MAX, const 1_u8) -> bb1; // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
|
||||||
|
}
|
||||||
|
|
||||||
|
bb1: {
|
||||||
|
- _1 = move (_6.0: u8); // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
|
||||||
|
+ _1 = const 0_u8; // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
|
||||||
|
StorageDead(_5); // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
|
||||||
|
StorageDead(_4); // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
|
||||||
|
StorageDead(_3); // scope 0 at $DIR/inherit_overflow_checks_use.rs:+3:13: +3:47
|
||||||
|
StorageDead(_2); // scope 0 at $DIR/inherit_overflow_checks_use.rs:+3:13: +3:47
|
||||||
|
StorageDead(_1); // scope 0 at $DIR/inherit_overflow_checks_use.rs:+3:47: +3:48
|
||||||
|
nop; // scope 0 at $DIR/inherit_overflow_checks_use.rs:+0:11: +4:2
|
||||||
|
return; // scope 0 at $DIR/inherit_overflow_checks_use.rs:+4:2: +4:2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
|||||||
|
// compile-flags: -C overflow-checks=off
|
||||||
|
|
||||||
|
// EMIT_MIR inherit_overflow_checks_use.main.DataflowConstProp.diff
|
||||||
|
fn main() {
|
||||||
|
// After inlining, this will contain a `CheckedBinaryOp`. The overflow
|
||||||
|
// must be ignored by the constant propagation to avoid triggering a panic.
|
||||||
|
let _ = <u8 as std::ops::Add>::add(255, 1);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user