1
Fork 0

rework MirPass API to be stateless and extract helper fns

This commit is contained in:
Niko Matsakis 2017-04-25 18:22:59 -04:00
parent 0e5e2f3634
commit 11b6b0663a
15 changed files with 74 additions and 82 deletions

View file

@ -10,7 +10,7 @@
use dep_graph::DepNode; use dep_graph::DepNode;
use hir; use hir;
use hir::def_id::LOCAL_CRATE; use hir::def_id::{DefId, LOCAL_CRATE};
use hir::map::DefPathData; use hir::map::DefPathData;
use mir::{Mir, Promoted}; use mir::{Mir, Promoted};
use ty::TyCtxt; use ty::TyCtxt;
@ -88,14 +88,14 @@ pub trait Pass {
/// A pass which inspects the whole Mir map. /// A pass which inspects the whole Mir map.
pub trait MirMapPass<'tcx>: Pass { pub trait MirMapPass<'tcx>: Pass {
fn run_pass<'a>( fn run_pass<'a>(
&mut self, &self,
tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>,
hooks: &mut [Box<for<'s> MirPassHook<'s>>]); hooks: &mut [Box<for<'s> MirPassHook<'s>>]);
} }
pub trait MirPassHook<'tcx>: Pass { pub trait MirPassHook<'tcx>: Pass {
fn on_mir_pass<'a>( fn on_mir_pass<'a>(
&mut self, &self,
tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>,
src: MirSource, src: MirSource,
mir: &Mir<'tcx>, mir: &Mir<'tcx>,
@ -106,40 +106,58 @@ pub trait MirPassHook<'tcx>: Pass {
/// A pass which inspects Mir of functions in isolation. /// A pass which inspects Mir of functions in isolation.
pub trait MirPass<'tcx>: Pass { pub trait MirPass<'tcx>: Pass {
fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, fn run_pass<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
src: MirSource, mir: &mut Mir<'tcx>); src: MirSource, mir: &mut Mir<'tcx>);
} }
impl<'tcx, T: MirPass<'tcx>> MirMapPass<'tcx> for T { impl<'tcx, T: MirPass<'tcx>> MirMapPass<'tcx> for T {
fn run_pass<'a>(&mut self, fn run_pass<'a>(&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>,
hooks: &mut [Box<for<'s> MirPassHook<'s>>]) hooks: &mut [Box<for<'s> MirPassHook<'s>>])
{ {
for &def_id in tcx.mir_keys(LOCAL_CRATE).iter() { for &def_id in tcx.mir_keys(LOCAL_CRATE).iter() {
run_hooks(tcx, hooks, self, false);
run_map_pass_task(tcx, self, def_id);
run_hooks(tcx, hooks, self, false);
}
}
}
fn run_map_pass_task<'a, 'tcx, T: MirPass<'tcx>>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
pass: &T,
def_id: DefId) {
let _task = tcx.dep_graph.in_task(DepNode::Mir(def_id)); let _task = tcx.dep_graph.in_task(DepNode::Mir(def_id));
let mir = &mut tcx.mir(def_id).borrow_mut(); let mir = &mut tcx.mir(def_id).borrow_mut();
tcx.dep_graph.write(DepNode::Mir(def_id)); let id = tcx.hir.as_local_node_id(def_id).expect("mir source requires local def-id");
let source = MirSource::from_node(tcx, id);
let id = tcx.hir.as_local_node_id(def_id).unwrap(); MirPass::run_pass(pass, tcx, source, mir);
let src = MirSource::from_node(tcx, id);
for hook in &mut *hooks {
hook.on_mir_pass(tcx, src, mir, self, false);
}
MirPass::run_pass(self, tcx, src, mir);
for hook in &mut *hooks {
hook.on_mir_pass(tcx, src, mir, self, true);
}
for (i, mir) in mir.promoted.iter_enumerated_mut() { for (i, mir) in mir.promoted.iter_enumerated_mut() {
let src = MirSource::Promoted(id, i); let source = MirSource::Promoted(id, i);
for hook in &mut *hooks { MirPass::run_pass(pass, tcx, source, mir);
hook.on_mir_pass(tcx, src, mir, self, false);
} }
MirPass::run_pass(self, tcx, src, mir); }
/// Invokes `hooks` on all the MIR that exists. This is read-only, so
/// new new tasks need to be created.
pub fn run_hooks<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
hooks: &mut [Box<for<'s> MirPassHook<'s>>],
pass: &Pass,
is_after: bool)
{
for &def_id in tcx.mir_keys(LOCAL_CRATE).iter() {
let mir = tcx.item_mir(def_id);
let id = tcx.hir.as_local_node_id(def_id).expect("mir source requires local def-id");
let source = MirSource::from_node(tcx, id);
for hook in &mut *hooks { for hook in &mut *hooks {
hook.on_mir_pass(tcx, src, mir, self, true); hook.on_mir_pass(tcx, source, &mir, pass, is_after);
} }
for (i, mir) in mir.promoted.iter_enumerated() {
let source = MirSource::Promoted(id, i);
for hook in &mut *hooks {
hook.on_mir_pass(tcx, source, &mir, pass, false);
} }
} }
} }

View file

@ -33,7 +33,7 @@ use std::u32;
pub struct ElaborateDrops; pub struct ElaborateDrops;
impl<'tcx> MirPass<'tcx> for ElaborateDrops { impl<'tcx> MirPass<'tcx> for ElaborateDrops {
fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, fn run_pass<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
src: MirSource, mir: &mut Mir<'tcx>) src: MirSource, mir: &mut Mir<'tcx>)
{ {
debug!("elaborate_drops({:?} @ {:?})", src, mir.span); debug!("elaborate_drops({:?} @ {:?})", src, mir.span);

View file

@ -1056,7 +1056,7 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
// No lifetime analysis based on borrowing can be done from here on out. // No lifetime analysis based on borrowing can be done from here on out.
passes.push_pass(box mir::transform::inline::Inline); passes.push_pass(box mir::transform::inline::Inline);
passes.push_pass(box mir::transform::instcombine::InstCombine::new()); passes.push_pass(box mir::transform::instcombine::InstCombine);
passes.push_pass(box mir::transform::deaggregator::Deaggregator); passes.push_pass(box mir::transform::deaggregator::Deaggregator);
passes.push_pass(box mir::transform::copy_prop::CopyPropagation); passes.push_pass(box mir::transform::copy_prop::CopyPropagation);

View file

@ -36,7 +36,7 @@ pub struct AddCallGuards;
*/ */
impl<'tcx> MirPass<'tcx> for AddCallGuards { impl<'tcx> MirPass<'tcx> for AddCallGuards {
fn run_pass<'a>(&mut self, _tcx: TyCtxt<'a, 'tcx, 'tcx>, _src: MirSource, mir: &mut Mir<'tcx>) { fn run_pass<'a>(&self, _tcx: TyCtxt<'a, 'tcx, 'tcx>, _src: MirSource, mir: &mut Mir<'tcx>) {
add_call_guards(mir); add_call_guards(mir);
} }
} }

View file

@ -41,7 +41,7 @@ pub struct CopyPropagation;
impl Pass for CopyPropagation {} impl Pass for CopyPropagation {}
impl<'tcx> MirPass<'tcx> for CopyPropagation { impl<'tcx> MirPass<'tcx> for CopyPropagation {
fn run_pass<'a>(&mut self, fn run_pass<'a>(&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>,
source: MirSource, source: MirSource,
mir: &mut Mir<'tcx>) { mir: &mut Mir<'tcx>) {

View file

@ -18,7 +18,7 @@ pub struct Deaggregator;
impl Pass for Deaggregator {} impl Pass for Deaggregator {}
impl<'tcx> MirPass<'tcx> for Deaggregator { impl<'tcx> MirPass<'tcx> for Deaggregator {
fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, fn run_pass<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
source: MirSource, mir: &mut Mir<'tcx>) { source: MirSource, mir: &mut Mir<'tcx>) {
let node_id = source.item_id(); let node_id = source.item_id();
let node_path = tcx.item_path_str(tcx.hir.local_def_id(node_id)); let node_path = tcx.item_path_str(tcx.hir.local_def_id(node_id));

View file

@ -23,7 +23,7 @@ use util as mir_util;
pub struct Marker<'a>(pub &'a str); pub struct Marker<'a>(pub &'a str);
impl<'b, 'tcx> MirPass<'tcx> for Marker<'b> { impl<'b, 'tcx> MirPass<'tcx> for Marker<'b> {
fn run_pass<'a>(&mut self, _tcx: TyCtxt<'a, 'tcx, 'tcx>, fn run_pass<'a>(&self, _tcx: TyCtxt<'a, 'tcx, 'tcx>,
_src: MirSource, _mir: &mut Mir<'tcx>) _src: MirSource, _mir: &mut Mir<'tcx>)
{} {}
} }
@ -52,7 +52,7 @@ pub struct DumpMir;
impl<'tcx> MirPassHook<'tcx> for DumpMir { impl<'tcx> MirPassHook<'tcx> for DumpMir {
fn on_mir_pass<'a>( fn on_mir_pass<'a>(
&mut self, &self,
tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>,
src: MirSource, src: MirSource,
mir: &Mir<'tcx>, mir: &Mir<'tcx>,

View file

@ -72,7 +72,7 @@ pub struct EraseRegions;
impl Pass for EraseRegions {} impl Pass for EraseRegions {}
impl<'tcx> MirPass<'tcx> for EraseRegions { impl<'tcx> MirPass<'tcx> for EraseRegions {
fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, fn run_pass<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
_: MirSource, mir: &mut Mir<'tcx>) { _: MirSource, mir: &mut Mir<'tcx>) {
EraseRegionsVisitor::new(tcx).visit_mir(mir); EraseRegionsVisitor::new(tcx).visit_mir(mir);
} }

View file

@ -18,7 +18,7 @@ use rustc_data_structures::graph;
use rustc::dep_graph::DepNode; use rustc::dep_graph::DepNode;
use rustc::mir::*; use rustc::mir::*;
use rustc::mir::transform::{MirMapPass, MirPassHook, MirSource, Pass}; use rustc::mir::transform::{self, MirMapPass, MirPassHook, MirSource, Pass};
use rustc::mir::visit::*; use rustc::mir::visit::*;
use rustc::traits; use rustc::traits;
use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::{self, Ty, TyCtxt};
@ -44,7 +44,7 @@ pub struct Inline;
impl<'tcx> MirMapPass<'tcx> for Inline { impl<'tcx> MirMapPass<'tcx> for Inline {
fn run_pass<'a>( fn run_pass<'a>(
&mut self, &self,
tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>,
hooks: &mut [Box<for<'s> MirPassHook<'s>>]) { hooks: &mut [Box<for<'s> MirPassHook<'s>>]) {
@ -58,33 +58,13 @@ impl<'tcx> MirMapPass<'tcx> for Inline {
tcx: tcx, tcx: tcx,
}; };
for &def_id in tcx.mir_keys(LOCAL_CRATE).iter() { transform::run_hooks(tcx, hooks, self, false);
let _task = tcx.dep_graph.in_task(DepNode::Mir(def_id));
let mir = &tcx.item_mir(def_id);
let id = tcx.hir.as_local_node_id(def_id).unwrap();
let src = MirSource::from_node(tcx, id);
for hook in &mut *hooks {
hook.on_mir_pass(tcx, src, mir, self, false);
}
}
for scc in callgraph.scc_iter() { for scc in callgraph.scc_iter() {
inliner.inline_scc(&callgraph, &scc); inliner.inline_scc(&callgraph, &scc);
} }
for &def_id in tcx.mir_keys(LOCAL_CRATE).iter() { transform::run_hooks(tcx, hooks, self, true);
let _task = tcx.dep_graph.in_task(DepNode::Mir(def_id));
let mir = &tcx.item_mir(def_id);
let id = tcx.hir.as_local_node_id(def_id).unwrap();
let src = MirSource::from_node(tcx, id);
for hook in &mut *hooks {
hook.on_mir_pass(tcx, src, mir, self, true);
}
}
} }
} }

View file

@ -18,22 +18,12 @@ use rustc::util::nodemap::FxHashSet;
use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::indexed_vec::Idx;
use std::mem; use std::mem;
pub struct InstCombine { pub struct InstCombine;
optimizations: OptimizationList,
}
impl InstCombine {
pub fn new() -> InstCombine {
InstCombine {
optimizations: OptimizationList::default(),
}
}
}
impl Pass for InstCombine {} impl Pass for InstCombine {}
impl<'tcx> MirPass<'tcx> for InstCombine { impl<'tcx> MirPass<'tcx> for InstCombine {
fn run_pass<'a>(&mut self, fn run_pass<'a>(&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>,
_: MirSource, _: MirSource,
mir: &mut Mir<'tcx>) { mir: &mut Mir<'tcx>) {
@ -45,18 +35,22 @@ impl<'tcx> MirPass<'tcx> for InstCombine {
// First, find optimization opportunities. This is done in a pre-pass to keep the MIR // First, find optimization opportunities. This is done in a pre-pass to keep the MIR
// read-only so that we can do global analyses on the MIR in the process (e.g. // read-only so that we can do global analyses on the MIR in the process (e.g.
// `Lvalue::ty()`). // `Lvalue::ty()`).
{ let optimizations = {
let mut optimization_finder = OptimizationFinder::new(mir, tcx); let mut optimization_finder = OptimizationFinder::new(mir, tcx);
optimization_finder.visit_mir(mir); optimization_finder.visit_mir(mir);
self.optimizations = optimization_finder.optimizations optimization_finder.optimizations
} };
// Then carry out those optimizations. // Then carry out those optimizations.
MutVisitor::visit_mir(&mut *self, mir); MutVisitor::visit_mir(&mut InstCombineVisitor { optimizations }, mir);
} }
} }
impl<'tcx> MutVisitor<'tcx> for InstCombine { pub struct InstCombineVisitor {
optimizations: OptimizationList,
}
impl<'tcx> MutVisitor<'tcx> for InstCombineVisitor {
fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>, location: Location) { fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>, location: Location) {
if self.optimizations.and_stars.remove(&location) { if self.optimizations.and_stars.remove(&location) {
debug!("Replacing `&*`: {:?}", rvalue); debug!("Replacing `&*`: {:?}", rvalue);

View file

@ -49,7 +49,7 @@ pub fn no_landing_pads<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &mut Mir<'tcx
} }
impl<'tcx> MirPass<'tcx> for NoLandingPads { impl<'tcx> MirPass<'tcx> for NoLandingPads {
fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, fn run_pass<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
_: MirSource, mir: &mut Mir<'tcx>) { _: MirSource, mir: &mut Mir<'tcx>) {
no_landing_pads(tcx, mir) no_landing_pads(tcx, mir)
} }

View file

@ -942,7 +942,7 @@ pub struct QualifyAndPromoteConstants;
impl Pass for QualifyAndPromoteConstants {} impl Pass for QualifyAndPromoteConstants {}
impl<'tcx> MirMapPass<'tcx> for QualifyAndPromoteConstants { impl<'tcx> MirMapPass<'tcx> for QualifyAndPromoteConstants {
fn run_pass<'a>(&mut self, fn run_pass<'a>(&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>,
hooks: &mut [Box<for<'s> MirPassHook<'s>>]) hooks: &mut [Box<for<'s> MirPassHook<'s>>])
{ {
@ -971,7 +971,7 @@ impl<'tcx> MirMapPass<'tcx> for QualifyAndPromoteConstants {
} }
impl<'tcx> QualifyAndPromoteConstants { impl<'tcx> QualifyAndPromoteConstants {
fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, fn run_pass<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
src: MirSource, mir: &mut Mir<'tcx>) { src: MirSource, mir: &mut Mir<'tcx>) {
let id = src.item_id(); let id = src.item_id();
let def_id = tcx.hir.local_def_id(id); let def_id = tcx.hir.local_def_id(id);

View file

@ -62,7 +62,7 @@ pub fn simplify_cfg(mir: &mut Mir) {
} }
impl<'l, 'tcx> MirPass<'tcx> for SimplifyCfg<'l> { impl<'l, 'tcx> MirPass<'tcx> for SimplifyCfg<'l> {
fn run_pass<'a>(&mut self, _tcx: TyCtxt<'a, 'tcx, 'tcx>, _src: MirSource, mir: &mut Mir<'tcx>) { fn run_pass<'a>(&self, _tcx: TyCtxt<'a, 'tcx, 'tcx>, _src: MirSource, mir: &mut Mir<'tcx>) {
debug!("SimplifyCfg({:?}) - simplifying {:?}", self.label, mir); debug!("SimplifyCfg({:?}) - simplifying {:?}", self.label, mir);
simplify_cfg(mir); simplify_cfg(mir);
} }
@ -320,7 +320,7 @@ impl Pass for SimplifyLocals {
} }
impl<'tcx> MirPass<'tcx> for SimplifyLocals { impl<'tcx> MirPass<'tcx> for SimplifyLocals {
fn run_pass<'a>(&mut self, _: TyCtxt<'a, 'tcx, 'tcx>, _: MirSource, mir: &mut Mir<'tcx>) { fn run_pass<'a>(&self, _: TyCtxt<'a, 'tcx, 'tcx>, _: MirSource, mir: &mut Mir<'tcx>) {
let mut marker = DeclMarker { locals: BitVector::new(mir.local_decls.len()) }; let mut marker = DeclMarker { locals: BitVector::new(mir.local_decls.len()) };
marker.visit_mir(mir); marker.visit_mir(mir);
// Return pointer and arguments are always live // Return pointer and arguments are always live

View file

@ -26,7 +26,7 @@ impl<'a> SimplifyBranches<'a> {
} }
impl<'l, 'tcx> MirPass<'tcx> for SimplifyBranches<'l> { impl<'l, 'tcx> MirPass<'tcx> for SimplifyBranches<'l> {
fn run_pass<'a>(&mut self, _tcx: TyCtxt<'a, 'tcx, 'tcx>, _src: MirSource, mir: &mut Mir<'tcx>) { fn run_pass<'a>(&self, _tcx: TyCtxt<'a, 'tcx, 'tcx>, _src: MirSource, mir: &mut Mir<'tcx>) {
for block in mir.basic_blocks_mut() { for block in mir.basic_blocks_mut() {
let terminator = block.terminator_mut(); let terminator = block.terminator_mut();
terminator.kind = match terminator.kind { terminator.kind = match terminator.kind {

View file

@ -738,7 +738,7 @@ impl TypeckMir {
} }
impl<'tcx> MirPass<'tcx> for TypeckMir { impl<'tcx> MirPass<'tcx> for TypeckMir {
fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, fn run_pass<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
src: MirSource, mir: &mut Mir<'tcx>) { src: MirSource, mir: &mut Mir<'tcx>) {
let item_id = src.item_id(); let item_id = src.item_id();
let def_id = tcx.hir.local_def_id(item_id); let def_id = tcx.hir.local_def_id(item_id);