|
| 1 | +//! This pass replaces a drop of a type that does not need dropping, with a goto |
| 2 | +
|
| 3 | +use crate::transform::{MirPass, MirSource}; |
| 4 | +use rustc_hir::def_id::LocalDefId; |
| 5 | +use rustc_middle::mir::visit::Visitor; |
| 6 | +use rustc_middle::mir::*; |
| 7 | +use rustc_middle::ty::TyCtxt; |
| 8 | + |
| 9 | +use super::simplify::simplify_cfg; |
| 10 | + |
| 11 | +pub struct RemoveUnneededDrops; |
| 12 | + |
| 13 | +impl<'tcx> MirPass<'tcx> for RemoveUnneededDrops { |
| 14 | + fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) { |
| 15 | + trace!("Running RemoveUnneededDrops on {:?}", source); |
| 16 | + let mut opt_finder = RemoveUnneededDropsOptimizationFinder { |
| 17 | + tcx, |
| 18 | + body, |
| 19 | + optimizations: vec![], |
| 20 | + def_id: source.def_id().expect_local(), |
| 21 | + }; |
| 22 | + opt_finder.visit_body(body); |
| 23 | + let should_simplify = !opt_finder.optimizations.is_empty(); |
| 24 | + for (loc, target) in opt_finder.optimizations { |
| 25 | + let terminator = body.basic_blocks_mut()[loc.block].terminator_mut(); |
| 26 | + debug!("SUCCESS: replacing `drop` with goto({:?})", target); |
| 27 | + terminator.kind = TerminatorKind::Goto { target }; |
| 28 | + } |
| 29 | + |
| 30 | + // if we applied optimizations, we potentially have some cfg to cleanup to |
| 31 | + // make it easier for further passes |
| 32 | + if should_simplify { |
| 33 | + simplify_cfg(body); |
| 34 | + } |
| 35 | + } |
| 36 | +} |
| 37 | + |
| 38 | +impl<'a, 'tcx> Visitor<'tcx> for RemoveUnneededDropsOptimizationFinder<'a, 'tcx> { |
| 39 | + fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) { |
| 40 | + match terminator.kind { |
| 41 | + TerminatorKind::Drop { place, target, .. } |
| 42 | + | TerminatorKind::DropAndReplace { place, target, .. } => { |
| 43 | + let ty = place.ty(self.body, self.tcx); |
| 44 | + let needs_drop = ty.ty.needs_drop(self.tcx, self.tcx.param_env(self.def_id)); |
| 45 | + if !needs_drop { |
| 46 | + self.optimizations.push((location, target)); |
| 47 | + } |
| 48 | + } |
| 49 | + _ => {} |
| 50 | + } |
| 51 | + self.super_terminator(terminator, location); |
| 52 | + } |
| 53 | +} |
| 54 | +pub struct RemoveUnneededDropsOptimizationFinder<'a, 'tcx> { |
| 55 | + tcx: TyCtxt<'tcx>, |
| 56 | + body: &'a Body<'tcx>, |
| 57 | + optimizations: Vec<(Location, BasicBlock)>, |
| 58 | + def_id: LocalDefId, |
| 59 | +} |
0 commit comments