From 9c5d0c18a73163a34c5a3fae8544537a2fed83ac Mon Sep 17 00:00:00 2001 From: Simon Vandel Sillesen Date: Sun, 13 Sep 2020 16:04:45 +0200 Subject: [PATCH 1/5] MIR pass to remove unneeded drops on types not needing drop This is heavily dependent on MIR inlining running to actually see the drop statement --- compiler/rustc_mir/src/transform/mod.rs | 2 + .../src/transform/remove_unneeded_drops.rs | 57 +++++++++++++++++++ ...annot_opt_generic.RemoveUnneededDrops.diff | 32 +++++++++++ ...ed_drops.dont_opt.RemoveUnneededDrops.diff | 32 +++++++++++ ...nneeded_drops.opt.RemoveUnneededDrops.diff | 29 ++++++++++ ....opt_generic_copy.RemoveUnneededDrops.diff | 29 ++++++++++ src/test/mir-opt/remove_unneeded_drops.rs | 28 +++++++++ 7 files changed, 209 insertions(+) create mode 100644 compiler/rustc_mir/src/transform/remove_unneeded_drops.rs create mode 100644 src/test/mir-opt/remove_unneeded_drops.cannot_opt_generic.RemoveUnneededDrops.diff create mode 100644 src/test/mir-opt/remove_unneeded_drops.dont_opt.RemoveUnneededDrops.diff create mode 100644 src/test/mir-opt/remove_unneeded_drops.opt.RemoveUnneededDrops.diff create mode 100644 src/test/mir-opt/remove_unneeded_drops.opt_generic_copy.RemoveUnneededDrops.diff create mode 100644 src/test/mir-opt/remove_unneeded_drops.rs diff --git a/compiler/rustc_mir/src/transform/mod.rs b/compiler/rustc_mir/src/transform/mod.rs index 8025b7c02043..3e831a48c257 100644 --- a/compiler/rustc_mir/src/transform/mod.rs +++ b/compiler/rustc_mir/src/transform/mod.rs @@ -36,6 +36,7 @@ pub mod nrvo; pub mod promote_consts; pub mod qualify_min_const_fn; pub mod remove_noop_landing_pads; +pub mod remove_unneeded_drops; pub mod required_consts; pub mod rustc_peek; pub mod simplify; @@ -455,6 +456,7 @@ fn run_optimization_passes<'tcx>( // The main optimizations that we do on MIR. let optimizations: &[&dyn MirPass<'tcx>] = &[ + &remove_unneeded_drops::RemoveUnneededDrops::new(def_id), &match_branches::MatchBranchSimplification, // inst combine is after MatchBranchSimplification to clean up Ne(_1, false) &instcombine::InstCombine, diff --git a/compiler/rustc_mir/src/transform/remove_unneeded_drops.rs b/compiler/rustc_mir/src/transform/remove_unneeded_drops.rs new file mode 100644 index 000000000000..0f023d71dd1d --- /dev/null +++ b/compiler/rustc_mir/src/transform/remove_unneeded_drops.rs @@ -0,0 +1,57 @@ +//! This pass replaces a drop of a type that does not need dropping, with a goto + +use crate::transform::{MirPass, MirSource}; +use rustc_hir::def_id::LocalDefId; +use rustc_middle::mir::visit::Visitor; +use rustc_middle::mir::*; +use rustc_middle::ty::TyCtxt; + +pub struct RemoveUnneededDrops { + def_id: LocalDefId, +} + +impl RemoveUnneededDrops { + pub fn new(def_id: LocalDefId) -> Self { + Self { def_id } + } +} + +impl<'tcx> MirPass<'tcx> for RemoveUnneededDrops { + fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) { + trace!("Running SimplifyComparisonIntegral on {:?}", source); + let mut opt_finder = RemoveUnneededDropsOptimizationFinder { + tcx, + body, + optimizations: vec![], + def_id: self.def_id, + }; + opt_finder.visit_body(body); + for (loc, target) in opt_finder.optimizations { + let terminator = body.basic_blocks_mut()[loc.block].terminator_mut(); + debug!("SUCCESS: replacing `drop` with goto({:?})", target); + terminator.kind = TerminatorKind::Goto { target }; + } + } +} + +impl<'a, 'tcx> Visitor<'tcx> for RemoveUnneededDropsOptimizationFinder<'a, 'tcx> { + fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) { + match terminator.kind { + TerminatorKind::Drop { place, target, .. } => { + let ty = place.ty(self.body, self.tcx); + let needs_drop = ty.ty.needs_drop(self.tcx, self.tcx.param_env(self.def_id)); + if !needs_drop { + self.optimizations.push((location, target)); + } + } + _ => {} + } + self.super_terminator(terminator, location); + } +} +pub struct RemoveUnneededDropsOptimizationFinder<'a, 'tcx> { + tcx: TyCtxt<'tcx>, + body: &'a Body<'tcx>, + optimizations: Vec<(Location, BasicBlock)>, + def_id: LocalDefId, +} diff --git a/src/test/mir-opt/remove_unneeded_drops.cannot_opt_generic.RemoveUnneededDrops.diff b/src/test/mir-opt/remove_unneeded_drops.cannot_opt_generic.RemoveUnneededDrops.diff new file mode 100644 index 000000000000..545ad2794ee1 --- /dev/null +++ b/src/test/mir-opt/remove_unneeded_drops.cannot_opt_generic.RemoveUnneededDrops.diff @@ -0,0 +1,32 @@ +- // MIR for `cannot_opt_generic` before RemoveUnneededDrops ++ // MIR for `cannot_opt_generic` after RemoveUnneededDrops + + fn cannot_opt_generic(_1: T) -> () { + debug x => _1; // in scope 0 at $DIR/remove_unneeded_drops.rs:19:26: 19:27 + let mut _0: (); // return place in scope 0 at $DIR/remove_unneeded_drops.rs:19:32: 19:32 + let _2: (); // in scope 0 at $DIR/remove_unneeded_drops.rs:20:5: 20:12 + let mut _3: T; // in scope 0 at $DIR/remove_unneeded_drops.rs:20:10: 20:11 + scope 1 { + debug _x => _3; // in scope 1 at $SRC_DIR/core/src/mem/mod.rs:LL:COL + } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/remove_unneeded_drops.rs:20:5: 20:12 + StorageLive(_3); // scope 0 at $DIR/remove_unneeded_drops.rs:20:10: 20:11 + _3 = move _1; // scope 0 at $DIR/remove_unneeded_drops.rs:20:10: 20:11 + _2 = const (); // scope 1 at $SRC_DIR/core/src/mem/mod.rs:LL:COL + drop(_3) -> [return: bb2, unwind: bb1]; // scope 1 at $SRC_DIR/core/src/mem/mod.rs:LL:COL + } + + bb1 (cleanup): { + resume; // scope 0 at $DIR/remove_unneeded_drops.rs:19:1: 21:2 + } + + bb2: { + StorageDead(_3); // scope 0 at $DIR/remove_unneeded_drops.rs:20:11: 20:12 + StorageDead(_2); // scope 0 at $DIR/remove_unneeded_drops.rs:20:12: 20:13 + _0 = const (); // scope 0 at $DIR/remove_unneeded_drops.rs:19:32: 21:2 + return; // scope 0 at $DIR/remove_unneeded_drops.rs:21:2: 21:2 + } + } + diff --git a/src/test/mir-opt/remove_unneeded_drops.dont_opt.RemoveUnneededDrops.diff b/src/test/mir-opt/remove_unneeded_drops.dont_opt.RemoveUnneededDrops.diff new file mode 100644 index 000000000000..78d65d13bd1b --- /dev/null +++ b/src/test/mir-opt/remove_unneeded_drops.dont_opt.RemoveUnneededDrops.diff @@ -0,0 +1,32 @@ +- // MIR for `dont_opt` before RemoveUnneededDrops ++ // MIR for `dont_opt` after RemoveUnneededDrops + + fn dont_opt(_1: Vec) -> () { + debug x => _1; // in scope 0 at $DIR/remove_unneeded_drops.rs:7:13: 7:14 + let mut _0: (); // return place in scope 0 at $DIR/remove_unneeded_drops.rs:7:27: 7:27 + let _2: (); // in scope 0 at $DIR/remove_unneeded_drops.rs:8:5: 8:12 + let mut _3: std::vec::Vec; // in scope 0 at $DIR/remove_unneeded_drops.rs:8:10: 8:11 + scope 1 { + debug _x => _3; // in scope 1 at $SRC_DIR/core/src/mem/mod.rs:LL:COL + } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/remove_unneeded_drops.rs:8:5: 8:12 + StorageLive(_3); // scope 0 at $DIR/remove_unneeded_drops.rs:8:10: 8:11 + _3 = move _1; // scope 0 at $DIR/remove_unneeded_drops.rs:8:10: 8:11 + _2 = const (); // scope 1 at $SRC_DIR/core/src/mem/mod.rs:LL:COL + drop(_3) -> [return: bb2, unwind: bb1]; // scope 1 at $SRC_DIR/core/src/mem/mod.rs:LL:COL + } + + bb1 (cleanup): { + resume; // scope 0 at $DIR/remove_unneeded_drops.rs:7:1: 9:2 + } + + bb2: { + StorageDead(_3); // scope 0 at $DIR/remove_unneeded_drops.rs:8:11: 8:12 + StorageDead(_2); // scope 0 at $DIR/remove_unneeded_drops.rs:8:12: 8:13 + _0 = const (); // scope 0 at $DIR/remove_unneeded_drops.rs:7:27: 9:2 + return; // scope 0 at $DIR/remove_unneeded_drops.rs:9:2: 9:2 + } + } + diff --git a/src/test/mir-opt/remove_unneeded_drops.opt.RemoveUnneededDrops.diff b/src/test/mir-opt/remove_unneeded_drops.opt.RemoveUnneededDrops.diff new file mode 100644 index 000000000000..34193ccc5c7e --- /dev/null +++ b/src/test/mir-opt/remove_unneeded_drops.opt.RemoveUnneededDrops.diff @@ -0,0 +1,29 @@ +- // MIR for `opt` before RemoveUnneededDrops ++ // MIR for `opt` after RemoveUnneededDrops + + fn opt(_1: bool) -> () { + debug x => _1; // in scope 0 at $DIR/remove_unneeded_drops.rs:2:8: 2:9 + let mut _0: (); // return place in scope 0 at $DIR/remove_unneeded_drops.rs:2:17: 2:17 + let _2: (); // in scope 0 at $DIR/remove_unneeded_drops.rs:3:5: 3:12 + let mut _3: bool; // in scope 0 at $DIR/remove_unneeded_drops.rs:3:10: 3:11 + scope 1 { + debug _x => _3; // in scope 1 at $SRC_DIR/core/src/mem/mod.rs:LL:COL + } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/remove_unneeded_drops.rs:3:5: 3:12 + StorageLive(_3); // scope 0 at $DIR/remove_unneeded_drops.rs:3:10: 3:11 + _3 = _1; // scope 0 at $DIR/remove_unneeded_drops.rs:3:10: 3:11 + _2 = const (); // scope 1 at $SRC_DIR/core/src/mem/mod.rs:LL:COL +- drop(_3) -> bb1; // scope 1 at $SRC_DIR/core/src/mem/mod.rs:LL:COL ++ goto -> bb1; // scope 1 at $SRC_DIR/core/src/mem/mod.rs:LL:COL + } + + bb1: { + StorageDead(_3); // scope 0 at $DIR/remove_unneeded_drops.rs:3:11: 3:12 + StorageDead(_2); // scope 0 at $DIR/remove_unneeded_drops.rs:3:12: 3:13 + _0 = const (); // scope 0 at $DIR/remove_unneeded_drops.rs:2:17: 4:2 + return; // scope 0 at $DIR/remove_unneeded_drops.rs:4:2: 4:2 + } + } + diff --git a/src/test/mir-opt/remove_unneeded_drops.opt_generic_copy.RemoveUnneededDrops.diff b/src/test/mir-opt/remove_unneeded_drops.opt_generic_copy.RemoveUnneededDrops.diff new file mode 100644 index 000000000000..2e6c8c8a78a7 --- /dev/null +++ b/src/test/mir-opt/remove_unneeded_drops.opt_generic_copy.RemoveUnneededDrops.diff @@ -0,0 +1,29 @@ +- // MIR for `opt_generic_copy` before RemoveUnneededDrops ++ // MIR for `opt_generic_copy` after RemoveUnneededDrops + + fn opt_generic_copy(_1: T) -> () { + debug x => _1; // in scope 0 at $DIR/remove_unneeded_drops.rs:12:30: 12:31 + let mut _0: (); // return place in scope 0 at $DIR/remove_unneeded_drops.rs:12:36: 12:36 + let _2: (); // in scope 0 at $DIR/remove_unneeded_drops.rs:13:5: 13:12 + let mut _3: T; // in scope 0 at $DIR/remove_unneeded_drops.rs:13:10: 13:11 + scope 1 { + debug _x => _3; // in scope 1 at $SRC_DIR/core/src/mem/mod.rs:LL:COL + } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/remove_unneeded_drops.rs:13:5: 13:12 + StorageLive(_3); // scope 0 at $DIR/remove_unneeded_drops.rs:13:10: 13:11 + _3 = _1; // scope 0 at $DIR/remove_unneeded_drops.rs:13:10: 13:11 + _2 = const (); // scope 1 at $SRC_DIR/core/src/mem/mod.rs:LL:COL +- drop(_3) -> bb1; // scope 1 at $SRC_DIR/core/src/mem/mod.rs:LL:COL ++ goto -> bb1; // scope 1 at $SRC_DIR/core/src/mem/mod.rs:LL:COL + } + + bb1: { + StorageDead(_3); // scope 0 at $DIR/remove_unneeded_drops.rs:13:11: 13:12 + StorageDead(_2); // scope 0 at $DIR/remove_unneeded_drops.rs:13:12: 13:13 + _0 = const (); // scope 0 at $DIR/remove_unneeded_drops.rs:12:36: 14:2 + return; // scope 0 at $DIR/remove_unneeded_drops.rs:14:2: 14:2 + } + } + diff --git a/src/test/mir-opt/remove_unneeded_drops.rs b/src/test/mir-opt/remove_unneeded_drops.rs new file mode 100644 index 000000000000..17d7e79a1eb0 --- /dev/null +++ b/src/test/mir-opt/remove_unneeded_drops.rs @@ -0,0 +1,28 @@ +// EMIT_MIR remove_unneeded_drops.opt.RemoveUnneededDrops.diff +fn opt(x: bool) { + drop(x); +} + +// EMIT_MIR remove_unneeded_drops.dont_opt.RemoveUnneededDrops.diff +fn dont_opt(x: Vec) { + drop(x); +} + +// EMIT_MIR remove_unneeded_drops.opt_generic_copy.RemoveUnneededDrops.diff +fn opt_generic_copy(x: T) { + drop(x); +} + +// EMIT_MIR remove_unneeded_drops.cannot_opt_generic.RemoveUnneededDrops.diff +// since the pass is not running on monomorphisized code, +// we can't (but probably should) optimize this +fn cannot_opt_generic(x: T) { + drop(x); +} + +fn main() { + opt(true); + opt_generic_copy(42); + cannot_opt_generic(42); + dont_opt(vec![true]); +} From 9d47ecf327edbb5dd1b11dd112335506d8d26165 Mon Sep 17 00:00:00 2001 From: Simon Vandel Sillesen Date: Mon, 14 Sep 2020 22:56:39 +0200 Subject: [PATCH 2/5] Suggestion from review Co-authored-by: Andreas Jonson --- compiler/rustc_mir/src/transform/remove_unneeded_drops.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_mir/src/transform/remove_unneeded_drops.rs b/compiler/rustc_mir/src/transform/remove_unneeded_drops.rs index 0f023d71dd1d..393b0f923b91 100644 --- a/compiler/rustc_mir/src/transform/remove_unneeded_drops.rs +++ b/compiler/rustc_mir/src/transform/remove_unneeded_drops.rs @@ -18,7 +18,7 @@ impl RemoveUnneededDrops { impl<'tcx> MirPass<'tcx> for RemoveUnneededDrops { fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) { - trace!("Running SimplifyComparisonIntegral on {:?}", source); + trace!("Running RemoveUnneededDrops on {:?}", source); let mut opt_finder = RemoveUnneededDropsOptimizationFinder { tcx, body, From 673935fc0c8cbb4925e4fa0c936e4340aa818be0 Mon Sep 17 00:00:00 2001 From: Simon Vandel Sillesen Date: Sat, 19 Sep 2020 13:52:55 +0200 Subject: [PATCH 3/5] Get LocalDefId from source instead of passing in --- compiler/rustc_mir/src/transform/mod.rs | 2 +- .../rustc_mir/src/transform/remove_unneeded_drops.rs | 12 ++---------- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_mir/src/transform/mod.rs b/compiler/rustc_mir/src/transform/mod.rs index 3e831a48c257..685a56ad5de9 100644 --- a/compiler/rustc_mir/src/transform/mod.rs +++ b/compiler/rustc_mir/src/transform/mod.rs @@ -456,7 +456,7 @@ fn run_optimization_passes<'tcx>( // The main optimizations that we do on MIR. let optimizations: &[&dyn MirPass<'tcx>] = &[ - &remove_unneeded_drops::RemoveUnneededDrops::new(def_id), + &remove_unneeded_drops::RemoveUnneededDrops, &match_branches::MatchBranchSimplification, // inst combine is after MatchBranchSimplification to clean up Ne(_1, false) &instcombine::InstCombine, diff --git a/compiler/rustc_mir/src/transform/remove_unneeded_drops.rs b/compiler/rustc_mir/src/transform/remove_unneeded_drops.rs index 393b0f923b91..505133219b86 100644 --- a/compiler/rustc_mir/src/transform/remove_unneeded_drops.rs +++ b/compiler/rustc_mir/src/transform/remove_unneeded_drops.rs @@ -6,15 +6,7 @@ use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; -pub struct RemoveUnneededDrops { - def_id: LocalDefId, -} - -impl RemoveUnneededDrops { - pub fn new(def_id: LocalDefId) -> Self { - Self { def_id } - } -} +pub struct RemoveUnneededDrops; impl<'tcx> MirPass<'tcx> for RemoveUnneededDrops { fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) { @@ -23,7 +15,7 @@ impl<'tcx> MirPass<'tcx> for RemoveUnneededDrops { tcx, body, optimizations: vec![], - def_id: self.def_id, + def_id: source.def_id().expect_local(), }; opt_finder.visit_body(body); for (loc, target) in opt_finder.optimizations { From 30dd6cf9ba472d4ff12c9a28d03e3a61d54e34da Mon Sep 17 00:00:00 2001 From: Simon Vandel Sillesen Date: Sat, 19 Sep 2020 14:25:53 +0200 Subject: [PATCH 4/5] The optimization should also apply for DropAndReplace --- compiler/rustc_mir/src/transform/remove_unneeded_drops.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_mir/src/transform/remove_unneeded_drops.rs b/compiler/rustc_mir/src/transform/remove_unneeded_drops.rs index 505133219b86..b8ad816f7583 100644 --- a/compiler/rustc_mir/src/transform/remove_unneeded_drops.rs +++ b/compiler/rustc_mir/src/transform/remove_unneeded_drops.rs @@ -29,7 +29,8 @@ impl<'tcx> MirPass<'tcx> for RemoveUnneededDrops { impl<'a, 'tcx> Visitor<'tcx> for RemoveUnneededDropsOptimizationFinder<'a, 'tcx> { fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) { match terminator.kind { - TerminatorKind::Drop { place, target, .. } => { + TerminatorKind::Drop { place, target, .. } + | TerminatorKind::DropAndReplace { place, target, .. } => { let ty = place.ty(self.body, self.tcx); let needs_drop = ty.ty.needs_drop(self.tcx, self.tcx.param_env(self.def_id)); if !needs_drop { From 804f673762d732198e5023be6fa8f1e305e2c2ad Mon Sep 17 00:00:00 2001 From: Simon Vandel Sillesen Date: Sat, 19 Sep 2020 15:21:39 +0200 Subject: [PATCH 5/5] cleanup cfg after optimization --- .../rustc_mir/src/transform/remove_unneeded_drops.rs | 9 +++++++++ .../remove_unneeded_drops.opt.RemoveUnneededDrops.diff | 7 +++---- ...eeded_drops.opt_generic_copy.RemoveUnneededDrops.diff | 7 +++---- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_mir/src/transform/remove_unneeded_drops.rs b/compiler/rustc_mir/src/transform/remove_unneeded_drops.rs index b8ad816f7583..f027f5e33a18 100644 --- a/compiler/rustc_mir/src/transform/remove_unneeded_drops.rs +++ b/compiler/rustc_mir/src/transform/remove_unneeded_drops.rs @@ -6,6 +6,8 @@ use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; +use super::simplify::simplify_cfg; + pub struct RemoveUnneededDrops; impl<'tcx> MirPass<'tcx> for RemoveUnneededDrops { @@ -18,11 +20,18 @@ impl<'tcx> MirPass<'tcx> for RemoveUnneededDrops { def_id: source.def_id().expect_local(), }; opt_finder.visit_body(body); + let should_simplify = !opt_finder.optimizations.is_empty(); for (loc, target) in opt_finder.optimizations { let terminator = body.basic_blocks_mut()[loc.block].terminator_mut(); debug!("SUCCESS: replacing `drop` with goto({:?})", target); terminator.kind = TerminatorKind::Goto { target }; } + + // if we applied optimizations, we potentially have some cfg to cleanup to + // make it easier for further passes + if should_simplify { + simplify_cfg(body); + } } } diff --git a/src/test/mir-opt/remove_unneeded_drops.opt.RemoveUnneededDrops.diff b/src/test/mir-opt/remove_unneeded_drops.opt.RemoveUnneededDrops.diff index 34193ccc5c7e..eba839cf0a48 100644 --- a/src/test/mir-opt/remove_unneeded_drops.opt.RemoveUnneededDrops.diff +++ b/src/test/mir-opt/remove_unneeded_drops.opt.RemoveUnneededDrops.diff @@ -16,10 +16,9 @@ _3 = _1; // scope 0 at $DIR/remove_unneeded_drops.rs:3:10: 3:11 _2 = const (); // scope 1 at $SRC_DIR/core/src/mem/mod.rs:LL:COL - drop(_3) -> bb1; // scope 1 at $SRC_DIR/core/src/mem/mod.rs:LL:COL -+ goto -> bb1; // scope 1 at $SRC_DIR/core/src/mem/mod.rs:LL:COL - } - - bb1: { +- } +- +- bb1: { StorageDead(_3); // scope 0 at $DIR/remove_unneeded_drops.rs:3:11: 3:12 StorageDead(_2); // scope 0 at $DIR/remove_unneeded_drops.rs:3:12: 3:13 _0 = const (); // scope 0 at $DIR/remove_unneeded_drops.rs:2:17: 4:2 diff --git a/src/test/mir-opt/remove_unneeded_drops.opt_generic_copy.RemoveUnneededDrops.diff b/src/test/mir-opt/remove_unneeded_drops.opt_generic_copy.RemoveUnneededDrops.diff index 2e6c8c8a78a7..840b1ba30fb9 100644 --- a/src/test/mir-opt/remove_unneeded_drops.opt_generic_copy.RemoveUnneededDrops.diff +++ b/src/test/mir-opt/remove_unneeded_drops.opt_generic_copy.RemoveUnneededDrops.diff @@ -16,10 +16,9 @@ _3 = _1; // scope 0 at $DIR/remove_unneeded_drops.rs:13:10: 13:11 _2 = const (); // scope 1 at $SRC_DIR/core/src/mem/mod.rs:LL:COL - drop(_3) -> bb1; // scope 1 at $SRC_DIR/core/src/mem/mod.rs:LL:COL -+ goto -> bb1; // scope 1 at $SRC_DIR/core/src/mem/mod.rs:LL:COL - } - - bb1: { +- } +- +- bb1: { StorageDead(_3); // scope 0 at $DIR/remove_unneeded_drops.rs:13:11: 13:12 StorageDead(_2); // scope 0 at $DIR/remove_unneeded_drops.rs:13:12: 13:13 _0 = const (); // scope 0 at $DIR/remove_unneeded_drops.rs:12:36: 14:2