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 hir;
use hir::def_id::LOCAL_CRATE;
use hir::def_id::{DefId, LOCAL_CRATE};
use hir::map::DefPathData;
use mir::{Mir, Promoted};
use ty::TyCtxt;
@ -88,14 +88,14 @@ pub trait Pass {
/// A pass which inspects the whole Mir map.
pub trait MirMapPass<'tcx>: Pass {
fn run_pass<'a>(
&mut self,
&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
hooks: &mut [Box<for<'s> MirPassHook<'s>>]);
}
pub trait MirPassHook<'tcx>: Pass {
fn on_mir_pass<'a>(
&mut self,
&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
src: MirSource,
mir: &Mir<'tcx>,
@ -106,40 +106,58 @@ pub trait MirPassHook<'tcx>: Pass {
/// A pass which inspects Mir of functions in isolation.
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>);
}
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>,
hooks: &mut [Box<for<'s> MirPassHook<'s>>])
{
for &def_id in tcx.mir_keys(LOCAL_CRATE).iter() {
let _task = tcx.dep_graph.in_task(DepNode::Mir(def_id));
let mir = &mut tcx.mir(def_id).borrow_mut();
tcx.dep_graph.write(DepNode::Mir(def_id));
run_hooks(tcx, hooks, self, false);
run_map_pass_task(tcx, self, def_id);
run_hooks(tcx, hooks, self, false);
}
}
}
let id = tcx.hir.as_local_node_id(def_id).unwrap();
let src = MirSource::from_node(tcx, id);
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 mir = &mut tcx.mir(def_id).borrow_mut();
let id = tcx.hir.as_local_node_id(def_id).expect("mir source requires local def-id");
let source = MirSource::from_node(tcx, id);
MirPass::run_pass(pass, tcx, source, mir);
for (i, mir) in mir.promoted.iter_enumerated_mut() {
let source = MirSource::Promoted(id, i);
MirPass::run_pass(pass, tcx, source, 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 {
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, 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() {
let src = MirSource::Promoted(id, i);
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);
}
hook.on_mir_pass(tcx, source, &mir, pass, false);
}
}
}

View file

@ -33,7 +33,7 @@ use std::u32;
pub struct 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>)
{
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.
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::copy_prop::CopyPropagation);

View file

@ -36,7 +36,7 @@ pub struct 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);
}
}

View file

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

View file

@ -18,7 +18,7 @@ pub struct Deaggregator;
impl Pass 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>) {
let node_id = source.item_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);
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>)
{}
}
@ -52,7 +52,7 @@ pub struct DumpMir;
impl<'tcx> MirPassHook<'tcx> for DumpMir {
fn on_mir_pass<'a>(
&mut self,
&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
src: MirSource,
mir: &Mir<'tcx>,

View file

@ -72,7 +72,7 @@ pub struct EraseRegions;
impl Pass 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>) {
EraseRegionsVisitor::new(tcx).visit_mir(mir);
}

View file

@ -18,7 +18,7 @@ use rustc_data_structures::graph;
use rustc::dep_graph::DepNode;
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::traits;
use rustc::ty::{self, Ty, TyCtxt};
@ -44,7 +44,7 @@ pub struct Inline;
impl<'tcx> MirMapPass<'tcx> for Inline {
fn run_pass<'a>(
&mut self,
&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
hooks: &mut [Box<for<'s> MirPassHook<'s>>]) {
@ -58,33 +58,13 @@ impl<'tcx> MirMapPass<'tcx> for Inline {
tcx: tcx,
};
for &def_id in tcx.mir_keys(LOCAL_CRATE).iter() {
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);
}
}
transform::run_hooks(tcx, hooks, self, false);
for scc in callgraph.scc_iter() {
inliner.inline_scc(&callgraph, &scc);
}
for &def_id in tcx.mir_keys(LOCAL_CRATE).iter() {
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);
}
}
transform::run_hooks(tcx, hooks, self, true);
}
}

View file

@ -18,22 +18,12 @@ use rustc::util::nodemap::FxHashSet;
use rustc_data_structures::indexed_vec::Idx;
use std::mem;
pub struct InstCombine {
optimizations: OptimizationList,
}
impl InstCombine {
pub fn new() -> InstCombine {
InstCombine {
optimizations: OptimizationList::default(),
}
}
}
pub struct InstCombine;
impl Pass for InstCombine {}
impl<'tcx> MirPass<'tcx> for InstCombine {
fn run_pass<'a>(&mut self,
fn run_pass<'a>(&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
_: MirSource,
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
// read-only so that we can do global analyses on the MIR in the process (e.g.
// `Lvalue::ty()`).
{
let optimizations = {
let mut optimization_finder = OptimizationFinder::new(mir, tcx);
optimization_finder.visit_mir(mir);
self.optimizations = optimization_finder.optimizations
}
optimization_finder.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) {
if self.optimizations.and_stars.remove(&location) {
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 {
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>) {
no_landing_pads(tcx, mir)
}

View file

@ -942,7 +942,7 @@ pub struct QualifyAndPromoteConstants;
impl Pass for QualifyAndPromoteConstants {}
impl<'tcx> MirMapPass<'tcx> for QualifyAndPromoteConstants {
fn run_pass<'a>(&mut self,
fn run_pass<'a>(&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
hooks: &mut [Box<for<'s> MirPassHook<'s>>])
{
@ -971,7 +971,7 @@ impl<'tcx> MirMapPass<'tcx> for 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>) {
let id = src.item_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> {
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);
simplify_cfg(mir);
}
@ -320,7 +320,7 @@ impl Pass 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()) };
marker.visit_mir(mir);
// 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> {
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() {
let terminator = block.terminator_mut();
terminator.kind = match terminator.kind {

View file

@ -738,7 +738,7 @@ impl 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>) {
let item_id = src.item_id();
let def_id = tcx.hir.local_def_id(item_id);