about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSimonas Kazlauskas <git@kazlauskas.me>2016-02-26 18:05:50 +0200
committerSimonas Kazlauskas <git@kazlauskas.me>2016-03-04 15:20:10 +0200
commit811b874716210f0e4135cbaa489f8b2857bbb031 (patch)
tree075fe64d61a246582301d696f4d4633dbe909c8c
parent5b5e52186917502258a9feadc8bf77a89183386b (diff)
downloadrust-811b874716210f0e4135cbaa489f8b2857bbb031.tar.gz
rust-811b874716210f0e4135cbaa489f8b2857bbb031.zip
Add Pass manager for MIR
-rw-r--r--src/librustc/dep_graph/mod.rs1
-rw-r--r--src/librustc/mir/mir_map.rs22
-rw-r--r--src/librustc/mir/repr.rs2
-rw-r--r--src/librustc/mir/transform.rs63
-rw-r--r--src/librustc/session/mod.rs6
-rw-r--r--src/librustc_driver/driver.rs28
-rw-r--r--src/librustc_mir/mir_map.rs61
-rw-r--r--src/librustc_mir/transform/erase_regions.rs18
-rw-r--r--src/librustc_mir/transform/mod.rs2
-rw-r--r--src/librustc_mir/transform/no_landing_pads.rs13
-rw-r--r--src/librustc_mir/transform/remove_dead_blocks.rs (renamed from src/librustc_mir/transform/clear_dead_blocks.rs)65
-rw-r--r--src/librustc_mir/transform/simplify_cfg.rs56
-rw-r--r--src/librustc_mir/transform/type_check.rs37
-rw-r--r--src/librustc_plugin/registry.rs6
-rw-r--r--src/test/auxiliary/dummy_mir_pass.rs9
15 files changed, 177 insertions, 212 deletions
diff --git a/src/librustc/dep_graph/mod.rs b/src/librustc/dep_graph/mod.rs
index 2fad161652f..3a04b48bb83 100644
--- a/src/librustc/dep_graph/mod.rs
+++ b/src/librustc/dep_graph/mod.rs
@@ -70,6 +70,7 @@ pub enum DepNode {
     IntrinsicCheck(DefId),
     MatchCheck(DefId),
     MirMapConstruction(DefId),
+    MirPasses,
     BorrowCheck(DefId),
     RvalueCheck(DefId),
     Reachability,
diff --git a/src/librustc/mir/mir_map.rs b/src/librustc/mir/mir_map.rs
index 933621b765f..1a34699aff4 100644
--- a/src/librustc/mir/mir_map.rs
+++ b/src/librustc/mir/mir_map.rs
@@ -8,31 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use dep_graph::DepNode;
 use util::nodemap::NodeMap;
 use mir::repr::Mir;
-use mir::transform::MirPass;
-use middle::ty::{self, TyCtxt};
-use middle::infer;
 
 pub struct MirMap<'tcx> {
     pub map: NodeMap<Mir<'tcx>>,
 }
-
-impl<'tcx> MirMap<'tcx> {
-    pub fn run_passes(&mut self, passes: &mut [Box<MirPass>], tcx: &TyCtxt<'tcx>) {
-        if passes.is_empty() { return; }
-
-        for (&id, mir) in &mut self.map {
-            let did = tcx.map.local_def_id(id);
-            let _task = tcx.dep_graph.in_task(DepNode::MirMapConstruction(did));
-
-            let param_env = ty::ParameterEnvironment::for_item(tcx, id);
-            let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, Some(param_env));
-
-            for pass in &mut *passes {
-                pass.run_on_mir(mir, &infcx)
-            }
-        }
-    }
-}
diff --git a/src/librustc/mir/repr.rs b/src/librustc/mir/repr.rs
index ce7b1ceb355..348b496112c 100644
--- a/src/librustc/mir/repr.rs
+++ b/src/librustc/mir/repr.rs
@@ -207,7 +207,7 @@ impl Debug for BasicBlock {
 }
 
 ///////////////////////////////////////////////////////////////////////////
-// BasicBlock and Terminator
+// BasicBlockData and Terminator
 
 #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
 pub struct BasicBlockData<'tcx> {
diff --git a/src/librustc/mir/transform.rs b/src/librustc/mir/transform.rs
index cc417f5a99e..5f09fe042a5 100644
--- a/src/librustc/mir/transform.rs
+++ b/src/librustc/mir/transform.rs
@@ -8,9 +8,66 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use mir::mir_map::MirMap;
 use mir::repr::Mir;
-use middle::infer::InferCtxt;
+use middle::ty::TyCtxt;
 
-pub trait MirPass {
-    fn run_on_mir<'a, 'tcx>(&mut self, mir: &mut Mir<'tcx>, infcx: &InferCtxt<'a, 'tcx>);
+/// Various information about pass.
+pub trait Pass {
+    // fn name() for printouts of various sorts?
+    // fn should_run(Session) to check if pass should run?
+}
+
+/// A pass which inspects the whole MirMap.
+pub trait MirMapPass<'tcx>: Pass {
+    fn run_pass(&mut self, cx: &TyCtxt<'tcx>, map: &mut MirMap<'tcx>);
+}
+
+pub trait MirPass<'tcx>: Pass {
+    fn run_pass(&mut self, cx: &TyCtxt<'tcx>, map: &mut Mir<'tcx>);
+}
+
+impl<'tcx, T: MirPass<'tcx>> MirMapPass<'tcx> for T {
+    fn run_pass(&mut self, tcx: &TyCtxt<'tcx>, map: &mut MirMap<'tcx>) {
+        for (_, mir) in &mut map.map {
+            MirPass::run_pass(self, tcx, mir);
+        }
+    }
+}
+
+/// A manager for MIR passes.
+pub struct Passes {
+    passes: Vec<Box<for<'tcx> MirMapPass<'tcx>>>,
+    plugin_passes: Vec<Box<for<'tcx> MirMapPass<'tcx>>>
+}
+
+impl Passes {
+    pub fn new() -> Passes {
+        let passes = Passes {
+            passes: Vec::new(),
+            plugin_passes: Vec::new()
+        };
+        passes
+    }
+
+    pub fn run_passes<'tcx>(&mut self, pcx: &TyCtxt<'tcx>, map: &mut MirMap<'tcx>) {
+        for pass in &mut self.plugin_passes {
+            pass.run_pass(pcx, map);
+        }
+        for pass in &mut self.passes {
+            pass.run_pass(pcx, map);
+        }
+    }
+
+    /// Pushes a built-in pass.
+    pub fn push_pass(&mut self, pass: Box<for<'a> MirMapPass<'a>>) {
+        self.passes.push(pass);
+    }
+}
+
+/// Copies the plugin passes.
+impl ::std::iter::Extend<Box<for<'a> MirMapPass<'a>>> for Passes {
+    fn extend<I: IntoIterator<Item=Box<for <'a> MirMapPass<'a>>>>(&mut self, it: I) {
+        self.plugin_passes.extend(it);
+    }
 }
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index d2f8d3f09fd..b198eda1812 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -13,7 +13,7 @@ use middle::cstore::CrateStore;
 use middle::dependency_format;
 use session::search_paths::PathKind;
 use util::nodemap::{NodeMap, FnvHashMap};
-use mir::transform::MirPass;
+use mir::transform as mir_pass;
 
 use syntax::ast::{NodeId, NodeIdAssigner, Name};
 use syntax::codemap::{Span, MultiSpan};
@@ -60,7 +60,7 @@ pub struct Session {
     pub lint_store: RefCell<lint::LintStore>,
     pub lints: RefCell<NodeMap<Vec<(lint::LintId, Span, String)>>>,
     pub plugin_llvm_passes: RefCell<Vec<String>>,
-    pub plugin_mir_passes: RefCell<Vec<Box<MirPass>>>,
+    pub mir_passes: RefCell<mir_pass::Passes>,
     pub plugin_attributes: RefCell<Vec<(String, AttributeType)>>,
     pub crate_types: RefCell<Vec<config::CrateType>>,
     pub dependency_formats: RefCell<dependency_format::Dependencies>,
@@ -477,7 +477,7 @@ pub fn build_session_(sopts: config::Options,
         lint_store: RefCell::new(lint::LintStore::new()),
         lints: RefCell::new(NodeMap()),
         plugin_llvm_passes: RefCell::new(Vec::new()),
-        plugin_mir_passes: RefCell::new(Vec::new()),
+        mir_passes: RefCell::new(mir_pass::Passes::new()),
         plugin_attributes: RefCell::new(Vec::new()),
         crate_types: RefCell::new(Vec::new()),
         dependency_formats: RefCell::new(FnvHashMap()),
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index 9c1be4c9f2f..d6bbb22c203 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use rustc::dep_graph::DepGraph;
+use rustc::dep_graph::{DepGraph, DepNode};
 use rustc::front;
 use rustc::front::map as hir_map;
 use rustc_mir as mir;
@@ -561,7 +561,7 @@ pub fn phase_2_configure_and_expand(sess: &Session,
         }
 
         *sess.plugin_llvm_passes.borrow_mut() = llvm_passes;
-        *sess.plugin_mir_passes.borrow_mut() = mir_passes;
+        sess.mir_passes.borrow_mut().extend(mir_passes);
         *sess.plugin_attributes.borrow_mut() = attributes.clone();
     }));
 
@@ -861,9 +861,20 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
                  "MIR dump",
                  || mir::mir_map::build_mir_for_crate(tcx));
 
-        time(time_passes,
-             "MIR passes",
-             || mir_map.run_passes(&mut sess.plugin_mir_passes.borrow_mut(), tcx));
+        time(time_passes, "MIR passes", || {
+            let _task = tcx.dep_graph.in_task(DepNode::MirPasses);
+            let mut passes = sess.mir_passes.borrow_mut();
+            // Push all the built-in passes.
+            passes.push_pass(box mir::transform::remove_dead_blocks::RemoveDeadBlocks);
+            passes.push_pass(box mir::transform::type_check::TypeckMir);
+            passes.push_pass(box mir::transform::simplify_cfg::SimplifyCfg);
+            // Late passes
+            passes.push_pass(box mir::transform::no_landing_pads::NoLandingPads);
+            passes.push_pass(box mir::transform::remove_dead_blocks::RemoveDeadBlocks);
+            passes.push_pass(box mir::transform::erase_regions::EraseRegions);
+            // And run everything.
+            passes.run_passes(tcx, &mut mir_map);
+        });
 
         time(time_passes,
              "borrow checking",
@@ -912,9 +923,8 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
 }
 
 /// Run the translation phase to LLVM, after which the AST and analysis can
-/// be discarded.
 pub fn phase_4_translate_to_llvm<'tcx>(tcx: &TyCtxt<'tcx>,
-                                       mut mir_map: MirMap<'tcx>,
+                                       mir_map: MirMap<'tcx>,
                                        analysis: ty::CrateAnalysis)
                                        -> trans::CrateTranslation {
     let time_passes = tcx.sess.time_passes();
@@ -923,10 +933,6 @@ pub fn phase_4_translate_to_llvm<'tcx>(tcx: &TyCtxt<'tcx>,
          "resolving dependency formats",
          || dependency_format::calculate(&tcx.sess));
 
-    time(time_passes,
-         "erasing regions from MIR",
-         || mir::transform::erase_regions::erase_regions(tcx, &mut mir_map));
-
     // Option dance to work around the lack of stack once closures.
     time(time_passes,
          "translation",
diff --git a/src/librustc_mir/mir_map.rs b/src/librustc_mir/mir_map.rs
index 96828628888..400035a15de 100644
--- a/src/librustc_mir/mir_map.rs
+++ b/src/librustc_mir/mir_map.rs
@@ -20,16 +20,10 @@ extern crate syntax;
 extern crate rustc_front;
 
 use build;
-use graphviz;
-use pretty;
-use transform::{clear_dead_blocks, simplify_cfg, type_check};
-use transform::{no_landing_pads};
 use rustc::dep_graph::DepNode;
 use rustc::mir::repr::Mir;
 use hair::cx::Cx;
-use std::fs::File;
 
-use rustc::mir::transform::MirPass;
 use rustc::mir::mir_map::MirMap;
 use rustc::middle::infer;
 use rustc::middle::region::CodeExtentData;
@@ -136,61 +130,16 @@ impl<'a, 'm, 'tcx> Visitor<'tcx> for InnerDump<'a,'m,'tcx> {
                 body: &'tcx hir::Block,
                 span: Span,
                 id: ast::NodeId) {
-        let (prefix, implicit_arg_tys) = match fk {
-            intravisit::FnKind::Closure =>
-                (format!("{}-", id), vec![closure_self_ty(&self.tcx, id, body.id)]),
-            _ =>
-                (format!(""), vec![]),
+        let implicit_arg_tys = if let intravisit::FnKind::Closure = fk {
+            vec![closure_self_ty(&self.tcx, id, body.id)]
+        } else {
+            vec![]
         };
 
         let param_env = ty::ParameterEnvironment::for_item(self.tcx, id);
-
         let infcx = infer::new_infer_ctxt(self.tcx, &self.tcx.tables, Some(param_env));
-
         match build_mir(Cx::new(&infcx), implicit_arg_tys, id, span, decl, body) {
-            Ok(mut mir) => {
-                clear_dead_blocks::ClearDeadBlocks::new().run_on_mir(&mut mir, &infcx);
-                type_check::TypeckMir::new().run_on_mir(&mut mir, &infcx);
-                no_landing_pads::NoLandingPads.run_on_mir(&mut mir, &infcx);
-                if self.tcx.sess.opts.mir_opt_level > 0 {
-                    simplify_cfg::SimplifyCfg::new().run_on_mir(&mut mir, &infcx);
-                }
-                let meta_item_list = self.attr
-                                         .iter()
-                                         .flat_map(|a| a.meta_item_list())
-                                         .flat_map(|l| l.iter());
-                for item in meta_item_list {
-                    if item.check_name("graphviz") || item.check_name("pretty") {
-                        match item.value_str() {
-                            Some(s) => {
-                                let filename = format!("{}{}", prefix, s);
-                                let result = File::create(&filename).and_then(|ref mut output| {
-                                    if item.check_name("graphviz") {
-                                        graphviz::write_mir_graphviz(&mir, output)
-                                    } else {
-                                        pretty::write_mir_pretty(&mir, output)
-                                    }
-                                });
-
-                                if let Err(e) = result {
-                                    self.tcx.sess.span_fatal(
-                                        item.span,
-                                        &format!("Error writing MIR {} results to `{}`: {}",
-                                                 item.name(), filename, e));
-                                }
-                            }
-                            None => {
-                                self.tcx.sess.span_err(
-                                    item.span,
-                                    &format!("{} attribute requires a path", item.name()));
-                            }
-                        }
-                    }
-                }
-
-                let previous = self.map.map.insert(id, mir);
-                assert!(previous.is_none());
-            }
+            Ok(mir) => assert!(self.map.map.insert(id, mir).is_none()),
             Err(ErrorReported) => {}
         }
 
diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs
index 53d88709add..2bab0168c52 100644
--- a/src/librustc_mir/transform/erase_regions.rs
+++ b/src/librustc_mir/transform/erase_regions.rs
@@ -15,13 +15,7 @@
 use rustc::middle::ty::{self, TyCtxt};
 use rustc::mir::repr::*;
 use rustc::mir::visit::MutVisitor;
-use rustc::mir::mir_map::MirMap;
-
-pub fn erase_regions<'tcx>(tcx: &TyCtxt<'tcx>, mir_map: &mut MirMap<'tcx>) {
-    for (_, mir) in &mut mir_map.map {
-        EraseRegionsVisitor::new(tcx).visit_mir(mir);
-    }
-}
+use rustc::mir::transform::{MirPass, Pass};
 
 struct EraseRegionsVisitor<'a, 'tcx: 'a> {
     tcx: &'a TyCtxt<'tcx>,
@@ -123,3 +117,13 @@ impl<'a, 'tcx> MutVisitor<'tcx> for EraseRegionsVisitor<'a, 'tcx> {
         self.super_constant(constant);
     }
 }
+
+pub struct EraseRegions;
+
+impl Pass for EraseRegions {}
+
+impl<'tcx> MirPass<'tcx> for EraseRegions {
+    fn run_pass(&mut self, tcx: &TyCtxt<'tcx>, mir: &mut Mir<'tcx>) {
+        EraseRegionsVisitor::new(tcx).visit_mir(mir);
+    }
+}
diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs
index adca68114fd..57690caeccb 100644
--- a/src/librustc_mir/transform/mod.rs
+++ b/src/librustc_mir/transform/mod.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-pub mod clear_dead_blocks;
+pub mod remove_dead_blocks;
 pub mod simplify_cfg;
 pub mod erase_regions;
 pub mod no_landing_pads;
diff --git a/src/librustc_mir/transform/no_landing_pads.rs b/src/librustc_mir/transform/no_landing_pads.rs
index e2c93bd4e87..c08f45a8ec4 100644
--- a/src/librustc_mir/transform/no_landing_pads.rs
+++ b/src/librustc_mir/transform/no_landing_pads.rs
@@ -11,10 +11,10 @@
 //! This pass removes the unwind branch of all the terminators when the no-landing-pads option is
 //! specified.
 
-use rustc::middle::infer;
+use rustc::middle::ty::TyCtxt;
 use rustc::mir::repr::*;
 use rustc::mir::visit::MutVisitor;
-use rustc::mir::transform::MirPass;
+use rustc::mir::transform::{Pass, MirPass};
 
 pub struct NoLandingPads;
 
@@ -40,11 +40,12 @@ impl<'tcx> MutVisitor<'tcx> for NoLandingPads {
     }
 }
 
-impl MirPass for NoLandingPads {
-    fn run_on_mir<'a, 'tcx>(&mut self, mir: &mut Mir<'tcx>,
-                            infcx: &infer::InferCtxt<'a, 'tcx>) {
-        if infcx.tcx.sess.no_landing_pads() {
+impl<'tcx> MirPass<'tcx> for NoLandingPads {
+    fn run_pass(&mut self, tcx: &TyCtxt<'tcx>, mir: &mut Mir<'tcx>) {
+        if tcx.sess.no_landing_pads() {
             self.visit_mir(mir);
         }
     }
 }
+
+impl Pass for NoLandingPads {}
diff --git a/src/librustc_mir/transform/clear_dead_blocks.rs b/src/librustc_mir/transform/remove_dead_blocks.rs
index b35d8c08f5d..308e257c20d 100644
--- a/src/librustc_mir/transform/clear_dead_blocks.rs
+++ b/src/librustc_mir/transform/remove_dead_blocks.rs
@@ -32,50 +32,55 @@
 //! this pass just replaces the blocks with empty "return" blocks
 //! and does not renumber anything.
 
-use rustc::middle::infer;
+use rustc_data_structures::bitvec::BitVector;
+use rustc::middle::ty::TyCtxt;
 use rustc::mir::repr::*;
-use rustc::mir::transform::MirPass;
+use rustc::mir::transform::{Pass, MirPass};
 
-pub struct ClearDeadBlocks;
-
-impl ClearDeadBlocks {
-    pub fn new() -> ClearDeadBlocks {
-        ClearDeadBlocks
-    }
-
-    fn clear_dead_blocks(&self, mir: &mut Mir) {
-        let mut seen = vec![false; mir.basic_blocks.len()];
+pub struct RemoveDeadBlocks;
 
+impl<'tcx> MirPass<'tcx> for RemoveDeadBlocks {
+    fn run_pass(&mut self, _: &TyCtxt<'tcx>, mir: &mut Mir<'tcx>) {
+        let mut seen = BitVector::new(mir.basic_blocks.len());
         // These blocks are always required.
-        seen[START_BLOCK.index()] = true;
-        seen[END_BLOCK.index()] = true;
+        seen.insert(START_BLOCK.index());
+        seen.insert(END_BLOCK.index());
 
-        let mut worklist = vec![START_BLOCK];
+        let mut worklist = Vec::with_capacity(4);
+        worklist.push(START_BLOCK);
         while let Some(bb) = worklist.pop() {
             for succ in mir.basic_block_data(bb).terminator().successors().iter() {
-                if !seen[succ.index()] {
-                    seen[succ.index()] = true;
+                if seen.insert(succ.index()) {
                     worklist.push(*succ);
                 }
             }
         }
+        retain_basic_blocks(mir, &seen);
+    }
+}
 
-        for (n, (block, seen)) in mir.basic_blocks.iter_mut().zip(seen).enumerate() {
-            if !seen {
-                info!("clearing block #{}: {:?}", n, block);
-                *block = BasicBlockData {
-                    statements: vec![],
-                    terminator: Some(Terminator::Return),
-                    is_cleanup: false
-                };
-            }
+impl Pass for RemoveDeadBlocks {}
+
+/// Mass removal of basic blocks to keep the ID-remapping cheap.
+fn retain_basic_blocks(mir: &mut Mir, keep: &BitVector) {
+    let num_blocks = mir.basic_blocks.len();
+
+    let mut replacements: Vec<_> = (0..num_blocks).map(BasicBlock::new).collect();
+    let mut used_blocks = 0;
+    for alive_index in keep.iter() {
+        replacements[alive_index] = BasicBlock::new(used_blocks);
+        if alive_index != used_blocks {
+            // Swap the next alive block data with the current available slot. Since alive_index is
+            // non-decreasing this is a valid operation.
+            mir.basic_blocks.swap(alive_index, used_blocks);
         }
+        used_blocks += 1;
     }
-}
+    mir.basic_blocks.truncate(used_blocks);
 
-impl MirPass for ClearDeadBlocks {
-    fn run_on_mir<'a, 'tcx>(&mut self, mir: &mut Mir<'tcx>, _: &infer::InferCtxt<'a, 'tcx>)
-    {
-        self.clear_dead_blocks(mir);
+    for bb in mir.all_basic_blocks() {
+        for target in mir.basic_block_data_mut(bb).terminator_mut().successors_mut() {
+            *target = replacements[target.index()];
+        }
     }
 }
diff --git a/src/librustc_mir/transform/simplify_cfg.rs b/src/librustc_mir/transform/simplify_cfg.rs
index 785e6db57a5..85f36df7ced 100644
--- a/src/librustc_mir/transform/simplify_cfg.rs
+++ b/src/librustc_mir/transform/simplify_cfg.rs
@@ -8,11 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use rustc_data_structures::bitvec::BitVector;
 use rustc::middle::const_eval::ConstVal;
-use rustc::middle::infer;
+use rustc::middle::ty::TyCtxt;
 use rustc::mir::repr::*;
-use rustc::mir::transform::MirPass;
+use rustc::mir::transform::{MirPass, Pass};
+
+use super::remove_dead_blocks::RemoveDeadBlocks;
 
 pub struct SimplifyCfg;
 
@@ -21,26 +22,7 @@ impl SimplifyCfg {
         SimplifyCfg
     }
 
-    fn remove_dead_blocks(&self, mir: &mut Mir) {
-        let mut seen = BitVector::new(mir.basic_blocks.len());
-        // These blocks are always required.
-        seen.insert(START_BLOCK.index());
-        seen.insert(END_BLOCK.index());
-
-        let mut worklist = Vec::with_capacity(4);
-        worklist.push(START_BLOCK);
-        while let Some(bb) = worklist.pop() {
-            for succ in mir.basic_block_data(bb).terminator().successors().iter() {
-                if seen.insert(succ.index()) {
-                    worklist.push(*succ);
-                }
-            }
-        }
-        retain_basic_blocks(mir, &seen);
-    }
-
     fn remove_goto_chains(&self, mir: &mut Mir) -> bool {
-
         // Find the target at the end of the jump chain, return None if there is a loop
         fn final_target(mir: &Mir, mut target: BasicBlock) -> Option<BasicBlock> {
             // Keep track of already seen blocks to detect loops
@@ -118,39 +100,17 @@ impl SimplifyCfg {
     }
 }
 
-impl MirPass for SimplifyCfg {
-    fn run_on_mir<'a, 'tcx>(&mut self, mir: &mut Mir<'tcx>, _: &infer::InferCtxt<'a, 'tcx>) {
+impl<'tcx> MirPass<'tcx> for SimplifyCfg {
+    fn run_pass(&mut self, tcx: &TyCtxt<'tcx>, mir: &mut Mir<'tcx>) {
         let mut changed = true;
         while changed {
             changed = self.simplify_branches(mir);
             changed |= self.remove_goto_chains(mir);
-            self.remove_dead_blocks(mir);
+            RemoveDeadBlocks.run_pass(tcx, mir);
         }
         // FIXME: Should probably be moved into some kind of pass manager
         mir.basic_blocks.shrink_to_fit();
     }
 }
 
-/// Mass removal of basic blocks to keep the ID-remapping cheap.
-fn retain_basic_blocks(mir: &mut Mir, keep: &BitVector) {
-    let num_blocks = mir.basic_blocks.len();
-
-    let mut replacements: Vec<_> = (0..num_blocks).map(BasicBlock::new).collect();
-    let mut used_blocks = 0;
-    for alive_index in keep.iter() {
-        replacements[alive_index] = BasicBlock::new(used_blocks);
-        if alive_index != used_blocks {
-            // Swap the next alive block data with the current available slot. Since alive_index is
-            // non-decreasing this is a valid operation.
-            mir.basic_blocks.swap(alive_index, used_blocks);
-        }
-        used_blocks += 1;
-    }
-    mir.basic_blocks.truncate(used_blocks);
-
-    for bb in mir.all_basic_blocks() {
-        for target in mir.basic_block_data_mut(bb).terminator_mut().successors_mut() {
-            *target = replacements[target.index()];
-        }
-    }
-}
+impl Pass for SimplifyCfg {}
diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs
index bf22c7b0b8b..21b3566418c 100644
--- a/src/librustc_mir/transform/type_check.rs
+++ b/src/librustc_mir/transform/type_check.rs
@@ -16,8 +16,9 @@ use rustc::middle::traits;
 use rustc::middle::ty::{self, Ty, TyCtxt};
 use rustc::middle::ty::fold::TypeFoldable;
 use rustc::mir::repr::*;
+use rustc::mir::mir_map::MirMap;
 use rustc::mir::tcx::LvalueTy;
-use rustc::mir::transform::MirPass;
+use rustc::mir::transform::{MirMapPass, Pass};
 use rustc::mir::visit::{self, Visitor};
 
 use syntax::codemap::{Span, DUMMY_SP};
@@ -572,27 +573,29 @@ impl TypeckMir {
     }
 }
 
-impl MirPass for TypeckMir {
-    fn run_on_mir<'a, 'tcx>(&mut self, mir: &mut Mir<'tcx>, infcx: &InferCtxt<'a, 'tcx>)
-    {
-        if infcx.tcx.sess.err_count() > 0 {
+impl<'tcx> MirMapPass<'tcx> for TypeckMir {
+    fn run_pass(&mut self, tcx: &TyCtxt<'tcx>, map: &mut MirMap<'tcx>) {
+        if tcx.sess.err_count() > 0 {
             // compiling a broken program can obviously result in a
             // broken MIR, so try not to report duplicate errors.
             return;
         }
-
-        let mut checker = TypeChecker::new(infcx);
-
-        {
-            let mut verifier = TypeVerifier::new(&mut checker, mir);
-            verifier.visit_mir(mir);
-            if verifier.errors_reported {
-                // don't do further checks to avoid ICEs
-                return;
+        for (&id, mir) in &mut map.map {
+            let param_env = ty::ParameterEnvironment::for_item(tcx, id);
+            let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, Some(param_env));
+            let mut checker = TypeChecker::new(&infcx);
+            {
+                let mut verifier = TypeVerifier::new(&mut checker, mir);
+                verifier.visit_mir(mir);
+                if verifier.errors_reported {
+                    // don't do further checks to avoid ICEs
+                    continue;
+                }
             }
+            checker.typeck_mir(mir);
+            checker.verify_obligations(mir);
         }
-
-        checker.typeck_mir(mir);
-        checker.verify_obligations(mir);
     }
 }
+
+impl Pass for TypeckMir {}
diff --git a/src/librustc_plugin/registry.rs b/src/librustc_plugin/registry.rs
index a51fd58db88..3cfd6a76dda 100644
--- a/src/librustc_plugin/registry.rs
+++ b/src/librustc_plugin/registry.rs
@@ -13,7 +13,7 @@
 use rustc::lint::{EarlyLintPassObject, LateLintPassObject, LintId, Lint};
 use rustc::session::Session;
 
-use rustc::mir::transform::MirPass;
+use rustc::mir::transform::MirMapPass;
 
 use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension, NormalTT};
 use syntax::ext::base::{IdentTT, MultiModifier, MultiDecorator};
@@ -56,7 +56,7 @@ pub struct Registry<'a> {
     pub late_lint_passes: Vec<LateLintPassObject>,
 
     #[doc(hidden)]
-    pub mir_passes: Vec<Box<MirPass>>,
+    pub mir_passes: Vec<Box<for<'pcx> MirMapPass<'pcx>>>,
 
     #[doc(hidden)]
     pub lint_groups: HashMap<&'static str, Vec<LintId>>,
@@ -141,7 +141,7 @@ impl<'a> Registry<'a> {
     }
 
     /// Register a MIR pass
-    pub fn register_mir_pass(&mut self, pass: Box<MirPass>) {
+    pub fn register_mir_pass(&mut self, pass: Box<for<'pcx> MirMapPass<'pcx>>) {
         self.mir_passes.push(pass);
     }
 
diff --git a/src/test/auxiliary/dummy_mir_pass.rs b/src/test/auxiliary/dummy_mir_pass.rs
index 16ef965e0db..aec5165f6cf 100644
--- a/src/test/auxiliary/dummy_mir_pass.rs
+++ b/src/test/auxiliary/dummy_mir_pass.rs
@@ -18,17 +18,18 @@ extern crate rustc_front;
 extern crate rustc_plugin;
 extern crate syntax;
 
-use rustc::mir::transform::MirPass;
+use rustc::mir::transform::{self, MirPass};
 use rustc::mir::repr::{Mir, Literal};
 use rustc::mir::visit::MutVisitor;
-use rustc::middle::infer::InferCtxt;
+use rustc::middle::ty;
 use rustc::middle::const_eval::ConstVal;
 use rustc_plugin::Registry;
 
 struct Pass;
 
-impl MirPass for Pass {
-    fn run_on_mir<'a, 'tcx>(&mut self, mir: &mut Mir<'tcx>, _: &InferCtxt<'a, 'tcx>) {
+impl transform::Pass for Pass {}
+impl<'tcx> MirPass<'tcx> for Pass {
+    fn run_pass(&mut self, _: &ty::ctxt<'tcx>, mir: &mut Mir<'tcx>) {
         Visitor.visit_mir(mir)
     }
 }