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:
parent
e0bc267512
commit
290dca1781
7 changed files with 209 additions and 0 deletions
|
@ -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,
|
||||
|
|
57
compiler/rustc_mir/src/transform/remove_unneeded_drops.rs
Normal file
57
compiler/rustc_mir/src/transform/remove_unneeded_drops.rs
Normal 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,
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue