1
Fork 0

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
This commit is contained in:
Simon Vandel Sillesen 2020-09-13 16:04:45 +02:00
parent e0bc267512
commit 290dca1781
7 changed files with 209 additions and 0 deletions

View file

@ -38,6 +38,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;
@ -461,6 +462,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,

View file

@ -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,
}