diff --git a/compiler/rustc_mir_dataflow/src/impls/initialized.rs b/compiler/rustc_mir_dataflow/src/impls/initialized.rs index 18165b0b9bd08..961a6d42891ed 100644 --- a/compiler/rustc_mir_dataflow/src/impls/initialized.rs +++ b/compiler/rustc_mir_dataflow/src/impls/initialized.rs @@ -558,6 +558,80 @@ impl<'tcx> Analysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { } } +/// A dataflow analysis that tracks locals that are maybe uninitialized. +/// +/// This is a simpler analysis than `MaybeUninitializedPlaces`, because it does not track +/// individual fields. +pub struct MaybeUninitializedLocals; + +impl MaybeUninitializedLocals { + pub fn new() -> Self { + Self {} + } +} + +impl<'tcx> Analysis<'tcx> for MaybeUninitializedLocals { + type Domain = DenseBitSet; + + const NAME: &'static str = "maybe_uninit_locals"; + + fn bottom_value(&self, body: &Body<'tcx>) -> Self::Domain { + // bottom = all locals are initialized. + DenseBitSet::new_empty(body.local_decls.len()) + } + + fn initialize_start_block(&self, body: &Body<'tcx>, state: &mut Self::Domain) { + // All locals start as uninitialized... + state.insert_all(); + // ...except for arguments, which are definitely initialized. + for arg in body.args_iter() { + state.remove(arg); + } + } + + fn apply_primary_statement_effect( + &mut self, + state: &mut Self::Domain, + statement: &mir::Statement<'tcx>, + _location: Location, + ) { + match statement.kind { + // An assignment makes a local initialized. + mir::StatementKind::Assign(box (place, _)) => { + if let Some(local) = place.as_local() { + state.remove(local); + } + } + // Deinit makes the local uninitialized. + mir::StatementKind::Deinit(box place) => { + // A deinit makes a local uninitialized. + if let Some(local) = place.as_local() { + state.insert(local); + } + } + // Storage{Live,Dead} makes a local uninitialized. + mir::StatementKind::StorageLive(local) | mir::StatementKind::StorageDead(local) => { + state.insert(local); + } + _ => {} + } + } + + fn apply_call_return_effect( + &mut self, + state: &mut Self::Domain, + _block: mir::BasicBlock, + return_places: CallReturnPlaces<'_, 'tcx>, + ) { + // The return place of a call is initialized. + return_places.for_each(|place| { + if let Some(local) = place.as_local() { + state.remove(local); + } + }); + } +} + /// There can be many more `InitIndex` than there are locals in a MIR body. /// We use a mixed bitset to avoid paying too high a memory footprint. pub type EverInitializedPlacesDomain = MixedBitSet; diff --git a/compiler/rustc_mir_dataflow/src/impls/mod.rs b/compiler/rustc_mir_dataflow/src/impls/mod.rs index 3f29b819a6d18..695298529c19c 100644 --- a/compiler/rustc_mir_dataflow/src/impls/mod.rs +++ b/compiler/rustc_mir_dataflow/src/impls/mod.rs @@ -6,7 +6,7 @@ mod storage_liveness; pub use self::borrowed_locals::{MaybeBorrowedLocals, borrowed_locals}; pub use self::initialized::{ EverInitializedPlaces, EverInitializedPlacesDomain, MaybeInitializedPlaces, - MaybeUninitializedPlaces, MaybeUninitializedPlacesDomain, + MaybeUninitializedLocals, MaybeUninitializedPlaces, MaybeUninitializedPlacesDomain, }; pub use self::liveness::{ MaybeLiveLocals, MaybeTransitiveLiveLocals, TransferFunction as LivenessTransferFunction, diff --git a/compiler/rustc_mir_transform/src/copy_prop.rs b/compiler/rustc_mir_transform/src/copy_prop.rs index fe78a104fa0b6..d8b35f2358930 100644 --- a/compiler/rustc_mir_transform/src/copy_prop.rs +++ b/compiler/rustc_mir_transform/src/copy_prop.rs @@ -3,6 +3,8 @@ use rustc_index::bit_set::DenseBitSet; use rustc_middle::mir::visit::*; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; +use rustc_mir_dataflow::impls::MaybeUninitializedLocals; +use rustc_mir_dataflow::{Analysis, ResultsCursor}; use tracing::{debug, instrument}; use crate::ssa::SsaLocals; @@ -16,7 +18,7 @@ use crate::ssa::SsaLocals; /// _d = move? _c /// where each of the locals is only assigned once. /// -/// We want to replace all those locals by `_a`, either copied or moved. +/// We want to replace all those locals by `_a` (the "head"), either copied or moved. pub(super) struct CopyProp; impl<'tcx> crate::MirPass<'tcx> for CopyProp { @@ -30,21 +32,56 @@ impl<'tcx> crate::MirPass<'tcx> for CopyProp { let typing_env = body.typing_env(tcx); let ssa = SsaLocals::new(tcx, body, typing_env); - debug!(borrowed_locals = ?ssa.borrowed_locals()); + let borrowed_locals = ssa.borrowed_locals().clone(); + + debug!(?borrowed_locals); debug!(copy_classes = ?ssa.copy_classes()); let fully_moved = fully_moved_locals(&ssa, body); debug!(?fully_moved); + let mut head_storage_to_check = DenseBitSet::new_empty(fully_moved.domain_size()); let mut storage_to_remove = DenseBitSet::new_empty(fully_moved.domain_size()); + for (local, &head) in ssa.copy_classes().iter_enumerated() { if local != head { - storage_to_remove.insert(head); + // We need to determine if we can keep the head's storage statements (which enables better optimizations). + // For every local's usage location, if the head is maybe-uninitialized, we'll need to remove it's storage statements. + head_storage_to_check.insert(head); + + if borrowed_locals.contains(local) { + // To keep the storage of a head, we require that none of the locals in it's copy class are borrowed, + // since otherwise we cannot easily identify when it is used. + storage_to_remove.insert(head); + } } } let any_replacement = ssa.copy_classes().iter_enumerated().any(|(l, &h)| l != h); + // Debug builds have no use for the storage statements, so avoid extra work. + let storage_to_remove = if any_replacement && tcx.sess.emit_lifetime_markers() { + let maybe_uninit = MaybeUninitializedLocals::new() + .iterate_to_fixpoint(tcx, body, Some("mir_opt::copy_prop")) + .into_results_cursor(body); + + let mut storage_checker = StorageChecker { + maybe_uninit, + copy_classes: ssa.copy_classes(), + head_storage_to_check, + storage_to_remove, + }; + + storage_checker.visit_body(body); + + storage_checker.storage_to_remove + } else { + // Conservatively remove all storage statements for the head locals. + head_storage_to_check + }; + + debug!(?storage_to_remove); + Replacer { tcx, copy_classes: ssa.copy_classes(), fully_moved, storage_to_remove } .visit_body_preserves_cfg(body); @@ -152,3 +189,51 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'_, 'tcx> { } } } + +// Marks heads of copy classes that are maybe uninitialized at the location of a local +// as needing storage statement removal. +struct StorageChecker<'a, 'tcx> { + maybe_uninit: ResultsCursor<'a, 'tcx, MaybeUninitializedLocals>, + copy_classes: &'a IndexSlice, + head_storage_to_check: DenseBitSet, + storage_to_remove: DenseBitSet, +} + +impl<'a, 'tcx> Visitor<'tcx> for StorageChecker<'a, 'tcx> { + fn visit_local(&mut self, local: Local, context: PlaceContext, loc: Location) { + // We don't need to check storage statements and statements for which the local doesn't need to be initialized. + match context { + PlaceContext::MutatingUse( + MutatingUseContext::Store + | MutatingUseContext::Call + | MutatingUseContext::Yield + | MutatingUseContext::AsmOutput, + ) + | PlaceContext::NonUse(_) => { + return; + } + _ => {} + }; + + let head = self.copy_classes[local]; + + // The head must be initialized at the location of the local, otherwise we must remove it's storage statements. + if self.head_storage_to_check.contains(head) { + self.maybe_uninit.seek_before_primary_effect(loc); + + if self.maybe_uninit.get().contains(head) { + debug!( + ?loc, + ?context, + ?local, + ?head, + "found a head at a location in which it is maybe uninit, marking head for storage statement removal" + ); + self.storage_to_remove.insert(head); + + // Once we found a use of the head that is maybe uninit, we do not need to check it again. + self.head_storage_to_check.remove(head); + } + } + } +} diff --git a/tests/mir-opt/copy-prop/copy_prop_borrowed_storage_not_removed.f.CopyProp.diff b/tests/mir-opt/copy-prop/copy_prop_borrowed_storage_not_removed.f.CopyProp.diff new file mode 100644 index 0000000000000..782b053cf2240 --- /dev/null +++ b/tests/mir-opt/copy-prop/copy_prop_borrowed_storage_not_removed.f.CopyProp.diff @@ -0,0 +1,21 @@ +- // MIR for `f` before CopyProp ++ // MIR for `f` after CopyProp + + fn f(_1: (T, T)) -> T { + let mut _0: T; + let mut _2: T; + let mut _3: T; + let mut _4: &T; + + bb0: { +- StorageLive(_2); + _2 = copy (_1.0: T); +- _3 = copy _2; +- _4 = &_3; +- StorageDead(_2); ++ _4 = &_2; + _0 = copy (*_4); + return; + } + } + diff --git a/tests/mir-opt/copy-prop/copy_prop_borrowed_storage_not_removed.rs b/tests/mir-opt/copy-prop/copy_prop_borrowed_storage_not_removed.rs new file mode 100644 index 0000000000000..39a3fda47a8e5 --- /dev/null +++ b/tests/mir-opt/copy-prop/copy_prop_borrowed_storage_not_removed.rs @@ -0,0 +1,30 @@ +// skip-filecheck +//@ test-mir-pass: CopyProp + +#![feature(custom_mir, core_intrinsics, freeze)] + +// Check that we remove the storage statements if one of the locals is borrowed, +// and the head isn't borrowed. + +use std::intrinsics::mir::*; +use std::marker::Freeze; + +// EMIT_MIR copy_prop_borrowed_storage_not_removed.f.CopyProp.diff + +#[custom_mir(dialect = "runtime")] +pub fn f(_1: (T, T)) -> T { + mir! { + let _2: T; + let _3: T; + let _4: &T; + { + StorageLive(_2); + _2 = _1.0; + _3 = _2; + _4 = &_3; + StorageDead(_2); + RET = *_4; + Return() + } + } +} diff --git a/tests/mir-opt/copy-prop/copy_prop_storage_twice.dead_twice.CopyProp.diff b/tests/mir-opt/copy-prop/copy_prop_storage_twice.dead_twice.CopyProp.diff new file mode 100644 index 0000000000000..0eb86de527219 --- /dev/null +++ b/tests/mir-opt/copy-prop/copy_prop_storage_twice.dead_twice.CopyProp.diff @@ -0,0 +1,28 @@ +- // MIR for `dead_twice` before CopyProp ++ // MIR for `dead_twice` after CopyProp + + fn dead_twice(_1: T) -> T { + let mut _0: T; + let mut _2: T; + let mut _3: T; + let mut _4: T; + + bb0: { +- StorageLive(_2); + _2 = opaque::(move _1) -> [return: bb1, unwind unreachable]; + } + + bb1: { +- _4 = move _2; +- StorageDead(_2); +- StorageLive(_2); +- _0 = opaque::(move _4) -> [return: bb2, unwind unreachable]; ++ _0 = opaque::(move _2) -> [return: bb2, unwind unreachable]; + } + + bb2: { +- StorageDead(_2); + return; + } + } + diff --git a/tests/mir-opt/copy-prop/copy_prop_storage_twice.live_twice.CopyProp.diff b/tests/mir-opt/copy-prop/copy_prop_storage_twice.live_twice.CopyProp.diff new file mode 100644 index 0000000000000..01b59b547eaa8 --- /dev/null +++ b/tests/mir-opt/copy-prop/copy_prop_storage_twice.live_twice.CopyProp.diff @@ -0,0 +1,27 @@ +- // MIR for `live_twice` before CopyProp ++ // MIR for `live_twice` after CopyProp + + fn live_twice(_1: T) -> T { + let mut _0: T; + let mut _2: T; + let mut _3: T; + let mut _4: T; + + bb0: { +- StorageLive(_2); + _2 = opaque::(move _1) -> [return: bb1, unwind unreachable]; + } + + bb1: { +- _4 = move _2; +- StorageLive(_2); +- _0 = opaque::(copy _4) -> [return: bb2, unwind unreachable]; ++ _0 = opaque::(copy _2) -> [return: bb2, unwind unreachable]; + } + + bb2: { +- StorageDead(_2); + return; + } + } + diff --git a/tests/mir-opt/copy-prop/copy_prop_storage_twice.rs b/tests/mir-opt/copy-prop/copy_prop_storage_twice.rs new file mode 100644 index 0000000000000..421bb55d62ecc --- /dev/null +++ b/tests/mir-opt/copy-prop/copy_prop_storage_twice.rs @@ -0,0 +1,61 @@ +// skip-filecheck +//@ test-mir-pass: CopyProp +//@ compile-flags: -Zlint-mir=false + +#![feature(custom_mir, core_intrinsics)] + +// Check that we remove the storage statements if the head +// becomes uninitialized before it is used again. + +use std::intrinsics::mir::*; + +// EMIT_MIR copy_prop_storage_twice.dead_twice.CopyProp.diff +// EMIT_MIR copy_prop_storage_twice.live_twice.CopyProp.diff + +#[custom_mir(dialect = "runtime")] +pub fn dead_twice(_1: T) -> T { + mir! { + let _2: T; + let _3: T; + { + StorageLive(_2); + Call(_2 = opaque(Move(_1)), ReturnTo(bb1), UnwindUnreachable()) + } + bb1 = { + let _3 = Move(_2); + StorageDead(_2); + StorageLive(_2); + Call(RET = opaque(Move(_3)), ReturnTo(bb2), UnwindUnreachable()) + } + bb2 = { + StorageDead(_2); + Return() + } + } +} + +#[custom_mir(dialect = "runtime")] +pub fn live_twice(_1: T) -> T { + mir! { + let _2: T; + let _3: T; + { + StorageLive(_2); + Call(_2 = opaque(Move(_1)), ReturnTo(bb1), UnwindUnreachable()) + } + bb1 = { + let _3 = Move(_2); + StorageLive(_2); + Call(RET = opaque(_3), ReturnTo(bb2), UnwindUnreachable()) + } + bb2 = { + StorageDead(_2); + Return() + } + } +} + +#[inline(never)] +fn opaque(a: T) -> T { + a +} diff --git a/tests/mir-opt/copy-prop/cycle.main.CopyProp.panic-abort.diff b/tests/mir-opt/copy-prop/cycle.main.CopyProp.panic-abort.diff index d133091e6a438..f11685467fd7d 100644 --- a/tests/mir-opt/copy-prop/cycle.main.CopyProp.panic-abort.diff +++ b/tests/mir-opt/copy-prop/cycle.main.CopyProp.panic-abort.diff @@ -26,7 +26,7 @@ } bb1: { -- StorageLive(_2); + StorageLive(_2); _2 = copy _1; - StorageLive(_3); - _3 = copy _2; @@ -46,7 +46,7 @@ StorageDead(_5); _0 = const (); - StorageDead(_3); -- StorageDead(_2); + StorageDead(_2); StorageDead(_1); return; } diff --git a/tests/mir-opt/copy-prop/cycle.main.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/cycle.main.CopyProp.panic-unwind.diff index bd4ad737cec13..bf5d8d20b7a10 100644 --- a/tests/mir-opt/copy-prop/cycle.main.CopyProp.panic-unwind.diff +++ b/tests/mir-opt/copy-prop/cycle.main.CopyProp.panic-unwind.diff @@ -26,7 +26,7 @@ } bb1: { -- StorageLive(_2); + StorageLive(_2); _2 = copy _1; - StorageLive(_3); - _3 = copy _2; @@ -46,7 +46,7 @@ StorageDead(_5); _0 = const (); - StorageDead(_3); -- StorageDead(_2); + StorageDead(_2); StorageDead(_1); return; } diff --git a/tests/mir-opt/copy-prop/dead_stores_79191.f.CopyProp.after.panic-abort.mir b/tests/mir-opt/copy-prop/dead_stores_79191.f.CopyProp.after.panic-abort.mir index 4781fdfd902a4..90bd2b8e07a8f 100644 --- a/tests/mir-opt/copy-prop/dead_stores_79191.f.CopyProp.after.panic-abort.mir +++ b/tests/mir-opt/copy-prop/dead_stores_79191.f.CopyProp.after.panic-abort.mir @@ -11,6 +11,7 @@ fn f(_1: usize) -> usize { } bb0: { + StorageLive(_2); _2 = copy _1; _1 = const 5_usize; _1 = copy _2; @@ -21,6 +22,7 @@ fn f(_1: usize) -> usize { bb1: { StorageDead(_4); + StorageDead(_2); return; } } diff --git a/tests/mir-opt/copy-prop/dead_stores_79191.f.CopyProp.after.panic-unwind.mir b/tests/mir-opt/copy-prop/dead_stores_79191.f.CopyProp.after.panic-unwind.mir index f5fded45c13b4..72b51f0b60a7b 100644 --- a/tests/mir-opt/copy-prop/dead_stores_79191.f.CopyProp.after.panic-unwind.mir +++ b/tests/mir-opt/copy-prop/dead_stores_79191.f.CopyProp.after.panic-unwind.mir @@ -11,6 +11,7 @@ fn f(_1: usize) -> usize { } bb0: { + StorageLive(_2); _2 = copy _1; _1 = const 5_usize; _1 = copy _2; @@ -21,6 +22,7 @@ fn f(_1: usize) -> usize { bb1: { StorageDead(_4); + StorageDead(_2); return; } } diff --git a/tests/mir-opt/copy-prop/dead_stores_better.f.CopyProp.after.panic-abort.mir b/tests/mir-opt/copy-prop/dead_stores_better.f.CopyProp.after.panic-abort.mir index 4781fdfd902a4..90bd2b8e07a8f 100644 --- a/tests/mir-opt/copy-prop/dead_stores_better.f.CopyProp.after.panic-abort.mir +++ b/tests/mir-opt/copy-prop/dead_stores_better.f.CopyProp.after.panic-abort.mir @@ -11,6 +11,7 @@ fn f(_1: usize) -> usize { } bb0: { + StorageLive(_2); _2 = copy _1; _1 = const 5_usize; _1 = copy _2; @@ -21,6 +22,7 @@ fn f(_1: usize) -> usize { bb1: { StorageDead(_4); + StorageDead(_2); return; } } diff --git a/tests/mir-opt/copy-prop/dead_stores_better.f.CopyProp.after.panic-unwind.mir b/tests/mir-opt/copy-prop/dead_stores_better.f.CopyProp.after.panic-unwind.mir index f5fded45c13b4..72b51f0b60a7b 100644 --- a/tests/mir-opt/copy-prop/dead_stores_better.f.CopyProp.after.panic-unwind.mir +++ b/tests/mir-opt/copy-prop/dead_stores_better.f.CopyProp.after.panic-unwind.mir @@ -11,6 +11,7 @@ fn f(_1: usize) -> usize { } bb0: { + StorageLive(_2); _2 = copy _1; _1 = const 5_usize; _1 = copy _2; @@ -21,6 +22,7 @@ fn f(_1: usize) -> usize { bb1: { StorageDead(_4); + StorageDead(_2); return; } } diff --git a/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-abort.diff b/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-abort.diff index 689083dfc1d3a..fb2aa9c055a64 100644 --- a/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-abort.diff +++ b/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-abort.diff @@ -86,7 +86,7 @@ } bb6: { -- StorageLive(_16); + StorageLive(_16); _16 = copy ((_11 as Some).0: usize); StorageLive(_17); - StorageLive(_18); @@ -116,7 +116,7 @@ StorageDead(_17); - StorageDead(_18); - _10 = const (); -- StorageDead(_16); + StorageDead(_16); StorageDead(_13); StorageDead(_11); - StorageDead(_10); diff --git a/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-unwind.diff index 7f768a9f834d9..df3a7793bfdd3 100644 --- a/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-unwind.diff +++ b/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-unwind.diff @@ -86,7 +86,7 @@ } bb6: { -- StorageLive(_16); + StorageLive(_16); _16 = copy ((_11 as Some).0: usize); StorageLive(_17); - StorageLive(_18); @@ -116,7 +116,7 @@ StorageDead(_17); - StorageDead(_18); - _10 = const (); -- StorageDead(_16); + StorageDead(_16); StorageDead(_13); StorageDead(_11); - StorageDead(_10); diff --git a/tests/mir-opt/copy-prop/issue_141649.main.CopyProp.panic-abort.diff b/tests/mir-opt/copy-prop/issue_141649.main.CopyProp.panic-abort.diff new file mode 100644 index 0000000000000..c68bfb1b8e94a --- /dev/null +++ b/tests/mir-opt/copy-prop/issue_141649.main.CopyProp.panic-abort.diff @@ -0,0 +1,142 @@ +- // MIR for `main` before CopyProp ++ // MIR for `main` after CopyProp + + fn main() -> () { + let mut _0: (); + let _1: (); + let _2: main::S; + let _3: (); + let mut _4: main::S; + let _5: (); + let _6: main::S; + let _7: (); + let mut _8: main::S; + let _9: (); + let _10: main::S; + let _12: &main::S; + let mut _13: &main::S; + let _14: (); + let mut _15: main::S; + let _16: (); + let _17: main::C; + let _18: (); + let mut _19: main::C; + let _20: main::C; + let _21: (); + let mut _22: main::C; + scope 1 { + debug s1 => _2; + } + scope 2 { + debug s2 => _6; + } + scope 3 { + debug s3 => _10; + let _11: &main::S; + scope 4 { + debug borrowed_s3 => _11; + } + } + scope 5 { + debug c1 => _17; + } + scope 6 { + debug c2 => _20; + } + + bb0: { +- StorageLive(_1); + StorageLive(_2); + _2 = S(const 1_usize, const 2_usize); + StorageLive(_3); +- StorageLive(_4); +- _4 = move _2; +- _3 = std::mem::drop::(move _4) -> [return: bb1, unwind unreachable]; ++ _3 = std::mem::drop::(move _2) -> [return: bb1, unwind unreachable]; + } + + bb1: { +- StorageDead(_4); + StorageDead(_3); +- _1 = const (); + StorageDead(_2); +- StorageDead(_1); +- StorageLive(_5); + StorageLive(_6); + _6 = S(const 3_usize, const 4_usize); + StorageLive(_7); +- StorageLive(_8); +- _8 = move _6; +- _7 = std::mem::drop::(move _8) -> [return: bb2, unwind unreachable]; ++ _7 = std::mem::drop::(move _6) -> [return: bb2, unwind unreachable]; + } + + bb2: { +- StorageDead(_8); + StorageDead(_7); +- _5 = const (); + StorageDead(_6); +- StorageDead(_5); +- StorageLive(_9); + StorageLive(_10); + _10 = S(const 5_usize, const 6_usize); + StorageLive(_11); + _11 = &_10; + StorageLive(_12); +- StorageLive(_13); +- _13 = copy _11; +- _12 = opaque::<&S>(move _13) -> [return: bb3, unwind unreachable]; ++ _12 = opaque::<&S>(copy _11) -> [return: bb3, unwind unreachable]; + } + + bb3: { +- StorageDead(_13); + StorageDead(_12); + StorageLive(_14); +- StorageLive(_15); +- _15 = move _10; +- _14 = std::mem::drop::(move _15) -> [return: bb4, unwind unreachable]; ++ _14 = std::mem::drop::(move _10) -> [return: bb4, unwind unreachable]; + } + + bb4: { +- StorageDead(_15); + StorageDead(_14); +- _9 = const (); + StorageDead(_11); + StorageDead(_10); +- StorageDead(_9); +- StorageLive(_16); + StorageLive(_17); + _17 = C(const 1_usize, const 2_usize); + StorageLive(_18); +- StorageLive(_19); +- _19 = copy _17; +- _18 = std::mem::drop::(move _19) -> [return: bb5, unwind unreachable]; ++ _18 = std::mem::drop::(copy _17) -> [return: bb5, unwind unreachable]; + } + + bb5: { +- StorageDead(_19); + StorageDead(_18); +- _16 = const (); + StorageDead(_17); +- StorageDead(_16); + StorageLive(_20); + _20 = C(const 3_usize, const 4_usize); + StorageLive(_21); +- StorageLive(_22); +- _22 = copy _20; +- _21 = std::mem::drop::(move _22) -> [return: bb6, unwind unreachable]; ++ _21 = std::mem::drop::(copy _20) -> [return: bb6, unwind unreachable]; + } + + bb6: { +- StorageDead(_22); + StorageDead(_21); + _0 = const (); + StorageDead(_20); + return; + } + } + diff --git a/tests/mir-opt/copy-prop/issue_141649.main.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/issue_141649.main.CopyProp.panic-unwind.diff new file mode 100644 index 0000000000000..3535a9840f685 --- /dev/null +++ b/tests/mir-opt/copy-prop/issue_141649.main.CopyProp.panic-unwind.diff @@ -0,0 +1,142 @@ +- // MIR for `main` before CopyProp ++ // MIR for `main` after CopyProp + + fn main() -> () { + let mut _0: (); + let _1: (); + let _2: main::S; + let _3: (); + let mut _4: main::S; + let _5: (); + let _6: main::S; + let _7: (); + let mut _8: main::S; + let _9: (); + let _10: main::S; + let _12: &main::S; + let mut _13: &main::S; + let _14: (); + let mut _15: main::S; + let _16: (); + let _17: main::C; + let _18: (); + let mut _19: main::C; + let _20: main::C; + let _21: (); + let mut _22: main::C; + scope 1 { + debug s1 => _2; + } + scope 2 { + debug s2 => _6; + } + scope 3 { + debug s3 => _10; + let _11: &main::S; + scope 4 { + debug borrowed_s3 => _11; + } + } + scope 5 { + debug c1 => _17; + } + scope 6 { + debug c2 => _20; + } + + bb0: { +- StorageLive(_1); + StorageLive(_2); + _2 = S(const 1_usize, const 2_usize); + StorageLive(_3); +- StorageLive(_4); +- _4 = move _2; +- _3 = std::mem::drop::(move _4) -> [return: bb1, unwind continue]; ++ _3 = std::mem::drop::(move _2) -> [return: bb1, unwind continue]; + } + + bb1: { +- StorageDead(_4); + StorageDead(_3); +- _1 = const (); + StorageDead(_2); +- StorageDead(_1); +- StorageLive(_5); + StorageLive(_6); + _6 = S(const 3_usize, const 4_usize); + StorageLive(_7); +- StorageLive(_8); +- _8 = move _6; +- _7 = std::mem::drop::(move _8) -> [return: bb2, unwind continue]; ++ _7 = std::mem::drop::(move _6) -> [return: bb2, unwind continue]; + } + + bb2: { +- StorageDead(_8); + StorageDead(_7); +- _5 = const (); + StorageDead(_6); +- StorageDead(_5); +- StorageLive(_9); + StorageLive(_10); + _10 = S(const 5_usize, const 6_usize); + StorageLive(_11); + _11 = &_10; + StorageLive(_12); +- StorageLive(_13); +- _13 = copy _11; +- _12 = opaque::<&S>(move _13) -> [return: bb3, unwind continue]; ++ _12 = opaque::<&S>(copy _11) -> [return: bb3, unwind continue]; + } + + bb3: { +- StorageDead(_13); + StorageDead(_12); + StorageLive(_14); +- StorageLive(_15); +- _15 = move _10; +- _14 = std::mem::drop::(move _15) -> [return: bb4, unwind continue]; ++ _14 = std::mem::drop::(move _10) -> [return: bb4, unwind continue]; + } + + bb4: { +- StorageDead(_15); + StorageDead(_14); +- _9 = const (); + StorageDead(_11); + StorageDead(_10); +- StorageDead(_9); +- StorageLive(_16); + StorageLive(_17); + _17 = C(const 1_usize, const 2_usize); + StorageLive(_18); +- StorageLive(_19); +- _19 = copy _17; +- _18 = std::mem::drop::(move _19) -> [return: bb5, unwind continue]; ++ _18 = std::mem::drop::(copy _17) -> [return: bb5, unwind continue]; + } + + bb5: { +- StorageDead(_19); + StorageDead(_18); +- _16 = const (); + StorageDead(_17); +- StorageDead(_16); + StorageLive(_20); + _20 = C(const 3_usize, const 4_usize); + StorageLive(_21); +- StorageLive(_22); +- _22 = copy _20; +- _21 = std::mem::drop::(move _22) -> [return: bb6, unwind continue]; ++ _21 = std::mem::drop::(copy _20) -> [return: bb6, unwind continue]; + } + + bb6: { +- StorageDead(_22); + StorageDead(_21); + _0 = const (); + StorageDead(_20); + return; + } + } + diff --git a/tests/mir-opt/copy-prop/issue_141649.rs b/tests/mir-opt/copy-prop/issue_141649.rs new file mode 100644 index 0000000000000..e3b9062d65101 --- /dev/null +++ b/tests/mir-opt/copy-prop/issue_141649.rs @@ -0,0 +1,38 @@ +// skip-filecheck +// EMIT_MIR_FOR_EACH_PANIC_STRATEGY +//@ test-mir-pass: CopyProp + +// EMIT_MIR issue_141649.main.CopyProp.diff +fn main() { + struct S(usize, usize); + { + let s1 = S(1, 2); + drop(s1); + } + { + let s2 = S(3, 4); + drop(s2); + } + { + let s3 = S(5, 6); + let borrowed_s3 = &s3; + opaque(borrowed_s3); + drop(s3); + } + + #[derive(Clone, Copy)] + struct C(usize, usize); + { + let c1 = C(1, 2); + drop(c1); + } + { + let c2 = C(3, 4); + drop(c2); + } +} + +#[inline(never)] +fn opaque(a: T) -> T { + a +} diff --git a/tests/mir-opt/copy-prop/issue_141649_debug.main.CopyProp.panic-abort.diff b/tests/mir-opt/copy-prop/issue_141649_debug.main.CopyProp.panic-abort.diff new file mode 100644 index 0000000000000..93629b0f9f3f9 --- /dev/null +++ b/tests/mir-opt/copy-prop/issue_141649_debug.main.CopyProp.panic-abort.diff @@ -0,0 +1,100 @@ +- // MIR for `main` before CopyProp ++ // MIR for `main` after CopyProp + + fn main() -> () { + let mut _0: (); + let _1: (); + let _2: main::S; + let _3: (); + let mut _4: main::S; + let _5: (); + let _6: main::S; + let _7: (); + let mut _8: main::S; + let _9: (); + let _10: main::C; + let _11: (); + let mut _12: main::C; + let _13: main::C; + let _14: (); + let mut _15: main::C; + scope 1 { + debug s1 => _2; + } + scope 2 { + debug s2 => _6; + } + scope 3 { + debug c1 => _10; + } + scope 4 { + debug c2 => _13; + } + + bb0: { +- StorageLive(_1); +- StorageLive(_2); + _2 = S(const 1_usize, const 2_usize); + StorageLive(_3); +- StorageLive(_4); +- _4 = move _2; +- _3 = std::mem::drop::(move _4) -> [return: bb1, unwind unreachable]; ++ _3 = std::mem::drop::(move _2) -> [return: bb1, unwind unreachable]; + } + + bb1: { +- StorageDead(_4); + StorageDead(_3); +- _1 = const (); +- StorageDead(_2); +- StorageDead(_1); +- StorageLive(_5); +- StorageLive(_6); + _6 = S(const 3_usize, const 4_usize); + StorageLive(_7); +- StorageLive(_8); +- _8 = move _6; +- _7 = std::mem::drop::(move _8) -> [return: bb2, unwind unreachable]; ++ _7 = std::mem::drop::(move _6) -> [return: bb2, unwind unreachable]; + } + + bb2: { +- StorageDead(_8); + StorageDead(_7); +- _5 = const (); +- StorageDead(_6); +- StorageDead(_5); +- StorageLive(_9); +- StorageLive(_10); + _10 = C(const 1_usize, const 2_usize); + StorageLive(_11); +- StorageLive(_12); +- _12 = copy _10; +- _11 = std::mem::drop::(move _12) -> [return: bb3, unwind unreachable]; ++ _11 = std::mem::drop::(copy _10) -> [return: bb3, unwind unreachable]; + } + + bb3: { +- StorageDead(_12); + StorageDead(_11); +- _9 = const (); +- StorageDead(_10); +- StorageDead(_9); +- StorageLive(_13); + _13 = C(const 3_usize, const 4_usize); + StorageLive(_14); +- StorageLive(_15); +- _15 = copy _13; +- _14 = std::mem::drop::(move _15) -> [return: bb4, unwind unreachable]; ++ _14 = std::mem::drop::(copy _13) -> [return: bb4, unwind unreachable]; + } + + bb4: { +- StorageDead(_15); + StorageDead(_14); + _0 = const (); +- StorageDead(_13); + return; + } + } + diff --git a/tests/mir-opt/copy-prop/issue_141649_debug.main.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/issue_141649_debug.main.CopyProp.panic-unwind.diff new file mode 100644 index 0000000000000..e02fe72a47a7b --- /dev/null +++ b/tests/mir-opt/copy-prop/issue_141649_debug.main.CopyProp.panic-unwind.diff @@ -0,0 +1,100 @@ +- // MIR for `main` before CopyProp ++ // MIR for `main` after CopyProp + + fn main() -> () { + let mut _0: (); + let _1: (); + let _2: main::S; + let _3: (); + let mut _4: main::S; + let _5: (); + let _6: main::S; + let _7: (); + let mut _8: main::S; + let _9: (); + let _10: main::C; + let _11: (); + let mut _12: main::C; + let _13: main::C; + let _14: (); + let mut _15: main::C; + scope 1 { + debug s1 => _2; + } + scope 2 { + debug s2 => _6; + } + scope 3 { + debug c1 => _10; + } + scope 4 { + debug c2 => _13; + } + + bb0: { +- StorageLive(_1); +- StorageLive(_2); + _2 = S(const 1_usize, const 2_usize); + StorageLive(_3); +- StorageLive(_4); +- _4 = move _2; +- _3 = std::mem::drop::(move _4) -> [return: bb1, unwind continue]; ++ _3 = std::mem::drop::(move _2) -> [return: bb1, unwind continue]; + } + + bb1: { +- StorageDead(_4); + StorageDead(_3); +- _1 = const (); +- StorageDead(_2); +- StorageDead(_1); +- StorageLive(_5); +- StorageLive(_6); + _6 = S(const 3_usize, const 4_usize); + StorageLive(_7); +- StorageLive(_8); +- _8 = move _6; +- _7 = std::mem::drop::(move _8) -> [return: bb2, unwind continue]; ++ _7 = std::mem::drop::(move _6) -> [return: bb2, unwind continue]; + } + + bb2: { +- StorageDead(_8); + StorageDead(_7); +- _5 = const (); +- StorageDead(_6); +- StorageDead(_5); +- StorageLive(_9); +- StorageLive(_10); + _10 = C(const 1_usize, const 2_usize); + StorageLive(_11); +- StorageLive(_12); +- _12 = copy _10; +- _11 = std::mem::drop::(move _12) -> [return: bb3, unwind continue]; ++ _11 = std::mem::drop::(copy _10) -> [return: bb3, unwind continue]; + } + + bb3: { +- StorageDead(_12); + StorageDead(_11); +- _9 = const (); +- StorageDead(_10); +- StorageDead(_9); +- StorageLive(_13); + _13 = C(const 3_usize, const 4_usize); + StorageLive(_14); +- StorageLive(_15); +- _15 = copy _13; +- _14 = std::mem::drop::(move _15) -> [return: bb4, unwind continue]; ++ _14 = std::mem::drop::(copy _13) -> [return: bb4, unwind continue]; + } + + bb4: { +- StorageDead(_15); + StorageDead(_14); + _0 = const (); +- StorageDead(_13); + return; + } + } + diff --git a/tests/mir-opt/copy-prop/issue_141649_debug.rs b/tests/mir-opt/copy-prop/issue_141649_debug.rs new file mode 100644 index 0000000000000..5769118700ca1 --- /dev/null +++ b/tests/mir-opt/copy-prop/issue_141649_debug.rs @@ -0,0 +1,29 @@ +// skip-filecheck +// EMIT_MIR_FOR_EACH_PANIC_STRATEGY +//! Tests that in lower opt levels we remove (more) storage statements using a simpler strategy. +//@ test-mir-pass: CopyProp +//@ compile-flags: -Copt-level=0 + +// EMIT_MIR issue_141649_debug.main.CopyProp.diff +fn main() { + struct S(usize, usize); + { + let s1 = S(1, 2); + drop(s1); + } + { + let s2 = S(3, 4); + drop(s2); + } + + #[derive(Clone, Copy)] + struct C(usize, usize); + { + let c1 = C(1, 2); + drop(c1); + } + { + let c2 = C(3, 4); + drop(c2); + } +} diff --git a/tests/mir-opt/copy-prop/reborrow.demiraw.CopyProp.panic-abort.diff b/tests/mir-opt/copy-prop/reborrow.demiraw.CopyProp.panic-abort.diff index 676c5cee34387..ccd1e1caf003a 100644 --- a/tests/mir-opt/copy-prop/reborrow.demiraw.CopyProp.panic-abort.diff +++ b/tests/mir-opt/copy-prop/reborrow.demiraw.CopyProp.panic-abort.diff @@ -22,7 +22,7 @@ } bb0: { -- StorageLive(_2); + StorageLive(_2); _2 = &raw mut _1; StorageLive(_3); StorageLive(_4); @@ -44,7 +44,7 @@ _0 = const (); - StorageDead(_5); StorageDead(_3); -- StorageDead(_2); + StorageDead(_2); return; } } diff --git a/tests/mir-opt/copy-prop/reborrow.demiraw.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/reborrow.demiraw.CopyProp.panic-unwind.diff index ca2232ce54a1f..6cfb4af1fcf2e 100644 --- a/tests/mir-opt/copy-prop/reborrow.demiraw.CopyProp.panic-unwind.diff +++ b/tests/mir-opt/copy-prop/reborrow.demiraw.CopyProp.panic-unwind.diff @@ -22,7 +22,7 @@ } bb0: { -- StorageLive(_2); + StorageLive(_2); _2 = &raw mut _1; StorageLive(_3); StorageLive(_4); @@ -44,7 +44,7 @@ _0 = const (); - StorageDead(_5); StorageDead(_3); -- StorageDead(_2); + StorageDead(_2); return; } } diff --git a/tests/mir-opt/copy-prop/reborrow.miraw.CopyProp.panic-abort.diff b/tests/mir-opt/copy-prop/reborrow.miraw.CopyProp.panic-abort.diff index 1968696905fc7..b5f6a6e22f29f 100644 --- a/tests/mir-opt/copy-prop/reborrow.miraw.CopyProp.panic-abort.diff +++ b/tests/mir-opt/copy-prop/reborrow.miraw.CopyProp.panic-abort.diff @@ -21,7 +21,7 @@ } bb0: { -- StorageLive(_2); + StorageLive(_2); _2 = &raw mut _1; StorageLive(_3); _3 = &raw mut (*_2); @@ -40,7 +40,7 @@ _0 = const (); - StorageDead(_4); StorageDead(_3); -- StorageDead(_2); + StorageDead(_2); return; } } diff --git a/tests/mir-opt/copy-prop/reborrow.miraw.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/reborrow.miraw.CopyProp.panic-unwind.diff index 9a3c9665bc8f3..c28f7d037fd1d 100644 --- a/tests/mir-opt/copy-prop/reborrow.miraw.CopyProp.panic-unwind.diff +++ b/tests/mir-opt/copy-prop/reborrow.miraw.CopyProp.panic-unwind.diff @@ -21,7 +21,7 @@ } bb0: { -- StorageLive(_2); + StorageLive(_2); _2 = &raw mut _1; StorageLive(_3); _3 = &raw mut (*_2); @@ -40,7 +40,7 @@ _0 = const (); - StorageDead(_4); StorageDead(_3); -- StorageDead(_2); + StorageDead(_2); return; } } diff --git a/tests/mir-opt/copy-prop/reborrow.remut.CopyProp.panic-abort.diff b/tests/mir-opt/copy-prop/reborrow.remut.CopyProp.panic-abort.diff index 2026c1982f299..aebd98d85b54c 100644 --- a/tests/mir-opt/copy-prop/reborrow.remut.CopyProp.panic-abort.diff +++ b/tests/mir-opt/copy-prop/reborrow.remut.CopyProp.panic-abort.diff @@ -21,7 +21,7 @@ } bb0: { -- StorageLive(_2); + StorageLive(_2); _2 = &mut _1; StorageLive(_3); _3 = &mut (*_2); @@ -40,7 +40,7 @@ _0 = const (); - StorageDead(_4); StorageDead(_3); -- StorageDead(_2); + StorageDead(_2); return; } } diff --git a/tests/mir-opt/copy-prop/reborrow.remut.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/reborrow.remut.CopyProp.panic-unwind.diff index 67763fdce6676..a836d439c3eac 100644 --- a/tests/mir-opt/copy-prop/reborrow.remut.CopyProp.panic-unwind.diff +++ b/tests/mir-opt/copy-prop/reborrow.remut.CopyProp.panic-unwind.diff @@ -21,7 +21,7 @@ } bb0: { -- StorageLive(_2); + StorageLive(_2); _2 = &mut _1; StorageLive(_3); _3 = &mut (*_2); @@ -40,7 +40,7 @@ _0 = const (); - StorageDead(_4); StorageDead(_3); -- StorageDead(_2); + StorageDead(_2); return; } } diff --git a/tests/mir-opt/copy-prop/reborrow.reraw.CopyProp.panic-abort.diff b/tests/mir-opt/copy-prop/reborrow.reraw.CopyProp.panic-abort.diff index dfc8dd0975638..38801bc7811a8 100644 --- a/tests/mir-opt/copy-prop/reborrow.reraw.CopyProp.panic-abort.diff +++ b/tests/mir-opt/copy-prop/reborrow.reraw.CopyProp.panic-abort.diff @@ -21,7 +21,7 @@ } bb0: { -- StorageLive(_2); + StorageLive(_2); _2 = &mut _1; StorageLive(_3); _3 = &raw mut (*_2); @@ -40,7 +40,7 @@ _0 = const (); - StorageDead(_4); StorageDead(_3); -- StorageDead(_2); + StorageDead(_2); return; } } diff --git a/tests/mir-opt/copy-prop/reborrow.reraw.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/reborrow.reraw.CopyProp.panic-unwind.diff index becc425632104..f7af4681014b3 100644 --- a/tests/mir-opt/copy-prop/reborrow.reraw.CopyProp.panic-unwind.diff +++ b/tests/mir-opt/copy-prop/reborrow.reraw.CopyProp.panic-unwind.diff @@ -21,7 +21,7 @@ } bb0: { -- StorageLive(_2); + StorageLive(_2); _2 = &mut _1; StorageLive(_3); _3 = &raw mut (*_2); @@ -40,7 +40,7 @@ _0 = const (); - StorageDead(_4); StorageDead(_3); -- StorageDead(_2); + StorageDead(_2); return; } } diff --git a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-abort.diff b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-abort.diff index 25ffff619e60b..66f97c71fb860 100644 --- a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-abort.diff @@ -78,9 +78,8 @@ - _12 = AlignOf(()); + _11 = const 0_usize; + _12 = const 1_usize; - StorageLive(_14); StorageLive(_16); - StorageLive(_17); + StorageLive(_14); StorageLive(_19); _19 = const false; - switchInt(move _19) -> [0: bb6, otherwise: bb5]; @@ -103,15 +102,16 @@ } bb4: { + StorageLive(_17); _17 = copy ((_15 as Ok).0: std::ptr::NonNull<[u8]>); StorageLive(_22); _22 = copy _17 as *mut [u8] (Transmute); _13 = copy _22 as *mut u8 (PtrToPtr); StorageDead(_22); - StorageDead(_15); StorageDead(_17); - StorageDead(_16); + StorageDead(_15); StorageDead(_14); + StorageDead(_16); _3 = ShallowInitBox(move _13, ()); StorageDead(_13); StorageDead(_12); diff --git a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff index 839b53e3b0b3b..77be3948cdb7b 100644 --- a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff @@ -78,9 +78,8 @@ - _12 = AlignOf(()); + _11 = const 0_usize; + _12 = const 1_usize; - StorageLive(_14); StorageLive(_16); - StorageLive(_17); + StorageLive(_14); StorageLive(_19); _19 = const false; - switchInt(move _19) -> [0: bb6, otherwise: bb5]; @@ -103,15 +102,16 @@ } bb4: { + StorageLive(_17); _17 = copy ((_15 as Ok).0: std::ptr::NonNull<[u8]>); StorageLive(_22); _22 = copy _17 as *mut [u8] (Transmute); _13 = copy _22 as *mut u8 (PtrToPtr); StorageDead(_22); - StorageDead(_15); StorageDead(_17); - StorageDead(_16); + StorageDead(_15); StorageDead(_14); + StorageDead(_16); _3 = ShallowInitBox(move _13, ()); StorageDead(_13); StorageDead(_12); diff --git a/tests/mir-opt/jump_threading.identity.JumpThreading.panic-abort.diff b/tests/mir-opt/jump_threading.identity.JumpThreading.panic-abort.diff index 79599f856115d..09811088d25f6 100644 --- a/tests/mir-opt/jump_threading.identity.JumpThreading.panic-abort.diff +++ b/tests/mir-opt/jump_threading.identity.JumpThreading.panic-abort.diff @@ -47,8 +47,6 @@ StorageLive(_4); _4 = copy _1; StorageLive(_10); - StorageLive(_11); - StorageLive(_12); _10 = discriminant(_4); switchInt(move _10) -> [0: bb7, 1: bb6, otherwise: bb1]; } @@ -92,8 +90,6 @@ } bb5: { - StorageDead(_12); - StorageDead(_11); StorageDead(_10); StorageDead(_4); _5 = discriminant(_3); @@ -102,24 +98,26 @@ } bb6: { + StorageLive(_12); _12 = move ((_4 as Err).0: i32); StorageLive(_13); _13 = Result::::Err(copy _12); _3 = ControlFlow::, i32>::Break(move _13); StorageDead(_13); + StorageDead(_12); - goto -> bb5; + goto -> bb8; } bb7: { + StorageLive(_11); _11 = move ((_4 as Ok).0: i32); _3 = ControlFlow::, i32>::Continue(copy _11); + StorageDead(_11); goto -> bb5; + } + + bb8: { -+ StorageDead(_12); -+ StorageDead(_11); + StorageDead(_10); + StorageDead(_4); + _5 = discriminant(_3); diff --git a/tests/mir-opt/jump_threading.identity.JumpThreading.panic-unwind.diff b/tests/mir-opt/jump_threading.identity.JumpThreading.panic-unwind.diff index 79599f856115d..09811088d25f6 100644 --- a/tests/mir-opt/jump_threading.identity.JumpThreading.panic-unwind.diff +++ b/tests/mir-opt/jump_threading.identity.JumpThreading.panic-unwind.diff @@ -47,8 +47,6 @@ StorageLive(_4); _4 = copy _1; StorageLive(_10); - StorageLive(_11); - StorageLive(_12); _10 = discriminant(_4); switchInt(move _10) -> [0: bb7, 1: bb6, otherwise: bb1]; } @@ -92,8 +90,6 @@ } bb5: { - StorageDead(_12); - StorageDead(_11); StorageDead(_10); StorageDead(_4); _5 = discriminant(_3); @@ -102,24 +98,26 @@ } bb6: { + StorageLive(_12); _12 = move ((_4 as Err).0: i32); StorageLive(_13); _13 = Result::::Err(copy _12); _3 = ControlFlow::, i32>::Break(move _13); StorageDead(_13); + StorageDead(_12); - goto -> bb5; + goto -> bb8; } bb7: { + StorageLive(_11); _11 = move ((_4 as Ok).0: i32); _3 = ControlFlow::, i32>::Continue(copy _11); + StorageDead(_11); goto -> bb5; + } + + bb8: { -+ StorageDead(_12); -+ StorageDead(_11); + StorageDead(_10); + StorageDead(_4); + _5 = discriminant(_3); diff --git a/tests/mir-opt/pre-codegen/derived_ord.demo_le.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/derived_ord.demo_le.PreCodegen.after.mir index 8746cb0899166..5cf1c682cbbf8 100644 --- a/tests/mir-opt/pre-codegen/derived_ord.demo_le.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/derived_ord.demo_le.PreCodegen.after.mir @@ -37,7 +37,6 @@ fn demo_le(_1: &MultiField, _2: &MultiField) -> bool { } bb0: { - StorageLive(_12); StorageLive(_11); StorageLive(_5); StorageLive(_6); @@ -80,13 +79,14 @@ fn demo_le(_1: &MultiField, _2: &MultiField) -> bool { } bb3: { + StorageLive(_12); _12 = move ((_11 as Some).0: std::cmp::Ordering); StorageLive(_13); _13 = discriminant(_12); _0 = Le(move _13, const 0_i8); StorageDead(_13); - StorageDead(_11); StorageDead(_12); + StorageDead(_11); return; } } diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff index 027c71dfaae46..5947404d9565c 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff @@ -84,13 +84,13 @@ StorageDead(_8); StorageDead(_7); StorageLive(_12); - StorageLive(_16); _12 = discriminant(_6); switchInt(move _12) -> [0: bb6, 1: bb5, otherwise: bb1]; } bb5: { StorageLive(_15); + StorageLive(_16); _16 = &_13; _15 = copy _16 as &dyn std::fmt::Debug (PointerCoercion(Unsize, Implicit)); _14 = result::unwrap_failed(const "called `Result::unwrap()` on an `Err` value", move _15) -> unwind unreachable; @@ -98,7 +98,6 @@ bb6: { _5 = move ((_6 as Ok).0: std::ptr::NonNull<[u8]>); - StorageDead(_16); StorageDead(_12); StorageDead(_6); _4 = copy _5 as *mut [u8] (Transmute); diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff index ebf305a6f1b12..30da78e298bc9 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff @@ -84,13 +84,13 @@ StorageDead(_8); StorageDead(_7); StorageLive(_12); - StorageLive(_16); _12 = discriminant(_6); switchInt(move _12) -> [0: bb6, 1: bb5, otherwise: bb1]; } bb5: { StorageLive(_15); + StorageLive(_16); _16 = &_13; _15 = copy _16 as &dyn std::fmt::Debug (PointerCoercion(Unsize, Implicit)); _14 = result::unwrap_failed(const "called `Result::unwrap()` on an `Err` value", move _15) -> unwind unreachable; @@ -98,7 +98,6 @@ bb6: { _5 = move ((_6 as Ok).0: std::ptr::NonNull<[u8]>); - StorageDead(_16); StorageDead(_12); StorageDead(_6); _4 = copy _5 as *mut [u8] (Transmute); diff --git a/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir index d22ea54004c91..0f1e83c3b8079 100644 --- a/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir @@ -54,7 +54,6 @@ fn mapped(_1: impl Iterator, _2: impl Fn(T) -> U) -> () { bb2: { StorageLive(_13); _5 = &mut _4; - StorageLive(_8); StorageLive(_7); StorageLive(_6); _6 = &mut (_4.0: impl Iterator); @@ -63,18 +62,17 @@ fn mapped(_1: impl Iterator, _2: impl Fn(T) -> U) -> () { bb3: { StorageDead(_6); + StorageLive(_8); _8 = &mut (_4.1: impl Fn(T) -> U); StorageLive(_9); - StorageLive(_10); _9 = discriminant(_7); switchInt(move _9) -> [0: bb4, 1: bb6, otherwise: bb9]; } bb4: { - StorageDead(_10); StorageDead(_9); - StorageDead(_7); StorageDead(_8); + StorageDead(_7); StorageDead(_13); drop(_4) -> [return: bb5, unwind continue]; } @@ -85,6 +83,7 @@ fn mapped(_1: impl Iterator, _2: impl Fn(T) -> U) -> () { } bb6: { + StorageLive(_10); _10 = move ((_7 as Some).0: T); StorageLive(_12); StorageLive(_11); @@ -98,8 +97,8 @@ fn mapped(_1: impl Iterator, _2: impl Fn(T) -> U) -> () { StorageDead(_12); StorageDead(_10); StorageDead(_9); - StorageDead(_7); StorageDead(_8); + StorageDead(_7); _14 = move ((_13 as Some).0: U); _15 = opaque::(move _14) -> [return: bb8, unwind: bb10]; } diff --git a/tests/mir-opt/pre-codegen/simple_option_map.map_via_question_mark.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/simple_option_map.map_via_question_mark.PreCodegen.after.mir index b921b96966b29..fae561ae4b927 100644 --- a/tests/mir-opt/pre-codegen/simple_option_map.map_via_question_mark.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/simple_option_map.map_via_question_mark.PreCodegen.after.mir @@ -29,13 +29,11 @@ fn map_via_question_mark(_1: Option) -> Option { StorageLive(_6); StorageLive(_4); StorageLive(_2); - StorageLive(_3); _2 = discriminant(_1); switchInt(move _2) -> [0: bb1, 1: bb2, otherwise: bb4]; } bb1: { - StorageDead(_3); StorageDead(_2); _0 = const Option::::None; StorageDead(_6); @@ -44,6 +42,7 @@ fn map_via_question_mark(_1: Option) -> Option { } bb2: { + StorageLive(_3); _3 = copy ((_1 as Some).0: i32); _4 = ControlFlow::, i32>::Continue(copy _3); StorageDead(_3); diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir index 6fb1637a6e02f..8e9c0b2b251e5 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir @@ -36,7 +36,6 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> StorageLive(_11); StorageLive(_5); _5 = &raw mut (*_1); - StorageLive(_8); StorageLive(_6); _6 = PtrMetadata(copy _1); _7 = as SliceIndex<[T]>>::get_unchecked_mut::precondition_check(copy _3, copy _4, move _6) -> [return: bb1, unwind unreachable]; @@ -44,10 +43,11 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> bb1: { StorageDead(_6); + StorageLive(_8); _8 = SubUnchecked(copy _4, copy _3); StorageLive(_9); - StorageLive(_10); _9 = copy _5 as *mut u32 (PtrToPtr); + StorageLive(_10); _10 = Offset(copy _9, copy _3); _11 = *mut [u32] from (copy _10, copy _8); StorageDead(_10); diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir index 6fb1637a6e02f..8e9c0b2b251e5 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir @@ -36,7 +36,6 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> StorageLive(_11); StorageLive(_5); _5 = &raw mut (*_1); - StorageLive(_8); StorageLive(_6); _6 = PtrMetadata(copy _1); _7 = as SliceIndex<[T]>>::get_unchecked_mut::precondition_check(copy _3, copy _4, move _6) -> [return: bb1, unwind unreachable]; @@ -44,10 +43,11 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> bb1: { StorageDead(_6); + StorageLive(_8); _8 = SubUnchecked(copy _4, copy _3); StorageLive(_9); - StorageLive(_10); _9 = copy _5 as *mut u32 (PtrToPtr); + StorageLive(_10); _10 = Offset(copy _9, copy _3); _11 = *mut [u32] from (copy _10, copy _8); StorageDead(_10); diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-abort.mir index ad1ca5dff43a9..4b488b007f4d9 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-abort.mir @@ -31,7 +31,6 @@ fn slice_ptr_get_unchecked_range(_1: *const [u32], _2: std::ops::Range) - bb0: { _3 = move (_2.0: usize); _4 = move (_2.1: usize); - StorageLive(_7); StorageLive(_5); _5 = PtrMetadata(copy _1); _6 = as SliceIndex<[T]>>::get_unchecked::precondition_check(copy _3, copy _4, move _5) -> [return: bb1, unwind unreachable]; @@ -39,10 +38,11 @@ fn slice_ptr_get_unchecked_range(_1: *const [u32], _2: std::ops::Range) - bb1: { StorageDead(_5); + StorageLive(_7); _7 = SubUnchecked(copy _4, copy _3); StorageLive(_8); - StorageLive(_9); _8 = copy _1 as *const u32 (PtrToPtr); + StorageLive(_9); _9 = Offset(copy _8, copy _3); _0 = *const [u32] from (copy _9, copy _7); StorageDead(_9); diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-unwind.mir index ad1ca5dff43a9..4b488b007f4d9 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-unwind.mir @@ -31,7 +31,6 @@ fn slice_ptr_get_unchecked_range(_1: *const [u32], _2: std::ops::Range) - bb0: { _3 = move (_2.0: usize); _4 = move (_2.1: usize); - StorageLive(_7); StorageLive(_5); _5 = PtrMetadata(copy _1); _6 = as SliceIndex<[T]>>::get_unchecked::precondition_check(copy _3, copy _4, move _5) -> [return: bb1, unwind unreachable]; @@ -39,10 +38,11 @@ fn slice_ptr_get_unchecked_range(_1: *const [u32], _2: std::ops::Range) - bb1: { StorageDead(_5); + StorageLive(_7); _7 = SubUnchecked(copy _4, copy _3); StorageLive(_8); - StorageLive(_9); _8 = copy _1 as *const u32 (PtrToPtr); + StorageLive(_9); _9 = Offset(copy _8, copy _3); _0 = *const [u32] from (copy _9, copy _7); StorageDead(_9); diff --git a/tests/mir-opt/separate_const_switch.identity.JumpThreading.diff b/tests/mir-opt/separate_const_switch.identity.JumpThreading.diff index ce9d812701a8f..7d5c88d5cde2c 100644 --- a/tests/mir-opt/separate_const_switch.identity.JumpThreading.diff +++ b/tests/mir-opt/separate_const_switch.identity.JumpThreading.diff @@ -39,8 +39,6 @@ bb0: { StorageLive(_2); StorageLive(_6); - StorageLive(_7); - StorageLive(_8); _6 = discriminant(_1); switchInt(move _6) -> [0: bb6, 1: bb5, otherwise: bb1]; } @@ -65,8 +63,6 @@ } bb4: { - StorageDead(_8); - StorageDead(_7); StorageDead(_6); _3 = discriminant(_2); - switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1]; @@ -74,24 +70,26 @@ } bb5: { + StorageLive(_8); _8 = copy ((_1 as Err).0: i32); StorageLive(_9); _9 = Result::::Err(copy _8); _2 = ControlFlow::, i32>::Break(move _9); StorageDead(_9); + StorageDead(_8); - goto -> bb4; + goto -> bb7; } bb6: { + StorageLive(_7); _7 = copy ((_1 as Ok).0: i32); _2 = ControlFlow::, i32>::Continue(copy _7); + StorageDead(_7); goto -> bb4; + } + + bb7: { -+ StorageDead(_8); -+ StorageDead(_7); + StorageDead(_6); + _3 = discriminant(_2); + goto -> bb3; diff --git a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-abort.diff b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-abort.diff index ff1bc58524bc2..c590c1aad4477 100644 --- a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-abort.diff +++ b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-abort.diff @@ -35,7 +35,9 @@ } bb2: { + StorageLive(_6); _6 = copy (((_1.0: std::option::Option) as Some).0: u8); + StorageDead(_6); goto -> bb3; } diff --git a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-unwind.diff b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-unwind.diff index 2c289c664754a..9dd0195c86c97 100644 --- a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-unwind.diff +++ b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-unwind.diff @@ -35,7 +35,9 @@ } bb2: { + StorageLive(_6); _6 = copy (((_1.0: std::option::Option) as Some).0: u8); + StorageDead(_6); goto -> bb3; }