rust/compiler/rustc_mir/src/transform/remove_unneeded_drops.rs

62 lines
2.2 KiB
Rust
Raw Normal View History

//! This pass replaces a drop of a type that does not need dropping, with a goto
use crate::transform::MirPass;
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::*;
use rustc_middle::ty::{ParamEnv, TyCtxt};
2020-09-19 15:21:39 +02:00
use super::simplify::simplify_cfg;
pub struct RemoveUnneededDrops;
impl<'tcx> MirPass<'tcx> for RemoveUnneededDrops {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
if !tcx.consider_optimizing(|| format!("RemoveUnneededDrops {:?} ", body.source.def_id())) {
return;
}
trace!("Running RemoveUnneededDrops on {:?}", body.source);
let mut opt_finder = RemoveUnneededDropsOptimizationFinder {
tcx,
body,
param_env: tcx.param_env(body.source.def_id()),
optimizations: vec![],
};
opt_finder.visit_body(body);
2020-09-19 15:21:39 +02:00
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 };
}
2020-09-19 15:21:39 +02:00
// if we applied optimizations, we potentially have some cfg to cleanup to
// make it easier for further passes
if should_simplify {
simplify_cfg(body);
}
}
}
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.param_env);
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)>,
param_env: ParamEnv<'tcx>,
}