diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 7e5f8018dfc42..894b5aa5caedf 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1902,6 +1902,43 @@ impl<'tcx> Place<'tcx> { (base, proj) }) } + + /// Checks if the places may overlap. + /// + /// The analysis is conservative. Returning `false` indicates that the places definitely do not + /// overlap; returning `true` does not mean they necessarily do. + #[inline] + pub fn may_overlap(self, other: Place<'tcx>) -> bool { + if self.is_indirect() || other.is_indirect() { + return true; + } + + if self.local != other.local { + return false; + } + + for (p1, p2) in self.projection.iter().zip(other.projection.iter()) { + match (p1, p2) { + (ProjectionElem::Field(f1, _), ProjectionElem::Field(f2, _)) if f1 != f2 => { + return false; + } + ( + ProjectionElem::ConstantIndex { offset: o1, from_end: e1, .. }, + ProjectionElem::ConstantIndex { offset: o2, from_end: e2, .. }, + ) => { + if e1 == e2 && o1 != o2 { + return false; + } + } + // There are other conditions we could check for here with slicing and such, but + // those checks are error-prone and its unclear if that would really get us much + (a, b) if a != b => return true, + (_, _) => (), + } + } + + return true; + } } impl From for Place<'_> { diff --git a/compiler/rustc_mir_transform/src/dead_store_elimination.rs b/compiler/rustc_mir_transform/src/dead_store_elimination.rs new file mode 100644 index 0000000000000..a9d446e14bf50 --- /dev/null +++ b/compiler/rustc_mir_transform/src/dead_store_elimination.rs @@ -0,0 +1,187 @@ +use rustc_middle::{ + mir::*, + ty::{List, TyCtxt}, +}; +use smallvec::SmallVec; + +/// Loops over basic blocks and calls [`simple_local_dse`] for each, see there for more. +pub struct SimpleLocalDse; + +impl<'tcx> MirPass<'tcx> for SimpleLocalDse { + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + sess.mir_opt_level() >= 2 + } + + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + for bb in body.basic_blocks_mut() { + simple_local_dse(bb, tcx); + } + } +} + +/// This performs a very basic form of dead store elimintation on the basic block. +/// +/// Essentially, we loop over the statements in reverse order. As we go, we maintain a list of +/// places that will be written to before they are used again. If we find a write to any such place, +/// we can replace it with a nop. Full details and arguments for correctness are in inline comments. +#[instrument(level = "debug", skip(tcx))] +pub fn simple_local_dse<'tcx>(bb: &mut BasicBlockData<'tcx>, tcx: TyCtxt<'tcx>) { + let mut overwritten: Vec> = Vec::new(); + // We iterate backwards over the statements in the basic block + for stmt in bb.statements.iter_mut().rev() { + // For each statement, compute where it reads from and writes to + let data = compute_statement_data(stmt, tcx); + // If the statement definitely derefs something, then assume any write that is visible now + // is not dead + let Some(data) = data else { + overwritten.clear(); + continue; + }; + if let Some(p) = data.stored { + // If the statement writes somewhere, and we know that a "parent" place is over-written + // later, the statement can be optimized out. This uses the assumptions that 1) `p` does + // not include any `Deref`s (this is enforced in `compute_statement_data`) and that 2) + // this write is the entirety of the statements behavior, ie that knowing that the write + // is dead lets us remove the statement entirely. + + // It may be possible to make this smarter. For example, if a type with no padding has + // all of its fields overwritten, then the whole type can be considered overwritten. + // Leave that for the future though. + if overwritten + .iter() + .copied() + .any(|dp| dp.local == p.local && p.projection[..].starts_with(&dp.projection[..])) + { + debug!("Optimizing {:?}", stmt); + stmt.make_nop(); + continue; + } + + // If we get here, this write can't be optimized out. We may now be able to add it to + // `overwritten`, but to do that, we need to check that the place does not contain any + // non-constant indexing. The values of such indexes may change, which may make the part + // of memory that the place points to inconsistent. + if p.projection.iter().all(|x| !matches!(x, ProjectionElem::Index(_))) { + overwritten.push(p); + } + } + + // We need to kick elements out of `overwritten` if their value was used. + overwritten.retain(|p1| data.loaded.iter().copied().all(|p2| !p1.may_overlap(p2))) + } +} + +struct StatementData<'tcx> { + /// The place that this statement writes to, or `None`, if it doesn't write anywhere. If this is + /// `Some`, it is assumed that the corresponding write represents the + /// entirety of the statement's behavior. + stored: Option>, + /// The places that this statement loads from. If `stored` is `Some(_)`, then it is assumed that + /// these loads are conditioned on the above store not being optimized out. + loaded: SmallVec<[Place<'tcx>; 8]>, +} + +/// Returns information about how one statement interacts with memory. +/// +/// Returning `None` indicates that execution of this statement accesses memory not inside a local. +fn compute_statement_data<'tcx>( + stmt: &Statement<'tcx>, + tcx: TyCtxt<'tcx>, +) -> Option> { + let mut loaded = SmallVec::new(); + + // Adds a `load` to the `loaded` list. This also adds in any locals that are used as indexes. + let mut add_load = |p: Place<'tcx>| { + loaded.push(p); + for elem in p.projection.iter() { + if let ProjectionElem::Index(i) = elem { + loaded.push(Place { local: i, projection: List::empty() }); + } + } + }; + // Adds the address of `p` to the loaded list. + let add_address_of = |p: Place<'tcx>, loaded: &mut SmallVec<_>| { + // First of all, computing the address unconditionally uses any `Index`s that appear in the + // place. + for elem in p.projection.iter() { + if let ProjectionElem::Index(i) = elem { + loaded.push(Place { local: i, projection: List::empty() }); + } + } + + // Now, we additionally use the place that is outside the innermost `Deref`, since that + // contains the pointer from which we're computing the address. + if let Some(i) = p.projection.iter().rposition(|x| x == ProjectionElem::Deref) { + let prefix = &p.projection[0..i]; + loaded.push(Place { local: p.local, projection: tcx.intern_place_elems(prefix) }); + }; + }; + + let mut stored = match &stmt.kind { + StatementKind::FakeRead(x) => { + add_load(x.1); + Some(x.1) + } + StatementKind::SetDiscriminant { .. } => { + // There isn't really a clear place associated with a discriminant, so we won't report one + None + } + StatementKind::StorageDead(x) => Some(Place { local: *x, projection: List::empty() }), + StatementKind::Retag(_, x) => { + add_load(**x); + Some(**x) + } + StatementKind::AscribeUserType(x, _) => { + add_load((**x).0); + Some((**x).0) + } + StatementKind::Coverage(_) | StatementKind::StorageLive(_) | StatementKind::Nop => None, + StatementKind::CopyNonOverlapping(_) => { + return None; + } + StatementKind::Assign(x) => { + let mut dest = Some(x.0); + let src = &x.1; + match src { + Rvalue::Use(op) + | Rvalue::Repeat(op, _) + | Rvalue::Cast(_, op, _) + | Rvalue::UnaryOp(_, op) + | Rvalue::ShallowInitBox(op, _) => { + op.place().map(&mut add_load); + } + Rvalue::Len(p) | Rvalue::Discriminant(p) => { + add_load(*p); + } + Rvalue::Ref(_, _, p) | Rvalue::AddressOf(_, p) => { + add_address_of(*p, &mut loaded); + } + Rvalue::BinaryOp(_, x) | Rvalue::CheckedBinaryOp(_, x) => { + x.0.place().map(&mut add_load); + x.1.place().map(&mut add_load); + } + Rvalue::Aggregate(_, v) => { + for op in v { + op.place().map(&mut add_load); + } + } + Rvalue::ThreadLocalRef(_) => { + // Creating a thread local ref has side-effects, so don't optimize that away + dest = None; + } + Rvalue::NullaryOp(..) => {} + }; + dest + } + }; + if let Some(p) = stored { + add_address_of(p, &mut loaded); + + if p.projection.iter().any(|x| x == ProjectionElem::Deref) { + // We don't reason about memory, so we cannot optimize this statement + stored = None; + } + } + + Some(StatementData { stored, loaded }) +} diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index e7d5bab8fd9d4..e22018dd6cd9c 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -49,6 +49,7 @@ mod const_debuginfo; mod const_goto; mod const_prop; mod coverage; +mod dead_store_elimination; mod deaggregator; mod deduplicate_blocks; mod dest_prop; @@ -484,6 +485,7 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { &simplify_try::SimplifyArmIdentity, &simplify_try::SimplifyBranchSame, &dest_prop::DestinationPropagation, + &dead_store_elimination::SimpleLocalDse, &o1(simplify_branches::SimplifyConstCondition::new("final")), &o1(remove_noop_landing_pads::RemoveNoopLandingPads), &o1(simplify::SimplifyCfg::new("final")), diff --git a/src/test/mir-opt/const_debuginfo.main.ConstDebugInfo.diff b/src/test/mir-opt/const_debuginfo.main.ConstDebugInfo.diff index 8714a8992d7e0..50994cd7adbff 100644 --- a/src/test/mir-opt/const_debuginfo.main.ConstDebugInfo.diff +++ b/src/test/mir-opt/const_debuginfo.main.ConstDebugInfo.diff @@ -2,46 +2,52 @@ + // MIR for `main` after ConstDebugInfo fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/const_debuginfo.rs:8:11: 8:11 - let _1: u8; // in scope 0 at $DIR/const_debuginfo.rs:9:9: 9:10 - let mut _5: u8; // in scope 0 at $DIR/const_debuginfo.rs:12:15: 12:20 - let mut _6: u8; // in scope 0 at $DIR/const_debuginfo.rs:12:15: 12:16 - let mut _7: u8; // in scope 0 at $DIR/const_debuginfo.rs:12:19: 12:20 - let mut _8: u8; // in scope 0 at $DIR/const_debuginfo.rs:12:23: 12:24 - let mut _14: u32; // in scope 0 at $DIR/const_debuginfo.rs:21:13: 21:16 - let mut _15: u32; // in scope 0 at $DIR/const_debuginfo.rs:21:19: 21:22 + let mut _0: (); // return place in scope 0 at $DIR/const_debuginfo.rs:10:11: 10:11 + let _1: u8; // in scope 0 at $DIR/const_debuginfo.rs:11:9: 11:10 + let mut _5: u8; // in scope 0 at $DIR/const_debuginfo.rs:14:15: 14:20 + let mut _6: u8; // in scope 0 at $DIR/const_debuginfo.rs:14:15: 14:16 + let mut _7: u8; // in scope 0 at $DIR/const_debuginfo.rs:14:19: 14:20 + let mut _8: u8; // in scope 0 at $DIR/const_debuginfo.rs:14:23: 14:24 + let mut _14: u32; // in scope 0 at $DIR/const_debuginfo.rs:23:13: 23:16 + let mut _15: u32; // in scope 0 at $DIR/const_debuginfo.rs:23:19: 23:22 + let _16: (); // in scope 0 at $DIR/const_debuginfo.rs:25:5: 25:30 + let mut _17: (); // in scope 0 at $DIR/const_debuginfo.rs:25:27: 25:29 scope 1 { -- debug x => _1; // in scope 1 at $DIR/const_debuginfo.rs:9:9: 9:10 -+ debug x => const 1_u8; // in scope 1 at $DIR/const_debuginfo.rs:9:9: 9:10 - let _2: u8; // in scope 1 at $DIR/const_debuginfo.rs:10:9: 10:10 +- debug x => _1; // in scope 1 at $DIR/const_debuginfo.rs:11:9: 11:10 ++ debug x => const 1_u8; // in scope 1 at $DIR/const_debuginfo.rs:11:9: 11:10 + let _2: u8; // in scope 1 at $DIR/const_debuginfo.rs:12:9: 12:10 scope 2 { -- debug y => _2; // in scope 2 at $DIR/const_debuginfo.rs:10:9: 10:10 -+ debug y => const 2_u8; // in scope 2 at $DIR/const_debuginfo.rs:10:9: 10:10 - let _3: u8; // in scope 2 at $DIR/const_debuginfo.rs:11:9: 11:10 +- debug y => _2; // in scope 2 at $DIR/const_debuginfo.rs:12:9: 12:10 ++ debug y => const 2_u8; // in scope 2 at $DIR/const_debuginfo.rs:12:9: 12:10 + let _3: u8; // in scope 2 at $DIR/const_debuginfo.rs:13:9: 13:10 scope 3 { -- debug z => _3; // in scope 3 at $DIR/const_debuginfo.rs:11:9: 11:10 -+ debug z => const 3_u8; // in scope 3 at $DIR/const_debuginfo.rs:11:9: 11:10 - let _4: u8; // in scope 3 at $DIR/const_debuginfo.rs:12:9: 12:12 +- debug z => _3; // in scope 3 at $DIR/const_debuginfo.rs:13:9: 13:10 ++ debug z => const 3_u8; // in scope 3 at $DIR/const_debuginfo.rs:13:9: 13:10 + let _4: u8; // in scope 3 at $DIR/const_debuginfo.rs:14:9: 14:12 scope 4 { -- debug sum => _4; // in scope 4 at $DIR/const_debuginfo.rs:12:9: 12:12 -+ debug sum => const 6_u8; // in scope 4 at $DIR/const_debuginfo.rs:12:9: 12:12 - let _9: &str; // in scope 4 at $DIR/const_debuginfo.rs:14:9: 14:10 +- debug sum => _4; // in scope 4 at $DIR/const_debuginfo.rs:14:9: 14:12 ++ debug sum => const 6_u8; // in scope 4 at $DIR/const_debuginfo.rs:14:9: 14:12 + let _9: &str; // in scope 4 at $DIR/const_debuginfo.rs:16:9: 16:10 scope 5 { -- debug s => _9; // in scope 5 at $DIR/const_debuginfo.rs:14:9: 14:10 -+ debug s => const "hello, world!"; // in scope 5 at $DIR/const_debuginfo.rs:14:9: 14:10 - let _10: (bool, bool, u32); // in scope 5 at $DIR/const_debuginfo.rs:16:9: 16:10 +- debug s => _9; // in scope 5 at $DIR/const_debuginfo.rs:16:9: 16:10 ++ debug s => const "hello, world!"; // in scope 5 at $DIR/const_debuginfo.rs:16:9: 16:10 + let _10: (bool, bool, u32); // in scope 5 at $DIR/const_debuginfo.rs:18:9: 18:10 scope 6 { - debug f => _10; // in scope 6 at $DIR/const_debuginfo.rs:16:9: 16:10 - let _11: std::option::Option; // in scope 6 at $DIR/const_debuginfo.rs:18:9: 18:10 + debug f => _10; // in scope 6 at $DIR/const_debuginfo.rs:18:9: 18:10 + let _11: std::option::Option; // in scope 6 at $DIR/const_debuginfo.rs:20:9: 20:10 scope 7 { - debug o => _11; // in scope 7 at $DIR/const_debuginfo.rs:18:9: 18:10 - let _12: Point; // in scope 7 at $DIR/const_debuginfo.rs:20:9: 20:10 + debug o => _11; // in scope 7 at $DIR/const_debuginfo.rs:20:9: 20:10 + let _12: Point; // in scope 7 at $DIR/const_debuginfo.rs:22:9: 22:10 scope 8 { - debug p => _12; // in scope 8 at $DIR/const_debuginfo.rs:20:9: 20:10 - let _13: u32; // in scope 8 at $DIR/const_debuginfo.rs:21:9: 21:10 + debug p => _12; // in scope 8 at $DIR/const_debuginfo.rs:22:9: 22:10 + let _13: u32; // in scope 8 at $DIR/const_debuginfo.rs:23:9: 23:10 scope 9 { -- debug a => _13; // in scope 9 at $DIR/const_debuginfo.rs:21:9: 21:10 -+ debug a => const 64_u32; // in scope 9 at $DIR/const_debuginfo.rs:21:9: 21:10 +- debug a => _13; // in scope 9 at $DIR/const_debuginfo.rs:23:9: 23:10 ++ debug a => const 64_u32; // in scope 9 at $DIR/const_debuginfo.rs:23:9: 23:10 + scope 10 (inlined std::hint::black_box::<()>) { // at $DIR/const_debuginfo.rs:25:5: 25:30 + debug dummy => _17; // in scope 10 at $DIR/const_debuginfo.rs:25:5: 25:30 + let mut _18: (); // in scope 10 at $DIR/const_debuginfo.rs:25:5: 25:30 + } } } } @@ -53,62 +59,69 @@ } bb0: { - StorageLive(_1); // scope 0 at $DIR/const_debuginfo.rs:9:9: 9:10 - _1 = const 1_u8; // scope 0 at $DIR/const_debuginfo.rs:9:13: 9:16 - StorageLive(_2); // scope 1 at $DIR/const_debuginfo.rs:10:9: 10:10 - _2 = const 2_u8; // scope 1 at $DIR/const_debuginfo.rs:10:13: 10:16 - StorageLive(_3); // scope 2 at $DIR/const_debuginfo.rs:11:9: 11:10 - _3 = const 3_u8; // scope 2 at $DIR/const_debuginfo.rs:11:13: 11:16 - StorageLive(_4); // scope 3 at $DIR/const_debuginfo.rs:12:9: 12:12 - StorageLive(_5); // scope 3 at $DIR/const_debuginfo.rs:12:15: 12:20 - StorageLive(_6); // scope 3 at $DIR/const_debuginfo.rs:12:15: 12:16 - _6 = const 1_u8; // scope 3 at $DIR/const_debuginfo.rs:12:15: 12:16 - StorageLive(_7); // scope 3 at $DIR/const_debuginfo.rs:12:19: 12:20 - _7 = const 2_u8; // scope 3 at $DIR/const_debuginfo.rs:12:19: 12:20 - _5 = const 3_u8; // scope 3 at $DIR/const_debuginfo.rs:12:15: 12:20 - StorageDead(_7); // scope 3 at $DIR/const_debuginfo.rs:12:19: 12:20 - StorageDead(_6); // scope 3 at $DIR/const_debuginfo.rs:12:19: 12:20 - StorageLive(_8); // scope 3 at $DIR/const_debuginfo.rs:12:23: 12:24 - _8 = const 3_u8; // scope 3 at $DIR/const_debuginfo.rs:12:23: 12:24 - _4 = const 6_u8; // scope 3 at $DIR/const_debuginfo.rs:12:15: 12:24 - StorageDead(_8); // scope 3 at $DIR/const_debuginfo.rs:12:23: 12:24 - StorageDead(_5); // scope 3 at $DIR/const_debuginfo.rs:12:23: 12:24 - StorageLive(_9); // scope 4 at $DIR/const_debuginfo.rs:14:9: 14:10 - _9 = const "hello, world!"; // scope 4 at $DIR/const_debuginfo.rs:14:13: 14:28 + StorageLive(_1); // scope 0 at $DIR/const_debuginfo.rs:11:9: 11:10 + _1 = const 1_u8; // scope 0 at $DIR/const_debuginfo.rs:11:13: 11:16 + StorageLive(_2); // scope 1 at $DIR/const_debuginfo.rs:12:9: 12:10 + _2 = const 2_u8; // scope 1 at $DIR/const_debuginfo.rs:12:13: 12:16 + StorageLive(_3); // scope 2 at $DIR/const_debuginfo.rs:13:9: 13:10 + _3 = const 3_u8; // scope 2 at $DIR/const_debuginfo.rs:13:13: 13:16 + StorageLive(_4); // scope 3 at $DIR/const_debuginfo.rs:14:9: 14:12 + StorageLive(_5); // scope 3 at $DIR/const_debuginfo.rs:14:15: 14:20 + StorageLive(_6); // scope 3 at $DIR/const_debuginfo.rs:14:15: 14:16 + StorageLive(_7); // scope 3 at $DIR/const_debuginfo.rs:14:19: 14:20 + StorageDead(_7); // scope 3 at $DIR/const_debuginfo.rs:14:19: 14:20 + StorageDead(_6); // scope 3 at $DIR/const_debuginfo.rs:14:19: 14:20 + StorageLive(_8); // scope 3 at $DIR/const_debuginfo.rs:14:23: 14:24 + _4 = const 6_u8; // scope 3 at $DIR/const_debuginfo.rs:14:15: 14:24 + StorageDead(_8); // scope 3 at $DIR/const_debuginfo.rs:14:23: 14:24 + StorageDead(_5); // scope 3 at $DIR/const_debuginfo.rs:14:23: 14:24 + StorageLive(_9); // scope 4 at $DIR/const_debuginfo.rs:16:9: 16:10 + _9 = const "hello, world!"; // scope 4 at $DIR/const_debuginfo.rs:16:13: 16:28 // ty::Const // + ty: &str // + val: Value(Slice { data: Allocation { bytes: [104, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [8191], len: Size { raw: 13 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 13 }) // mir::Constant - // + span: $DIR/const_debuginfo.rs:14:13: 14:28 + // + span: $DIR/const_debuginfo.rs:16:13: 16:28 // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [104, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [8191], len: Size { raw: 13 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 13 }) } - StorageLive(_10); // scope 5 at $DIR/const_debuginfo.rs:16:9: 16:10 - (_10.0: bool) = const true; // scope 5 at $DIR/const_debuginfo.rs:16:13: 16:34 - (_10.1: bool) = const false; // scope 5 at $DIR/const_debuginfo.rs:16:13: 16:34 - (_10.2: u32) = const 123_u32; // scope 5 at $DIR/const_debuginfo.rs:16:13: 16:34 - StorageLive(_11); // scope 6 at $DIR/const_debuginfo.rs:18:9: 18:10 - ((_11 as Some).0: u16) = const 99_u16; // scope 6 at $DIR/const_debuginfo.rs:18:13: 18:24 - discriminant(_11) = 1; // scope 6 at $DIR/const_debuginfo.rs:18:13: 18:24 - StorageLive(_12); // scope 7 at $DIR/const_debuginfo.rs:20:9: 20:10 - (_12.0: u32) = const 32_u32; // scope 7 at $DIR/const_debuginfo.rs:20:13: 20:35 - (_12.1: u32) = const 32_u32; // scope 7 at $DIR/const_debuginfo.rs:20:13: 20:35 - StorageLive(_13); // scope 8 at $DIR/const_debuginfo.rs:21:9: 21:10 - StorageLive(_14); // scope 8 at $DIR/const_debuginfo.rs:21:13: 21:16 - _14 = const 32_u32; // scope 8 at $DIR/const_debuginfo.rs:21:13: 21:16 - StorageLive(_15); // scope 8 at $DIR/const_debuginfo.rs:21:19: 21:22 - _15 = const 32_u32; // scope 8 at $DIR/const_debuginfo.rs:21:19: 21:22 - _13 = const 64_u32; // scope 8 at $DIR/const_debuginfo.rs:21:13: 21:22 - StorageDead(_15); // scope 8 at $DIR/const_debuginfo.rs:21:21: 21:22 - StorageDead(_14); // scope 8 at $DIR/const_debuginfo.rs:21:21: 21:22 - StorageDead(_13); // scope 8 at $DIR/const_debuginfo.rs:22:1: 22:2 - StorageDead(_12); // scope 7 at $DIR/const_debuginfo.rs:22:1: 22:2 - StorageDead(_11); // scope 6 at $DIR/const_debuginfo.rs:22:1: 22:2 - StorageDead(_10); // scope 5 at $DIR/const_debuginfo.rs:22:1: 22:2 - StorageDead(_9); // scope 4 at $DIR/const_debuginfo.rs:22:1: 22:2 - StorageDead(_4); // scope 3 at $DIR/const_debuginfo.rs:22:1: 22:2 - StorageDead(_3); // scope 2 at $DIR/const_debuginfo.rs:22:1: 22:2 - StorageDead(_2); // scope 1 at $DIR/const_debuginfo.rs:22:1: 22:2 - StorageDead(_1); // scope 0 at $DIR/const_debuginfo.rs:22:1: 22:2 - return; // scope 0 at $DIR/const_debuginfo.rs:22:2: 22:2 + StorageLive(_10); // scope 5 at $DIR/const_debuginfo.rs:18:9: 18:10 + (_10.0: bool) = const true; // scope 5 at $DIR/const_debuginfo.rs:18:13: 18:34 + (_10.1: bool) = const false; // scope 5 at $DIR/const_debuginfo.rs:18:13: 18:34 + (_10.2: u32) = const 123_u32; // scope 5 at $DIR/const_debuginfo.rs:18:13: 18:34 + StorageLive(_11); // scope 6 at $DIR/const_debuginfo.rs:20:9: 20:10 + ((_11 as Some).0: u16) = const 99_u16; // scope 6 at $DIR/const_debuginfo.rs:20:13: 20:24 + discriminant(_11) = 1; // scope 6 at $DIR/const_debuginfo.rs:20:13: 20:24 + StorageLive(_12); // scope 7 at $DIR/const_debuginfo.rs:22:9: 22:10 + (_12.0: u32) = const 32_u32; // scope 7 at $DIR/const_debuginfo.rs:22:13: 22:35 + (_12.1: u32) = const 32_u32; // scope 7 at $DIR/const_debuginfo.rs:22:13: 22:35 + StorageLive(_13); // scope 8 at $DIR/const_debuginfo.rs:23:9: 23:10 + StorageLive(_14); // scope 8 at $DIR/const_debuginfo.rs:23:13: 23:16 + StorageLive(_15); // scope 8 at $DIR/const_debuginfo.rs:23:19: 23:22 + _13 = const 64_u32; // scope 8 at $DIR/const_debuginfo.rs:23:13: 23:22 + StorageDead(_15); // scope 8 at $DIR/const_debuginfo.rs:23:21: 23:22 + StorageDead(_14); // scope 8 at $DIR/const_debuginfo.rs:23:21: 23:22 + StorageLive(_16); // scope 9 at $DIR/const_debuginfo.rs:25:5: 25:30 + StorageLive(_17); // scope 9 at $DIR/const_debuginfo.rs:25:27: 25:29 + StorageLive(_18); // scope 10 at $DIR/const_debuginfo.rs:25:5: 25:30 + _16 = std::intrinsics::black_box::<()>(const ()) -> bb1; // scope 10 at $DIR/const_debuginfo.rs:25:5: 25:30 + // mir::Constant + // + span: $DIR/const_debuginfo.rs:25:5: 25:30 + // + literal: Const { ty: extern "rust-intrinsic" fn(()) {std::intrinsics::black_box::<()>}, val: Value(Scalar()) } + } + + bb1: { + StorageDead(_18); // scope 10 at $DIR/const_debuginfo.rs:25:5: 25:30 + StorageDead(_17); // scope 9 at $DIR/const_debuginfo.rs:25:29: 25:30 + StorageDead(_16); // scope 9 at $DIR/const_debuginfo.rs:25:30: 25:31 + StorageDead(_13); // scope 8 at $DIR/const_debuginfo.rs:26:1: 26:2 + StorageDead(_12); // scope 7 at $DIR/const_debuginfo.rs:26:1: 26:2 + StorageDead(_11); // scope 6 at $DIR/const_debuginfo.rs:26:1: 26:2 + StorageDead(_10); // scope 5 at $DIR/const_debuginfo.rs:26:1: 26:2 + StorageDead(_9); // scope 4 at $DIR/const_debuginfo.rs:26:1: 26:2 + StorageDead(_4); // scope 3 at $DIR/const_debuginfo.rs:26:1: 26:2 + StorageDead(_3); // scope 2 at $DIR/const_debuginfo.rs:26:1: 26:2 + StorageDead(_2); // scope 1 at $DIR/const_debuginfo.rs:26:1: 26:2 + StorageDead(_1); // scope 0 at $DIR/const_debuginfo.rs:26:1: 26:2 + return; // scope 0 at $DIR/const_debuginfo.rs:26:2: 26:2 } } diff --git a/src/test/mir-opt/const_debuginfo.rs b/src/test/mir-opt/const_debuginfo.rs index a188da3852623..b348e49da853c 100644 --- a/src/test/mir-opt/const_debuginfo.rs +++ b/src/test/mir-opt/const_debuginfo.rs @@ -1,5 +1,7 @@ // compile-flags: -C overflow-checks=no -Zunsound-mir-opts +#![feature(bench_black_box)] + struct Point { x: u32, y: u32, @@ -19,6 +21,8 @@ fn main() { let p = Point { x: 32, y: 32 }; let a = p.x + p.y; + + core::hint::black_box(()); } // EMIT_MIR const_debuginfo.main.ConstDebugInfo.diff diff --git a/src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals.after.32bit.mir b/src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals.after.32bit.mir index c6f1d86ae3a07..abc2b485bd63e 100644 --- a/src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals.after.32bit.mir +++ b/src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals.after.32bit.mir @@ -19,9 +19,7 @@ fn main() -> () { StorageLive(_1); // scope 0 at $DIR/optimizes_into_variable.rs:12:9: 12:10 _1 = const 4_i32; // scope 0 at $DIR/optimizes_into_variable.rs:12:13: 12:18 StorageLive(_2); // scope 1 at $DIR/optimizes_into_variable.rs:13:9: 13:10 - _2 = const 3_i32; // scope 1 at $DIR/optimizes_into_variable.rs:13:13: 13:34 StorageLive(_3); // scope 2 at $DIR/optimizes_into_variable.rs:14:9: 14:10 - _3 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:14:13: 14:38 StorageDead(_3); // scope 2 at $DIR/optimizes_into_variable.rs:15:1: 15:2 StorageDead(_2); // scope 1 at $DIR/optimizes_into_variable.rs:15:1: 15:2 StorageDead(_1); // scope 0 at $DIR/optimizes_into_variable.rs:15:1: 15:2 diff --git a/src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals.after.64bit.mir b/src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals.after.64bit.mir index c6f1d86ae3a07..abc2b485bd63e 100644 --- a/src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals.after.64bit.mir +++ b/src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals.after.64bit.mir @@ -19,9 +19,7 @@ fn main() -> () { StorageLive(_1); // scope 0 at $DIR/optimizes_into_variable.rs:12:9: 12:10 _1 = const 4_i32; // scope 0 at $DIR/optimizes_into_variable.rs:12:13: 12:18 StorageLive(_2); // scope 1 at $DIR/optimizes_into_variable.rs:13:9: 13:10 - _2 = const 3_i32; // scope 1 at $DIR/optimizes_into_variable.rs:13:13: 13:34 StorageLive(_3); // scope 2 at $DIR/optimizes_into_variable.rs:14:9: 14:10 - _3 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:14:13: 14:38 StorageDead(_3); // scope 2 at $DIR/optimizes_into_variable.rs:15:1: 15:2 StorageDead(_2); // scope 1 at $DIR/optimizes_into_variable.rs:15:1: 15:2 StorageDead(_1); // scope 0 at $DIR/optimizes_into_variable.rs:15:1: 15:2 diff --git a/src/test/mir-opt/dead_store_elimination.coverage.SimpleLocalDse.diff b/src/test/mir-opt/dead_store_elimination.coverage.SimpleLocalDse.diff new file mode 100644 index 0000000000000..20b54b5483e4a --- /dev/null +++ b/src/test/mir-opt/dead_store_elimination.coverage.SimpleLocalDse.diff @@ -0,0 +1,173 @@ +- // MIR for `coverage` before SimpleLocalDse ++ // MIR for `coverage` after SimpleLocalDse + + fn coverage() -> () { + let mut _0: (); // return place in scope 0 at $DIR/dead_store_elimination.rs:6:19: 6:19 + let mut _1: i32; // in scope 0 at $DIR/dead_store_elimination.rs:7:9: 7:14 + let _2: (); // in scope 0 at $DIR/dead_store_elimination.rs:10:5: 10:12 + let mut _3: i32; // in scope 0 at $DIR/dead_store_elimination.rs:10:10: 10:11 + let mut _6: i32; // in scope 0 at $DIR/dead_store_elimination.rs:13:22: 13:24 + let mut _7: i32; // in scope 0 at $DIR/dead_store_elimination.rs:14:9: 14:11 + let _8: (); // in scope 0 at $DIR/dead_store_elimination.rs:16:5: 16:12 + let mut _9: i32; // in scope 0 at $DIR/dead_store_elimination.rs:16:10: 16:11 + let _11: (); // in scope 0 at $DIR/dead_store_elimination.rs:23:5: 23:12 + let mut _12: coverage::S; // in scope 0 at $DIR/dead_store_elimination.rs:23:10: 23:11 + let mut _14: coverage::S; // in scope 0 at $DIR/dead_store_elimination.rs:27:9: 27:14 + let _15: (); // in scope 0 at $DIR/dead_store_elimination.rs:28:5: 28:12 + let mut _16: coverage::S; // in scope 0 at $DIR/dead_store_elimination.rs:28:10: 28:11 + scope 1 { + debug x => _1; // in scope 1 at $DIR/dead_store_elimination.rs:7:9: 7:14 + let mut _4: i32; // in scope 1 at $DIR/dead_store_elimination.rs:12:9: 12:14 + scope 2 { + debug x => _4; // in scope 2 at $DIR/dead_store_elimination.rs:12:9: 12:14 + let mut _5: &mut i32; // in scope 2 at $DIR/dead_store_elimination.rs:13:9: 13:14 + scope 3 { + debug r => _5; // in scope 3 at $DIR/dead_store_elimination.rs:13:9: 13:14 + let mut _10: coverage::S; // in scope 3 at $DIR/dead_store_elimination.rs:20:9: 20:14 + scope 4 { + debug s => _10; // in scope 4 at $DIR/dead_store_elimination.rs:20:9: 20:14 + let mut _13: coverage::S; // in scope 4 at $DIR/dead_store_elimination.rs:25:9: 25:14 + scope 5 { + debug s => _13; // in scope 5 at $DIR/dead_store_elimination.rs:25:9: 25:14 + let mut _17: i32; // in scope 5 at $DIR/dead_store_elimination.rs:30:9: 30:14 + scope 6 { + debug x => _17; // in scope 6 at $DIR/dead_store_elimination.rs:30:9: 30:14 + } + } + } + } + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/dead_store_elimination.rs:7:9: 7:14 +- _1 = const 0_i32; // scope 0 at $DIR/dead_store_elimination.rs:7:17: 7:18 +- _1 = const 1_i32; // scope 1 at $DIR/dead_store_elimination.rs:8:5: 8:10 ++ nop; // scope 0 at $DIR/dead_store_elimination.rs:7:17: 7:18 ++ nop; // scope 1 at $DIR/dead_store_elimination.rs:8:5: 8:10 + _1 = const 2_i32; // scope 1 at $DIR/dead_store_elimination.rs:9:5: 9:10 + StorageLive(_2); // scope 1 at $DIR/dead_store_elimination.rs:10:5: 10:12 + StorageLive(_3); // scope 1 at $DIR/dead_store_elimination.rs:10:10: 10:11 + _3 = const 2_i32; // scope 1 at $DIR/dead_store_elimination.rs:10:10: 10:11 + _2 = read::(const 2_i32) -> bb1; // scope 1 at $DIR/dead_store_elimination.rs:10:5: 10:12 + // mir::Constant + // + span: $DIR/dead_store_elimination.rs:10:5: 10:9 + // + literal: Const { ty: fn(i32) {read::}, val: Value(Scalar()) } + } + + bb1: { + StorageDead(_3); // scope 1 at $DIR/dead_store_elimination.rs:10:11: 10:12 + StorageDead(_2); // scope 1 at $DIR/dead_store_elimination.rs:10:12: 10:13 + StorageLive(_4); // scope 1 at $DIR/dead_store_elimination.rs:12:9: 12:14 +- _4 = const 10_i32; // scope 1 at $DIR/dead_store_elimination.rs:12:17: 12:19 ++ nop; // scope 1 at $DIR/dead_store_elimination.rs:12:17: 12:19 + StorageLive(_5); // scope 2 at $DIR/dead_store_elimination.rs:13:9: 13:14 + StorageLive(_6); // scope 2 at $DIR/dead_store_elimination.rs:13:22: 13:24 + _6 = const 11_i32; // scope 2 at $DIR/dead_store_elimination.rs:13:22: 13:24 + _5 = &mut _6; // scope 2 at $DIR/dead_store_elimination.rs:13:17: 13:24 + StorageLive(_7); // scope 3 at $DIR/dead_store_elimination.rs:14:9: 14:11 +- _7 = (*_5); // scope 3 at $DIR/dead_store_elimination.rs:14:9: 14:11 +- _4 = move _7; // scope 3 at $DIR/dead_store_elimination.rs:14:5: 14:11 ++ nop; // scope 3 at $DIR/dead_store_elimination.rs:14:9: 14:11 ++ nop; // scope 3 at $DIR/dead_store_elimination.rs:14:5: 14:11 + StorageDead(_7); // scope 3 at $DIR/dead_store_elimination.rs:14:10: 14:11 + _4 = const 12_i32; // scope 3 at $DIR/dead_store_elimination.rs:15:5: 15:11 + StorageLive(_8); // scope 3 at $DIR/dead_store_elimination.rs:16:5: 16:12 + StorageLive(_9); // scope 3 at $DIR/dead_store_elimination.rs:16:10: 16:11 + _9 = const 12_i32; // scope 3 at $DIR/dead_store_elimination.rs:16:10: 16:11 + _8 = read::(const 12_i32) -> bb2; // scope 3 at $DIR/dead_store_elimination.rs:16:5: 16:12 + // mir::Constant + // + span: $DIR/dead_store_elimination.rs:16:5: 16:9 + // + literal: Const { ty: fn(i32) {read::}, val: Value(Scalar()) } + } + + bb2: { + StorageDead(_9); // scope 3 at $DIR/dead_store_elimination.rs:16:11: 16:12 + StorageDead(_8); // scope 3 at $DIR/dead_store_elimination.rs:16:12: 16:13 + StorageLive(_10); // scope 3 at $DIR/dead_store_elimination.rs:20:9: 20:14 +- (_10.0: u32) = const 20_u32; // scope 3 at $DIR/dead_store_elimination.rs:20:17: 20:22 +- (_10.0: u32) = const 21_u32; // scope 4 at $DIR/dead_store_elimination.rs:21:5: 21:13 ++ nop; // scope 3 at $DIR/dead_store_elimination.rs:20:17: 20:22 ++ nop; // scope 4 at $DIR/dead_store_elimination.rs:21:5: 21:13 + (_10.0: u32) = const 22_u32; // scope 4 at $DIR/dead_store_elimination.rs:22:5: 22:13 + StorageLive(_11); // scope 4 at $DIR/dead_store_elimination.rs:23:5: 23:12 + StorageLive(_12); // scope 4 at $DIR/dead_store_elimination.rs:23:10: 23:11 + _12 = const S(22_u32); // scope 4 at $DIR/dead_store_elimination.rs:23:10: 23:11 + // ty::Const + // + ty: coverage::S + // + val: Value(Scalar(0x00000016)) + // mir::Constant + // + span: $DIR/dead_store_elimination.rs:23:10: 23:11 + // + literal: Const { ty: coverage::S, val: Value(Scalar(0x00000016)) } + _11 = read::(const S(22_u32)) -> bb3; // scope 4 at $DIR/dead_store_elimination.rs:23:5: 23:12 + // mir::Constant + // + span: $DIR/dead_store_elimination.rs:23:5: 23:9 + // + literal: Const { ty: fn(coverage::S) {read::}, val: Value(Scalar()) } + // ty::Const + // + ty: coverage::S + // + val: Value(Scalar(0x00000016)) + // mir::Constant + // + span: $DIR/dead_store_elimination.rs:23:5: 23:12 + // + literal: Const { ty: coverage::S, val: Value(Scalar(0x00000016)) } + } + + bb3: { + StorageDead(_12); // scope 4 at $DIR/dead_store_elimination.rs:23:11: 23:12 + StorageDead(_11); // scope 4 at $DIR/dead_store_elimination.rs:23:12: 23:13 + StorageLive(_13); // scope 4 at $DIR/dead_store_elimination.rs:25:9: 25:14 +- (_13.0: u32) = const 30_u32; // scope 4 at $DIR/dead_store_elimination.rs:25:17: 25:22 +- (_13.0: u32) = const 31_u32; // scope 5 at $DIR/dead_store_elimination.rs:26:5: 26:13 ++ nop; // scope 4 at $DIR/dead_store_elimination.rs:25:17: 25:22 ++ nop; // scope 5 at $DIR/dead_store_elimination.rs:26:5: 26:13 + StorageLive(_14); // scope 5 at $DIR/dead_store_elimination.rs:27:9: 27:14 +- (_14.0: u32) = const 32_u32; // scope 5 at $DIR/dead_store_elimination.rs:27:9: 27:14 ++ nop; // scope 5 at $DIR/dead_store_elimination.rs:27:9: 27:14 + _13 = const S(32_u32); // scope 5 at $DIR/dead_store_elimination.rs:27:5: 27:14 + // ty::Const + // + ty: coverage::S + // + val: Value(Scalar(0x00000020)) + // mir::Constant + // + span: $DIR/dead_store_elimination.rs:27:5: 27:14 + // + literal: Const { ty: coverage::S, val: Value(Scalar(0x00000020)) } + StorageDead(_14); // scope 5 at $DIR/dead_store_elimination.rs:27:13: 27:14 + StorageLive(_15); // scope 5 at $DIR/dead_store_elimination.rs:28:5: 28:12 + StorageLive(_16); // scope 5 at $DIR/dead_store_elimination.rs:28:10: 28:11 + _16 = const S(32_u32); // scope 5 at $DIR/dead_store_elimination.rs:28:10: 28:11 + // ty::Const + // + ty: coverage::S + // + val: Value(Scalar(0x00000020)) + // mir::Constant + // + span: $DIR/dead_store_elimination.rs:28:10: 28:11 + // + literal: Const { ty: coverage::S, val: Value(Scalar(0x00000020)) } + _15 = read::(const S(32_u32)) -> bb4; // scope 5 at $DIR/dead_store_elimination.rs:28:5: 28:12 + // mir::Constant + // + span: $DIR/dead_store_elimination.rs:28:5: 28:9 + // + literal: Const { ty: fn(coverage::S) {read::}, val: Value(Scalar()) } + // ty::Const + // + ty: coverage::S + // + val: Value(Scalar(0x00000020)) + // mir::Constant + // + span: $DIR/dead_store_elimination.rs:28:5: 28:12 + // + literal: Const { ty: coverage::S, val: Value(Scalar(0x00000020)) } + } + + bb4: { + StorageDead(_16); // scope 5 at $DIR/dead_store_elimination.rs:28:11: 28:12 + StorageDead(_15); // scope 5 at $DIR/dead_store_elimination.rs:28:12: 28:13 + StorageLive(_17); // scope 5 at $DIR/dead_store_elimination.rs:30:9: 30:14 +- _17 = const 40_i32; // scope 5 at $DIR/dead_store_elimination.rs:30:17: 30:19 +- _17 = const 41_i32; // scope 6 at $DIR/dead_store_elimination.rs:31:5: 31:11 ++ nop; // scope 5 at $DIR/dead_store_elimination.rs:30:17: 30:19 ++ nop; // scope 6 at $DIR/dead_store_elimination.rs:31:5: 31:11 + nop; // scope 0 at $DIR/dead_store_elimination.rs:6:19: 33:2 + StorageDead(_17); // scope 5 at $DIR/dead_store_elimination.rs:33:1: 33:2 + StorageDead(_13); // scope 4 at $DIR/dead_store_elimination.rs:33:1: 33:2 + StorageDead(_10); // scope 3 at $DIR/dead_store_elimination.rs:33:1: 33:2 + StorageDead(_6); // scope 2 at $DIR/dead_store_elimination.rs:33:1: 33:2 + StorageDead(_5); // scope 2 at $DIR/dead_store_elimination.rs:33:1: 33:2 + StorageDead(_4); // scope 1 at $DIR/dead_store_elimination.rs:33:1: 33:2 + StorageDead(_1); // scope 0 at $DIR/dead_store_elimination.rs:33:1: 33:2 + return; // scope 0 at $DIR/dead_store_elimination.rs:33:2: 33:2 + } + } + diff --git a/src/test/mir-opt/dead_store_elimination.find_reads.SimpleLocalDse.diff b/src/test/mir-opt/dead_store_elimination.find_reads.SimpleLocalDse.diff new file mode 100644 index 0000000000000..940af6ad03e15 --- /dev/null +++ b/src/test/mir-opt/dead_store_elimination.find_reads.SimpleLocalDse.diff @@ -0,0 +1,150 @@ +- // MIR for `find_reads` before SimpleLocalDse ++ // MIR for `find_reads` after SimpleLocalDse + + fn find_reads() -> () { + let mut _0: (); // return place in scope 0 at $DIR/dead_store_elimination.rs:66:21: 66:21 + let mut _1: i32; // in scope 0 at $DIR/dead_store_elimination.rs:67:9: 67:14 + let mut _4: i32; // in scope 0 at $DIR/dead_store_elimination.rs:69:13: 69:14 + let mut _5: i32; // in scope 0 at $DIR/dead_store_elimination.rs:69:17: 69:18 + let _6: (); // in scope 0 at $DIR/dead_store_elimination.rs:70:5: 70:12 + let mut _7: i32; // in scope 0 at $DIR/dead_store_elimination.rs:70:10: 70:11 + let _10: (); // in scope 0 at $DIR/dead_store_elimination.rs:74:5: 74:12 + let mut _11: &i32; // in scope 0 at $DIR/dead_store_elimination.rs:74:10: 74:11 + let mut _14: i32; // in scope 0 at $DIR/dead_store_elimination.rs:77:18: 77:19 + let _15: (); // in scope 0 at $DIR/dead_store_elimination.rs:78:5: 78:12 + let mut _16: std::option::Option; // in scope 0 at $DIR/dead_store_elimination.rs:78:10: 78:11 + let mut _18: isize; // in scope 0 at $DIR/dead_store_elimination.rs:81:12: 81:19 + scope 1 { + debug a => _1; // in scope 1 at $DIR/dead_store_elimination.rs:67:9: 67:14 + let mut _2: i32; // in scope 1 at $DIR/dead_store_elimination.rs:68:9: 68:14 + scope 2 { + debug b => _2; // in scope 2 at $DIR/dead_store_elimination.rs:68:9: 68:14 + let _3: i32; // in scope 2 at $DIR/dead_store_elimination.rs:69:9: 69:10 + scope 3 { + debug c => _3; // in scope 3 at $DIR/dead_store_elimination.rs:69:9: 69:10 + let mut _8: i32; // in scope 3 at $DIR/dead_store_elimination.rs:72:9: 72:14 + scope 4 { + debug a => _8; // in scope 4 at $DIR/dead_store_elimination.rs:72:9: 72:14 + let _9: &i32; // in scope 4 at $DIR/dead_store_elimination.rs:73:9: 73:10 + scope 5 { + debug r => _9; // in scope 5 at $DIR/dead_store_elimination.rs:73:9: 73:10 + let mut _12: i32; // in scope 5 at $DIR/dead_store_elimination.rs:76:9: 76:14 + scope 6 { + debug a => _12; // in scope 6 at $DIR/dead_store_elimination.rs:76:9: 76:14 + let _13: std::option::Option; // in scope 6 at $DIR/dead_store_elimination.rs:77:9: 77:10 + scope 7 { + debug e => _13; // in scope 7 at $DIR/dead_store_elimination.rs:77:9: 77:10 + let mut _17: std::option::Option; // in scope 7 at $DIR/dead_store_elimination.rs:80:9: 80:14 + scope 8 { + debug a => _17; // in scope 8 at $DIR/dead_store_elimination.rs:80:9: 80:14 + let _19: i32; // in scope 8 at $DIR/dead_store_elimination.rs:81:17: 81:18 + scope 9 { + debug x => _19; // in scope 9 at $DIR/dead_store_elimination.rs:81:17: 81:18 + } + } + } + } + } + } + } + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/dead_store_elimination.rs:67:9: 67:14 + _1 = const 0_i32; // scope 0 at $DIR/dead_store_elimination.rs:67:17: 67:18 + StorageLive(_2); // scope 1 at $DIR/dead_store_elimination.rs:68:9: 68:14 + _2 = const 1_i32; // scope 1 at $DIR/dead_store_elimination.rs:68:17: 68:18 + StorageLive(_3); // scope 2 at $DIR/dead_store_elimination.rs:69:9: 69:10 + StorageLive(_4); // scope 2 at $DIR/dead_store_elimination.rs:69:13: 69:14 +- _4 = const 0_i32; // scope 2 at $DIR/dead_store_elimination.rs:69:13: 69:14 ++ nop; // scope 2 at $DIR/dead_store_elimination.rs:69:13: 69:14 + StorageLive(_5); // scope 2 at $DIR/dead_store_elimination.rs:69:17: 69:18 +- _5 = const 1_i32; // scope 2 at $DIR/dead_store_elimination.rs:69:17: 69:18 ++ nop; // scope 2 at $DIR/dead_store_elimination.rs:69:17: 69:18 + _3 = const 1_i32; // scope 2 at $DIR/dead_store_elimination.rs:69:13: 69:18 + StorageDead(_5); // scope 2 at $DIR/dead_store_elimination.rs:69:17: 69:18 + StorageDead(_4); // scope 2 at $DIR/dead_store_elimination.rs:69:17: 69:18 + StorageLive(_6); // scope 3 at $DIR/dead_store_elimination.rs:70:5: 70:12 + StorageLive(_7); // scope 3 at $DIR/dead_store_elimination.rs:70:10: 70:11 + _7 = const 1_i32; // scope 3 at $DIR/dead_store_elimination.rs:70:10: 70:11 + _6 = read::(const 1_i32) -> bb1; // scope 3 at $DIR/dead_store_elimination.rs:70:5: 70:12 + // mir::Constant + // + span: $DIR/dead_store_elimination.rs:70:5: 70:9 + // + literal: Const { ty: fn(i32) {read::}, val: Value(Scalar()) } + } + + bb1: { + StorageDead(_7); // scope 3 at $DIR/dead_store_elimination.rs:70:11: 70:12 + StorageDead(_6); // scope 3 at $DIR/dead_store_elimination.rs:70:12: 70:13 + StorageLive(_8); // scope 3 at $DIR/dead_store_elimination.rs:72:9: 72:14 + _8 = const 10_i32; // scope 3 at $DIR/dead_store_elimination.rs:72:17: 72:19 + StorageLive(_9); // scope 4 at $DIR/dead_store_elimination.rs:73:9: 73:10 + _9 = &_8; // scope 4 at $DIR/dead_store_elimination.rs:73:13: 73:15 + StorageLive(_10); // scope 5 at $DIR/dead_store_elimination.rs:74:5: 74:12 + StorageLive(_11); // scope 5 at $DIR/dead_store_elimination.rs:74:10: 74:11 + _11 = _9; // scope 5 at $DIR/dead_store_elimination.rs:74:10: 74:11 + _10 = read::<&i32>(move _11) -> bb2; // scope 5 at $DIR/dead_store_elimination.rs:74:5: 74:12 + // mir::Constant + // + span: $DIR/dead_store_elimination.rs:74:5: 74:9 + // + literal: Const { ty: fn(&i32) {read::<&i32>}, val: Value(Scalar()) } + } + + bb2: { + StorageDead(_11); // scope 5 at $DIR/dead_store_elimination.rs:74:11: 74:12 + StorageDead(_10); // scope 5 at $DIR/dead_store_elimination.rs:74:12: 74:13 + StorageLive(_12); // scope 5 at $DIR/dead_store_elimination.rs:76:9: 76:14 + _12 = const 20_i32; // scope 5 at $DIR/dead_store_elimination.rs:76:17: 76:19 + StorageLive(_13); // scope 6 at $DIR/dead_store_elimination.rs:77:9: 77:10 + StorageLive(_14); // scope 6 at $DIR/dead_store_elimination.rs:77:18: 77:19 +- _14 = const 20_i32; // scope 6 at $DIR/dead_store_elimination.rs:77:18: 77:19 ++ nop; // scope 6 at $DIR/dead_store_elimination.rs:77:18: 77:19 + ((_13 as Some).0: i32) = const 20_i32; // scope 6 at $DIR/dead_store_elimination.rs:77:13: 77:20 + discriminant(_13) = 1; // scope 6 at $DIR/dead_store_elimination.rs:77:13: 77:20 + StorageDead(_14); // scope 6 at $DIR/dead_store_elimination.rs:77:19: 77:20 + StorageLive(_15); // scope 7 at $DIR/dead_store_elimination.rs:78:5: 78:12 + StorageLive(_16); // scope 7 at $DIR/dead_store_elimination.rs:78:10: 78:11 + _16 = _13; // scope 7 at $DIR/dead_store_elimination.rs:78:10: 78:11 + _15 = read::>(move _16) -> bb3; // scope 7 at $DIR/dead_store_elimination.rs:78:5: 78:12 + // mir::Constant + // + span: $DIR/dead_store_elimination.rs:78:5: 78:9 + // + literal: Const { ty: fn(std::option::Option) {read::>}, val: Value(Scalar()) } + } + + bb3: { + StorageDead(_16); // scope 7 at $DIR/dead_store_elimination.rs:78:11: 78:12 + StorageDead(_15); // scope 7 at $DIR/dead_store_elimination.rs:78:12: 78:13 + StorageLive(_17); // scope 7 at $DIR/dead_store_elimination.rs:80:9: 80:14 + ((_17 as Some).0: i32) = const 30_i32; // scope 7 at $DIR/dead_store_elimination.rs:80:17: 80:25 + discriminant(_17) = 1; // scope 7 at $DIR/dead_store_elimination.rs:80:17: 80:25 + _18 = const 1_isize; // scope 8 at $DIR/dead_store_elimination.rs:81:12: 81:19 + goto -> bb4; // scope 8 at $DIR/dead_store_elimination.rs:81:12: 81:19 + } + + bb4: { + StorageLive(_19); // scope 8 at $DIR/dead_store_elimination.rs:81:17: 81:18 +- _19 = ((_17 as Some).0: i32); // scope 8 at $DIR/dead_store_elimination.rs:81:17: 81:18 ++ nop; // scope 8 at $DIR/dead_store_elimination.rs:81:17: 81:18 + nop; // scope 8 at $DIR/dead_store_elimination.rs:81:24: 82:6 + StorageDead(_19); // scope 8 at $DIR/dead_store_elimination.rs:82:5: 82:6 + goto -> bb6; // scope 8 at $DIR/dead_store_elimination.rs:81:5: 83:6 + } + + bb5: { + nop; // scope 8 at $DIR/dead_store_elimination.rs:82:12: 83:6 + goto -> bb6; // scope 8 at $DIR/dead_store_elimination.rs:81:5: 83:6 + } + + bb6: { + StorageDead(_17); // scope 7 at $DIR/dead_store_elimination.rs:84:1: 84:2 + StorageDead(_13); // scope 6 at $DIR/dead_store_elimination.rs:84:1: 84:2 + StorageDead(_12); // scope 5 at $DIR/dead_store_elimination.rs:84:1: 84:2 + StorageDead(_9); // scope 4 at $DIR/dead_store_elimination.rs:84:1: 84:2 + StorageDead(_8); // scope 3 at $DIR/dead_store_elimination.rs:84:1: 84:2 + StorageDead(_3); // scope 2 at $DIR/dead_store_elimination.rs:84:1: 84:2 + StorageDead(_2); // scope 1 at $DIR/dead_store_elimination.rs:84:1: 84:2 + StorageDead(_1); // scope 0 at $DIR/dead_store_elimination.rs:84:1: 84:2 + return; // scope 0 at $DIR/dead_store_elimination.rs:84:2: 84:2 + } + } + diff --git a/src/test/mir-opt/dead_store_elimination.indexing.SimpleLocalDse.diff b/src/test/mir-opt/dead_store_elimination.indexing.SimpleLocalDse.diff new file mode 100644 index 0000000000000..302817cc16e79 --- /dev/null +++ b/src/test/mir-opt/dead_store_elimination.indexing.SimpleLocalDse.diff @@ -0,0 +1,154 @@ +- // MIR for `indexing` before SimpleLocalDse ++ // MIR for `indexing` after SimpleLocalDse + + fn indexing() -> () { + let mut _0: (); // return place in scope 0 at $DIR/dead_store_elimination.rs:36:19: 36:19 + let mut _1: usize; // in scope 0 at $DIR/dead_store_elimination.rs:37:9: 37:14 + let _4: usize; // in scope 0 at $DIR/dead_store_elimination.rs:39:15: 39:16 + let mut _5: usize; // in scope 0 at $DIR/dead_store_elimination.rs:39:13: 39:17 + let mut _6: bool; // in scope 0 at $DIR/dead_store_elimination.rs:39:13: 39:17 + let _7: (); // in scope 0 at $DIR/dead_store_elimination.rs:40:5: 40:12 + let mut _8: i32; // in scope 0 at $DIR/dead_store_elimination.rs:40:10: 40:11 + let _13: usize; // in scope 0 at $DIR/dead_store_elimination.rs:45:16: 45:17 + let mut _14: usize; // in scope 0 at $DIR/dead_store_elimination.rs:45:14: 45:18 + let mut _15: bool; // in scope 0 at $DIR/dead_store_elimination.rs:45:14: 45:18 + let _16: (); // in scope 0 at $DIR/dead_store_elimination.rs:46:5: 46:12 + let mut _17: &i32; // in scope 0 at $DIR/dead_store_elimination.rs:46:10: 46:11 + let _20: usize; // in scope 0 at $DIR/dead_store_elimination.rs:50:7: 50:8 + let mut _21: usize; // in scope 0 at $DIR/dead_store_elimination.rs:50:5: 50:9 + let mut _22: bool; // in scope 0 at $DIR/dead_store_elimination.rs:50:5: 50:9 + let _23: (); // in scope 0 at $DIR/dead_store_elimination.rs:51:5: 51:12 + let mut _24: [i32; 2]; // in scope 0 at $DIR/dead_store_elimination.rs:51:10: 51:11 + scope 1 { + debug i => _1; // in scope 1 at $DIR/dead_store_elimination.rs:37:9: 37:14 + let _2: [i32; 2]; // in scope 1 at $DIR/dead_store_elimination.rs:38:9: 38:10 + scope 2 { + debug a => _2; // in scope 2 at $DIR/dead_store_elimination.rs:38:9: 38:10 + let _3: i32; // in scope 2 at $DIR/dead_store_elimination.rs:39:9: 39:10 + scope 3 { + debug x => _3; // in scope 3 at $DIR/dead_store_elimination.rs:39:9: 39:10 + let mut _9: usize; // in scope 3 at $DIR/dead_store_elimination.rs:42:9: 42:14 + scope 4 { + debug i => _9; // in scope 4 at $DIR/dead_store_elimination.rs:42:9: 42:14 + let _10: [i32; 2]; // in scope 4 at $DIR/dead_store_elimination.rs:43:9: 43:10 + scope 5 { + debug a => _10; // in scope 5 at $DIR/dead_store_elimination.rs:43:9: 43:10 + let _11: &[i32; 2]; // in scope 5 at $DIR/dead_store_elimination.rs:44:9: 44:10 + scope 6 { + debug r => _11; // in scope 6 at $DIR/dead_store_elimination.rs:44:9: 44:10 + let _12: &i32; // in scope 6 at $DIR/dead_store_elimination.rs:45:9: 45:10 + scope 7 { + debug r => _12; // in scope 7 at $DIR/dead_store_elimination.rs:45:9: 45:10 + let mut _18: usize; // in scope 7 at $DIR/dead_store_elimination.rs:48:9: 48:14 + scope 8 { + debug i => _18; // in scope 8 at $DIR/dead_store_elimination.rs:48:9: 48:14 + let mut _19: [i32; 2]; // in scope 8 at $DIR/dead_store_elimination.rs:49:9: 49:14 + scope 9 { + debug a => _19; // in scope 9 at $DIR/dead_store_elimination.rs:49:9: 49:14 + } + } + } + } + } + } + } + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/dead_store_elimination.rs:37:9: 37:14 + _1 = const 0_usize; // scope 0 at $DIR/dead_store_elimination.rs:37:17: 37:18 + StorageLive(_2); // scope 1 at $DIR/dead_store_elimination.rs:38:9: 38:10 + _2 = [const 1_i32; 2]; // scope 1 at $DIR/dead_store_elimination.rs:38:13: 38:19 + StorageLive(_3); // scope 2 at $DIR/dead_store_elimination.rs:39:9: 39:10 + StorageLive(_4); // scope 2 at $DIR/dead_store_elimination.rs:39:15: 39:16 + _4 = const 0_usize; // scope 2 at $DIR/dead_store_elimination.rs:39:15: 39:16 + _5 = const 2_usize; // scope 2 at $DIR/dead_store_elimination.rs:39:13: 39:17 + _6 = const true; // scope 2 at $DIR/dead_store_elimination.rs:39:13: 39:17 + goto -> bb1; // scope 2 at $DIR/dead_store_elimination.rs:39:13: 39:17 + } + + bb1: { + _3 = _2[_4]; // scope 2 at $DIR/dead_store_elimination.rs:39:13: 39:17 + StorageDead(_4); // scope 2 at $DIR/dead_store_elimination.rs:39:17: 39:18 + StorageLive(_7); // scope 3 at $DIR/dead_store_elimination.rs:40:5: 40:12 + StorageLive(_8); // scope 3 at $DIR/dead_store_elimination.rs:40:10: 40:11 + _8 = _3; // scope 3 at $DIR/dead_store_elimination.rs:40:10: 40:11 + _7 = read::(move _8) -> bb2; // scope 3 at $DIR/dead_store_elimination.rs:40:5: 40:12 + // mir::Constant + // + span: $DIR/dead_store_elimination.rs:40:5: 40:9 + // + literal: Const { ty: fn(i32) {read::}, val: Value(Scalar()) } + } + + bb2: { + StorageDead(_8); // scope 3 at $DIR/dead_store_elimination.rs:40:11: 40:12 + StorageDead(_7); // scope 3 at $DIR/dead_store_elimination.rs:40:12: 40:13 + StorageLive(_9); // scope 3 at $DIR/dead_store_elimination.rs:42:9: 42:14 + _9 = const 0_usize; // scope 3 at $DIR/dead_store_elimination.rs:42:17: 42:18 + StorageLive(_10); // scope 4 at $DIR/dead_store_elimination.rs:43:9: 43:10 + _10 = [const 11_i32; 2]; // scope 4 at $DIR/dead_store_elimination.rs:43:13: 43:20 + StorageLive(_11); // scope 5 at $DIR/dead_store_elimination.rs:44:9: 44:10 + _11 = &_10; // scope 5 at $DIR/dead_store_elimination.rs:44:13: 44:15 + StorageLive(_12); // scope 6 at $DIR/dead_store_elimination.rs:45:9: 45:10 + StorageLive(_13); // scope 6 at $DIR/dead_store_elimination.rs:45:16: 45:17 + _13 = const 0_usize; // scope 6 at $DIR/dead_store_elimination.rs:45:16: 45:17 + _14 = const 2_usize; // scope 6 at $DIR/dead_store_elimination.rs:45:14: 45:18 + _15 = const true; // scope 6 at $DIR/dead_store_elimination.rs:45:14: 45:18 + goto -> bb3; // scope 6 at $DIR/dead_store_elimination.rs:45:14: 45:18 + } + + bb3: { + _12 = &(*_11)[_13]; // scope 6 at $DIR/dead_store_elimination.rs:45:13: 45:18 + StorageLive(_16); // scope 7 at $DIR/dead_store_elimination.rs:46:5: 46:12 + StorageLive(_17); // scope 7 at $DIR/dead_store_elimination.rs:46:10: 46:11 + _17 = _12; // scope 7 at $DIR/dead_store_elimination.rs:46:10: 46:11 + _16 = read::<&i32>(move _17) -> bb4; // scope 7 at $DIR/dead_store_elimination.rs:46:5: 46:12 + // mir::Constant + // + span: $DIR/dead_store_elimination.rs:46:5: 46:9 + // + literal: Const { ty: fn(&i32) {read::<&i32>}, val: Value(Scalar()) } + } + + bb4: { + StorageDead(_17); // scope 7 at $DIR/dead_store_elimination.rs:46:11: 46:12 + StorageDead(_16); // scope 7 at $DIR/dead_store_elimination.rs:46:12: 46:13 + StorageLive(_18); // scope 7 at $DIR/dead_store_elimination.rs:48:9: 48:14 + _18 = const 0_usize; // scope 7 at $DIR/dead_store_elimination.rs:48:17: 48:18 + StorageLive(_19); // scope 8 at $DIR/dead_store_elimination.rs:49:9: 49:14 + _19 = [const 13_i32; 2]; // scope 8 at $DIR/dead_store_elimination.rs:49:17: 49:24 + StorageLive(_20); // scope 9 at $DIR/dead_store_elimination.rs:50:7: 50:8 + _20 = const 0_usize; // scope 9 at $DIR/dead_store_elimination.rs:50:7: 50:8 + _21 = const 2_usize; // scope 9 at $DIR/dead_store_elimination.rs:50:5: 50:9 + _22 = const true; // scope 9 at $DIR/dead_store_elimination.rs:50:5: 50:9 + goto -> bb5; // scope 9 at $DIR/dead_store_elimination.rs:50:5: 50:9 + } + + bb5: { + _19[_20] = const 14_i32; // scope 9 at $DIR/dead_store_elimination.rs:50:5: 50:14 + StorageDead(_20); // scope 9 at $DIR/dead_store_elimination.rs:50:14: 50:15 + StorageLive(_23); // scope 9 at $DIR/dead_store_elimination.rs:51:5: 51:12 + StorageLive(_24); // scope 9 at $DIR/dead_store_elimination.rs:51:10: 51:11 + _24 = _19; // scope 9 at $DIR/dead_store_elimination.rs:51:10: 51:11 + _23 = read::<[i32; 2]>(move _24) -> bb6; // scope 9 at $DIR/dead_store_elimination.rs:51:5: 51:12 + // mir::Constant + // + span: $DIR/dead_store_elimination.rs:51:5: 51:9 + // + literal: Const { ty: fn([i32; 2]) {read::<[i32; 2]>}, val: Value(Scalar()) } + } + + bb6: { + StorageDead(_24); // scope 9 at $DIR/dead_store_elimination.rs:51:11: 51:12 + StorageDead(_23); // scope 9 at $DIR/dead_store_elimination.rs:51:12: 51:13 + nop; // scope 0 at $DIR/dead_store_elimination.rs:36:19: 52:2 + StorageDead(_19); // scope 8 at $DIR/dead_store_elimination.rs:52:1: 52:2 + StorageDead(_18); // scope 7 at $DIR/dead_store_elimination.rs:52:1: 52:2 + StorageDead(_13); // scope 6 at $DIR/dead_store_elimination.rs:52:1: 52:2 + StorageDead(_12); // scope 6 at $DIR/dead_store_elimination.rs:52:1: 52:2 + StorageDead(_11); // scope 5 at $DIR/dead_store_elimination.rs:52:1: 52:2 + StorageDead(_10); // scope 4 at $DIR/dead_store_elimination.rs:52:1: 52:2 + StorageDead(_9); // scope 3 at $DIR/dead_store_elimination.rs:52:1: 52:2 + StorageDead(_3); // scope 2 at $DIR/dead_store_elimination.rs:52:1: 52:2 + StorageDead(_2); // scope 1 at $DIR/dead_store_elimination.rs:52:1: 52:2 + StorageDead(_1); // scope 0 at $DIR/dead_store_elimination.rs:52:1: 52:2 + return; // scope 0 at $DIR/dead_store_elimination.rs:52:2: 52:2 + } + } + diff --git a/src/test/mir-opt/dead_store_elimination.memory.SimpleLocalDse.diff b/src/test/mir-opt/dead_store_elimination.memory.SimpleLocalDse.diff new file mode 100644 index 0000000000000..da995e6bae081 --- /dev/null +++ b/src/test/mir-opt/dead_store_elimination.memory.SimpleLocalDse.diff @@ -0,0 +1,53 @@ +- // MIR for `memory` before SimpleLocalDse ++ // MIR for `memory` after SimpleLocalDse + + fn memory() -> () { + let mut _0: (); // return place in scope 0 at $DIR/dead_store_elimination.rs:56:17: 56:17 + let mut _1: i32; // in scope 0 at $DIR/dead_store_elimination.rs:57:9: 57:14 + let mut _4: i32; // in scope 0 at $DIR/dead_store_elimination.rs:60:9: 60:11 + let _5: (); // in scope 0 at $DIR/dead_store_elimination.rs:62:5: 62:12 + let mut _6: i32; // in scope 0 at $DIR/dead_store_elimination.rs:62:10: 62:11 + scope 1 { + debug x => _1; // in scope 1 at $DIR/dead_store_elimination.rs:57:9: 57:14 + let mut _2: i32; // in scope 1 at $DIR/dead_store_elimination.rs:58:9: 58:14 + scope 2 { + debug y => _2; // in scope 2 at $DIR/dead_store_elimination.rs:58:9: 58:14 + let _3: &mut i32; // in scope 2 at $DIR/dead_store_elimination.rs:59:9: 59:10 + scope 3 { + debug r => _3; // in scope 3 at $DIR/dead_store_elimination.rs:59:9: 59:10 + } + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/dead_store_elimination.rs:57:9: 57:14 + _1 = const 0_i32; // scope 0 at $DIR/dead_store_elimination.rs:57:17: 57:18 + StorageLive(_2); // scope 1 at $DIR/dead_store_elimination.rs:58:9: 58:14 + _2 = const 1_i32; // scope 1 at $DIR/dead_store_elimination.rs:58:17: 58:18 + StorageLive(_3); // scope 2 at $DIR/dead_store_elimination.rs:59:9: 59:10 + _3 = &mut _2; // scope 2 at $DIR/dead_store_elimination.rs:59:13: 59:19 + StorageLive(_4); // scope 3 at $DIR/dead_store_elimination.rs:60:9: 60:11 + _4 = (*_3); // scope 3 at $DIR/dead_store_elimination.rs:60:9: 60:11 + _1 = move _4; // scope 3 at $DIR/dead_store_elimination.rs:60:5: 60:11 + StorageDead(_4); // scope 3 at $DIR/dead_store_elimination.rs:60:10: 60:11 + _2 = const 2_i32; // scope 3 at $DIR/dead_store_elimination.rs:61:5: 61:10 + StorageLive(_5); // scope 3 at $DIR/dead_store_elimination.rs:62:5: 62:12 + StorageLive(_6); // scope 3 at $DIR/dead_store_elimination.rs:62:10: 62:11 + _6 = _1; // scope 3 at $DIR/dead_store_elimination.rs:62:10: 62:11 + _5 = read::(move _6) -> bb1; // scope 3 at $DIR/dead_store_elimination.rs:62:5: 62:12 + // mir::Constant + // + span: $DIR/dead_store_elimination.rs:62:5: 62:9 + // + literal: Const { ty: fn(i32) {read::}, val: Value(Scalar()) } + } + + bb1: { + StorageDead(_6); // scope 3 at $DIR/dead_store_elimination.rs:62:11: 62:12 + StorageDead(_5); // scope 3 at $DIR/dead_store_elimination.rs:62:12: 62:13 + nop; // scope 0 at $DIR/dead_store_elimination.rs:56:17: 63:2 + StorageDead(_3); // scope 2 at $DIR/dead_store_elimination.rs:63:1: 63:2 + StorageDead(_2); // scope 1 at $DIR/dead_store_elimination.rs:63:1: 63:2 + StorageDead(_1); // scope 0 at $DIR/dead_store_elimination.rs:63:1: 63:2 + return; // scope 0 at $DIR/dead_store_elimination.rs:63:2: 63:2 + } + } + diff --git a/src/test/mir-opt/dead_store_elimination.rs b/src/test/mir-opt/dead_store_elimination.rs new file mode 100644 index 0000000000000..a2a157aedcd76 --- /dev/null +++ b/src/test/mir-opt/dead_store_elimination.rs @@ -0,0 +1,91 @@ +#[inline(never)] +pub fn read(_: T) {} + +// Check that we make the optimization in the cases we're interested in +// EMIT_MIR dead_store_elimination.coverage.SimpleLocalDse.diff +pub fn coverage() { + let mut x = 0; + x = 1; + x = 2; + read(x); + + let mut x = 10; + let mut r = &mut 11; + x = *r; + x = 12; + read(x); + + struct S(u32); + + let mut s = S(20); + s.0 = 21; + s.0 = 22; + read(s); + + let mut s = S(30); + s.0 = 31; + s = S(32); + read(s); + + let mut x = 40; + x = 41; + // StorageDead here +} + +// EMIT_MIR dead_store_elimination.indexing.SimpleLocalDse.diff +pub fn indexing() { + let mut i = 0; + let a = [1; 2]; + let x = a[i]; + read(x); + + let mut i = 0; + let a = [11; 2]; + let r = &a; + let r = &r[i]; + read(r); + + let mut i = 0; + let mut a = [13; 2]; + a[i] = 14; + read(a); +} + +// Don't optimize out things when memory accesses may observe them +// EMIT_MIR dead_store_elimination.memory.SimpleLocalDse.diff +pub fn memory() { + let mut x = 0; + let mut y = 1; // don't optimize out + let r = &mut y; + x = *r; + y = 2; + read(x); +} + +// EMIT_MIR dead_store_elimination.find_reads.SimpleLocalDse.diff +pub fn find_reads() { + let mut a = 0; + let mut b = 1; + let c = a + b; + read(c); + + let mut a = 10; + let r = &a; + read(r); + + let mut a = 20; + let e = Some(a); + read(e); + + let mut a = Some(30); + if let Some(x) = a { + } else { + } +} + +fn main() { + coverage(); + indexing(); + memory(); + find_reads(); +} diff --git a/src/test/mir-opt/lower_array_len.array_bound.SimplifyLocals.diff b/src/test/mir-opt/lower_array_len.array_bound.SimplifyLocals.diff index 5cf3312cd641b..887c7b01f4327 100644 --- a/src/test/mir-opt/lower_array_len.array_bound.SimplifyLocals.diff +++ b/src/test/mir-opt/lower_array_len.array_bound.SimplifyLocals.diff @@ -25,10 +25,7 @@ StorageLive(_5); // scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 - StorageLive(_6); // scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 - StorageLive(_7); // scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 -- _7 = _2; // scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 - StorageLive(_11); // scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 -- _11 = _7; // scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 -- _6 = move _7 as &[u8] (Pointer(Unsize)); // scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 - StorageDead(_7); // scope 0 at $DIR/lower_array_len.rs:7:20: 7:21 _5 = const N; // scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 - StorageDead(_11); // scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 diff --git a/src/test/mir-opt/lower_array_len.array_bound_mut.SimplifyLocals.diff b/src/test/mir-opt/lower_array_len.array_bound_mut.SimplifyLocals.diff index f72aee0e50280..51d5f1acdab83 100644 --- a/src/test/mir-opt/lower_array_len.array_bound_mut.SimplifyLocals.diff +++ b/src/test/mir-opt/lower_array_len.array_bound_mut.SimplifyLocals.diff @@ -31,10 +31,7 @@ StorageLive(_5); // scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 - StorageLive(_6); // scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 - StorageLive(_7); // scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 -- _7 = &(*_2); // scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 - StorageLive(_14); // scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 -- _14 = _7; // scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 -- _6 = move _7 as &[u8] (Pointer(Unsize)); // scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 - StorageDead(_7); // scope 0 at $DIR/lower_array_len.rs:18:20: 18:21 _5 = const N; // scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 - StorageDead(_14); // scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 diff --git a/src/test/mir-opt/lower_array_len.array_len.SimplifyLocals.diff b/src/test/mir-opt/lower_array_len.array_len.SimplifyLocals.diff index 20e2685aba59f..3c26cf32a76c7 100644 --- a/src/test/mir-opt/lower_array_len.array_len.SimplifyLocals.diff +++ b/src/test/mir-opt/lower_array_len.array_len.SimplifyLocals.diff @@ -11,10 +11,7 @@ bb0: { - StorageLive(_2); // scope 0 at $DIR/lower_array_len.rs:31:5: 31:14 - StorageLive(_3); // scope 0 at $DIR/lower_array_len.rs:31:5: 31:14 -- _3 = _1; // scope 0 at $DIR/lower_array_len.rs:31:5: 31:14 - StorageLive(_4); // scope 0 at $DIR/lower_array_len.rs:31:5: 31:14 -- _4 = _3; // scope 0 at $DIR/lower_array_len.rs:31:5: 31:14 -- _2 = move _3 as &[u8] (Pointer(Unsize)); // scope 0 at $DIR/lower_array_len.rs:31:5: 31:14 - StorageDead(_3); // scope 0 at $DIR/lower_array_len.rs:31:7: 31:8 _0 = const N; // scope 0 at $DIR/lower_array_len.rs:31:5: 31:14 - StorageDead(_4); // scope 0 at $DIR/lower_array_len.rs:31:5: 31:14 diff --git a/src/test/mir-opt/lower_array_len.array_len_by_value.SimplifyLocals.diff b/src/test/mir-opt/lower_array_len.array_len_by_value.SimplifyLocals.diff index 7e7b708145f40..7a94217fa8b09 100644 --- a/src/test/mir-opt/lower_array_len.array_len_by_value.SimplifyLocals.diff +++ b/src/test/mir-opt/lower_array_len.array_len_by_value.SimplifyLocals.diff @@ -11,10 +11,7 @@ bb0: { - StorageLive(_2); // scope 0 at $DIR/lower_array_len.rs:38:5: 38:14 - StorageLive(_3); // scope 0 at $DIR/lower_array_len.rs:38:5: 38:14 -- _3 = &_1; // scope 0 at $DIR/lower_array_len.rs:38:5: 38:14 - StorageLive(_4); // scope 0 at $DIR/lower_array_len.rs:38:5: 38:14 -- _4 = _3; // scope 0 at $DIR/lower_array_len.rs:38:5: 38:14 -- _2 = move _3 as &[u8] (Pointer(Unsize)); // scope 0 at $DIR/lower_array_len.rs:38:5: 38:14 - StorageDead(_3); // scope 0 at $DIR/lower_array_len.rs:38:7: 38:8 _0 = const N; // scope 0 at $DIR/lower_array_len.rs:38:5: 38:14 - StorageDead(_4); // scope 0 at $DIR/lower_array_len.rs:38:5: 38:14 diff --git a/src/test/mir-opt/separate_const_switch.too_complex.PreCodegen.after.mir b/src/test/mir-opt/separate_const_switch.too_complex.PreCodegen.after.mir index 38ad12157e279..dfabfd471ab71 100644 --- a/src/test/mir-opt/separate_const_switch.too_complex.PreCodegen.after.mir +++ b/src/test/mir-opt/separate_const_switch.too_complex.PreCodegen.after.mir @@ -41,7 +41,6 @@ fn too_complex(_1: Result) -> Option { StorageDead(_7); // scope 2 at $DIR/separate_const_switch.rs:17:43: 17:44 StorageDead(_6); // scope 0 at $DIR/separate_const_switch.rs:17:43: 17:44 StorageLive(_10); // scope 0 at $DIR/separate_const_switch.rs:21:28: 21:29 - _10 = ((_2 as Break).0: usize); // scope 0 at $DIR/separate_const_switch.rs:21:28: 21:29 discriminant(_0) = 0; // scope 4 at $DIR/separate_const_switch.rs:21:34: 21:38 StorageDead(_10); // scope 0 at $DIR/separate_const_switch.rs:21:37: 21:38 goto -> bb3; // scope 0 at $DIR/separate_const_switch.rs:21:37: 21:38 diff --git a/src/test/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals.diff index 598e8247efc5a..aceb6d6659015 100644 --- a/src/test/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals.diff +++ b/src/test/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals.diff @@ -48,7 +48,6 @@ - StorageLive(_10); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:12: 16:30 - StorageLive(_11); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:12: 16:28 - (_11.0: u8) = const 40_u8; // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:12: 16:28 -- _10 = const 40_u8; // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:12: 16:30 - _9 = const 42_u8; // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:12: 16:34 - StorageDead(_10); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:33: 16:34 - _8 = use_u8(const 42_u8) -> bb2; // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:5: 16:35 diff --git a/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.64bit.diff b/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.64bit.diff index e139eedf3a0d6..240aacacfc262 100644 --- a/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.64bit.diff +++ b/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.64bit.diff @@ -15,7 +15,6 @@ } bb0: { -- _5 = const false; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:4:11: 4:12 - _5 = const true; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:4:11: 4:12 - _2 = discriminant(_1); // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:4:11: 4:12 _0 = move _1; // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:6:20: 6:27 diff --git a/src/test/mir-opt/tls-access.rs b/src/test/mir-opt/tls-access.rs index b585fd0c808e5..877173e44d926 100644 --- a/src/test/mir-opt/tls-access.rs +++ b/src/test/mir-opt/tls-access.rs @@ -1,4 +1,5 @@ #![feature(thread_local)] +#![feature(bench_black_box)] #[thread_local] static mut FOO: u8 = 3; @@ -7,6 +8,7 @@ fn main() { unsafe { let a = &FOO; FOO = 42; + core::hint::black_box(()); } } diff --git a/src/test/mir-opt/tls_access.main.SimplifyCfg-final.after.mir b/src/test/mir-opt/tls_access.main.SimplifyCfg-final.after.mir index 78ddabd0d31fe..cefbe110f1039 100644 --- a/src/test/mir-opt/tls_access.main.SimplifyCfg-final.after.mir +++ b/src/test/mir-opt/tls_access.main.SimplifyCfg-final.after.mir @@ -1,27 +1,46 @@ // MIR for `main` after SimplifyCfg-final fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/tls-access.rs:6:11: 6:11 - let _2: *mut u8; // in scope 0 at $DIR/tls-access.rs:8:18: 8:21 - let mut _3: *mut u8; // in scope 0 at $DIR/tls-access.rs:9:9: 9:12 + let mut _0: (); // return place in scope 0 at $DIR/tls-access.rs:7:11: 7:11 + let _2: *mut u8; // in scope 0 at $DIR/tls-access.rs:9:18: 9:21 + let mut _3: *mut u8; // in scope 0 at $DIR/tls-access.rs:10:9: 10:12 + let _4: (); // in scope 0 at $DIR/tls-access.rs:11:9: 11:34 + let mut _5: (); // in scope 0 at $DIR/tls-access.rs:11:31: 11:33 scope 1 { - let _1: &u8; // in scope 1 at $DIR/tls-access.rs:8:13: 8:14 + let _1: &u8; // in scope 1 at $DIR/tls-access.rs:9:13: 9:14 scope 2 { - debug a => _1; // in scope 2 at $DIR/tls-access.rs:8:13: 8:14 + debug a => _1; // in scope 2 at $DIR/tls-access.rs:9:13: 9:14 + scope 3 (inlined std::hint::black_box::<()>) { // at $DIR/tls-access.rs:11:9: 11:34 + debug dummy => _5; // in scope 3 at $DIR/tls-access.rs:11:9: 11:34 + let mut _6: (); // in scope 3 at $DIR/tls-access.rs:11:9: 11:34 + } } } bb0: { - StorageLive(_1); // scope 1 at $DIR/tls-access.rs:8:13: 8:14 - StorageLive(_2); // scope 1 at $DIR/tls-access.rs:8:18: 8:21 - _2 = &/*tls*/ mut FOO; // scope 1 at $DIR/tls-access.rs:8:18: 8:21 - _1 = &(*_2); // scope 1 at $DIR/tls-access.rs:8:17: 8:21 - StorageLive(_3); // scope 2 at $DIR/tls-access.rs:9:9: 9:12 - _3 = &/*tls*/ mut FOO; // scope 2 at $DIR/tls-access.rs:9:9: 9:12 - (*_3) = const 42_u8; // scope 2 at $DIR/tls-access.rs:9:9: 9:17 - StorageDead(_3); // scope 2 at $DIR/tls-access.rs:9:17: 9:18 - StorageDead(_2); // scope 1 at $DIR/tls-access.rs:10:5: 10:6 - StorageDead(_1); // scope 1 at $DIR/tls-access.rs:10:5: 10:6 - return; // scope 0 at $DIR/tls-access.rs:11:2: 11:2 + StorageLive(_1); // scope 1 at $DIR/tls-access.rs:9:13: 9:14 + StorageLive(_2); // scope 1 at $DIR/tls-access.rs:9:18: 9:21 + _2 = &/*tls*/ mut FOO; // scope 1 at $DIR/tls-access.rs:9:18: 9:21 + _1 = &(*_2); // scope 1 at $DIR/tls-access.rs:9:17: 9:21 + StorageLive(_3); // scope 2 at $DIR/tls-access.rs:10:9: 10:12 + _3 = &/*tls*/ mut FOO; // scope 2 at $DIR/tls-access.rs:10:9: 10:12 + (*_3) = const 42_u8; // scope 2 at $DIR/tls-access.rs:10:9: 10:17 + StorageDead(_3); // scope 2 at $DIR/tls-access.rs:10:17: 10:18 + StorageLive(_4); // scope 2 at $DIR/tls-access.rs:11:9: 11:34 + StorageLive(_5); // scope 2 at $DIR/tls-access.rs:11:31: 11:33 + StorageLive(_6); // scope 3 at $DIR/tls-access.rs:11:9: 11:34 + _4 = std::intrinsics::black_box::<()>(const ()) -> bb1; // scope 3 at $DIR/tls-access.rs:11:9: 11:34 + // mir::Constant + // + span: $DIR/tls-access.rs:11:9: 11:34 + // + literal: Const { ty: extern "rust-intrinsic" fn(()) {std::intrinsics::black_box::<()>}, val: Value(Scalar()) } + } + + bb1: { + StorageDead(_6); // scope 3 at $DIR/tls-access.rs:11:9: 11:34 + StorageDead(_5); // scope 2 at $DIR/tls-access.rs:11:33: 11:34 + StorageDead(_4); // scope 2 at $DIR/tls-access.rs:11:34: 11:35 + StorageDead(_2); // scope 1 at $DIR/tls-access.rs:12:5: 12:6 + StorageDead(_1); // scope 1 at $DIR/tls-access.rs:12:5: 12:6 + return; // scope 0 at $DIR/tls-access.rs:13:2: 13:2 } } diff --git a/src/test/mir-opt/uninhabited_enum.process_never.SimplifyLocals.after.mir b/src/test/mir-opt/uninhabited_enum.process_never.SimplifyLocals.after.mir index c17fe3bb75757..aa6a4cac350b5 100644 --- a/src/test/mir-opt/uninhabited_enum.process_never.SimplifyLocals.after.mir +++ b/src/test/mir-opt/uninhabited_enum.process_never.SimplifyLocals.after.mir @@ -12,7 +12,6 @@ fn process_never(_1: *const !) -> () { bb0: { StorageLive(_2); // scope 0 at $DIR/uninhabited-enum.rs:8:8: 8:14 - _2 = &(*_1); // scope 2 at $DIR/uninhabited-enum.rs:8:26: 8:33 StorageDead(_2); // scope 0 at $DIR/uninhabited-enum.rs:9:1: 9:2 unreachable; // scope 0 at $DIR/uninhabited-enum.rs:7:39: 9:2 } diff --git a/src/test/mir-opt/uninhabited_enum.process_void.SimplifyLocals.after.mir b/src/test/mir-opt/uninhabited_enum.process_void.SimplifyLocals.after.mir index eeaabb7b9884e..9fd4b1b54e73d 100644 --- a/src/test/mir-opt/uninhabited_enum.process_void.SimplifyLocals.after.mir +++ b/src/test/mir-opt/uninhabited_enum.process_void.SimplifyLocals.after.mir @@ -12,7 +12,6 @@ fn process_void(_1: *const Void) -> () { bb0: { StorageLive(_2); // scope 0 at $DIR/uninhabited-enum.rs:14:8: 14:14 - _2 = &(*_1); // scope 2 at $DIR/uninhabited-enum.rs:14:26: 14:33 StorageDead(_2); // scope 0 at $DIR/uninhabited-enum.rs:17:1: 17:2 return; // scope 0 at $DIR/uninhabited-enum.rs:17:2: 17:2 }