2020-09-13 16:04:45 +02:00
|
|
|
//! This pass replaces a drop of a type that does not need dropping, with a goto
|
|
|
|
|
2020-10-04 11:01:38 -07:00
|
|
|
use crate::transform::MirPass;
|
2020-09-13 16:04:45 +02:00
|
|
|
use rustc_middle::mir::visit::Visitor;
|
|
|
|
use rustc_middle::mir::*;
|
2020-10-04 15:22:23 -07:00
|
|
|
use rustc_middle::ty::{ParamEnv, TyCtxt};
|
2020-09-13 16:04:45 +02:00
|
|
|
|
2020-09-19 15:21:39 +02:00
|
|
|
use super::simplify::simplify_cfg;
|
|
|
|
|
2020-09-19 13:52:55 +02:00
|
|
|
pub struct RemoveUnneededDrops;
|
2020-09-13 16:04:45 +02:00
|
|
|
|
|
|
|
impl<'tcx> MirPass<'tcx> for RemoveUnneededDrops {
|
2020-10-04 11:01:38 -07:00
|
|
|
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
2020-11-16 18:09:10 -05:00
|
|
|
if !tcx.consider_optimizing(|| format!("RemoveUnneededDrops {:?} ", body.source.def_id())) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-10-04 11:01:38 -07:00
|
|
|
trace!("Running RemoveUnneededDrops on {:?}", body.source);
|
2020-09-13 16:04:45 +02:00
|
|
|
let mut opt_finder = RemoveUnneededDropsOptimizationFinder {
|
|
|
|
tcx,
|
|
|
|
body,
|
2020-10-04 15:22:23 -07:00
|
|
|
param_env: tcx.param_env(body.source.def_id()),
|
2020-09-13 16:04:45 +02:00
|
|
|
optimizations: vec![],
|
|
|
|
};
|
|
|
|
opt_finder.visit_body(body);
|
2020-09-19 15:21:39 +02:00
|
|
|
let should_simplify = !opt_finder.optimizations.is_empty();
|
2020-09-13 16:04:45 +02:00
|
|
|
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);
|
|
|
|
}
|
2020-09-13 16:04:45 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a, 'tcx> Visitor<'tcx> for RemoveUnneededDropsOptimizationFinder<'a, 'tcx> {
|
|
|
|
fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
|
|
|
|
match terminator.kind {
|
2020-09-24 21:02:53 +02:00
|
|
|
TerminatorKind::Drop { place, target, .. } => {
|
2020-09-13 16:04:45 +02:00
|
|
|
let ty = place.ty(self.body, self.tcx);
|
2020-10-04 15:22:23 -07:00
|
|
|
let needs_drop = ty.ty.needs_drop(self.tcx, self.param_env);
|
2020-09-13 16:04:45 +02:00
|
|
|
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)>,
|
2020-10-04 15:22:23 -07:00
|
|
|
param_env: ParamEnv<'tcx>,
|
2020-09-13 16:04:45 +02:00
|
|
|
}
|