]> git.lizzy.rs Git - rust.git/commitdiff
rewrite `Passes` to have sets of passes
authorNiko Matsakis <niko@alum.mit.edu>
Thu, 27 Apr 2017 17:04:57 +0000 (13:04 -0400)
committerNiko Matsakis <niko@alum.mit.edu>
Tue, 2 May 2017 18:01:01 +0000 (14:01 -0400)
Also, store the completed set of passes in the tcx.

src/librustc/mir/transform.rs
src/librustc/ty/context.rs
src/librustc_driver/driver.rs

index 14ad413c5385e5bc87d6a1c19df0dde95877e288..cfe8254d1bb628b4c9ed0af304e2b620d49d53ab 100644 (file)
@@ -167,24 +167,46 @@ fn run_pass<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
 /// A manager for MIR passes.
 #[derive(Clone)]
 pub struct Passes {
-    passes: Vec<Rc<Pass>>,
     pass_hooks: Vec<Rc<PassHook>>,
-    plugin_passes: Vec<Rc<Pass>>
+    sets: Vec<PassSet>,
+}
+
+#[derive(Clone)]
+struct PassSet {
+    passes: Vec<Rc<Pass>>,
 }
 
+/// The number of "pass sets" that we have:
+///
+/// - ready for constant evaluation
+/// - unopt
+/// - optimized
+pub const MIR_PASS_SETS: usize = 3;
+
+/// Run the passes we need to do constant qualification and evaluation.
+pub const MIR_CONST: usize = 0;
+
+/// Run the passes we need to consider the MIR validated and ready for borrowck etc.
+pub const MIR_VALIDATED: usize = 1;
+
+/// Run the passes we need to consider the MIR *optimized*.
+pub const MIR_OPTIMIZED: usize = 2;
+
 impl<'a, 'tcx> Passes {
     pub fn new() -> Passes {
-        let passes = Passes {
-            passes: Vec::new(),
+        Passes {
             pass_hooks: Vec::new(),
-            plugin_passes: Vec::new()
-        };
-        passes
+            sets: (0..MIR_PASS_SETS).map(|_| PassSet { passes: Vec::new() }).collect(),
+        }
     }
 
-    pub fn run_passes(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>) {
+    pub fn run_passes(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, set_index: usize) {
+        let set = &self.sets[set_index];
+
+        let start_num: usize = self.sets[..set_index].iter().map(|s| s.passes.len()).sum();
+
         // NB: passes are numbered from 1, since "construction" is zero.
-        for (pass, pass_num) in self.plugin_passes.iter().chain(&self.passes).zip(1..) {
+        for (pass, pass_num) in set.passes.iter().zip(start_num + 1..) {
             for hook in &self.pass_hooks {
                 hook.on_mir_pass(tcx, &**pass, pass_num, false);
             }
@@ -198,8 +220,8 @@ pub fn run_passes(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     }
 
     /// Pushes a built-in pass.
-    pub fn push_pass<T: Pass + 'static>(&mut self, pass: T) {
-        self.passes.push(Rc::new(pass));
+    pub fn push_pass<T: Pass + 'static>(&mut self, set: usize, pass: T) {
+        self.sets[set].passes.push(Rc::new(pass));
     }
 
     /// Pushes a pass hook.
@@ -207,10 +229,3 @@ pub fn push_hook<T: PassHook + 'static>(&mut self, hook: T) {
         self.pass_hooks.push(Rc::new(hook));
     }
 }
-
-/// Copies the plugin passes.
-impl ::std::iter::Extend<Rc<Pass>> for Passes {
-    fn extend<I: IntoIterator<Item=Rc<Pass>>>(&mut self, it: I) {
-        self.plugin_passes.extend(it);
-    }
-}
index 6de61013dfdd3b8583ac0c9a733b53563f5c3c22..0c189853c6195efaca60aada70de18a1d93f9742 100644 (file)
@@ -25,6 +25,7 @@
 use middle::resolve_lifetime;
 use middle::stability;
 use mir::Mir;
+use mir::transform::Passes;
 use ty::subst::{Kind, Substs};
 use ty::ReprOptions;
 use traits;
 use rustc_data_structures::indexed_vec::IndexVec;
 use std::borrow::Borrow;
 use std::cell::{Cell, RefCell};
+use std::cmp::Ordering;
 use std::hash::{Hash, Hasher};
 use std::mem;
 use std::ops::Deref;
 use std::iter;
-use std::cmp::Ordering;
+use std::rc::Rc;
 use syntax::abi;
 use syntax::ast::{self, Name, NodeId};
 use syntax::attr;
@@ -441,8 +443,11 @@ pub struct GlobalCtxt<'tcx> {
     pub named_region_map: resolve_lifetime::NamedRegionMap,
 
     pub hir: hir_map::Map<'tcx>,
+
     pub maps: maps::Maps<'tcx>,
 
+    pub mir_passes: Rc<Passes>,
+
     // Records the free variables refrenced by every closure
     // expression. Do not track deps for this, just recompute it from
     // scratch every time.
@@ -712,6 +717,7 @@ fn is_global(self) -> bool {
     pub fn create_and_enter<F, R>(s: &'tcx Session,
                                   local_providers: ty::maps::Providers<'tcx>,
                                   extern_providers: ty::maps::Providers<'tcx>,
+                                  mir_passes: Rc<Passes>,
                                   arenas: &'tcx GlobalArenas<'tcx>,
                                   arena: &'tcx DroplessArena,
                                   resolutions: ty::Resolutions,
@@ -746,6 +752,7 @@ pub fn create_and_enter<F, R>(s: &'tcx Session,
             fulfilled_predicates: RefCell::new(fulfilled_predicates),
             hir: hir,
             maps: maps::Maps::new(dep_graph, providers),
+            mir_passes,
             freevars: RefCell::new(resolutions.freevars),
             maybe_unused_trait_imports: resolutions.maybe_unused_trait_imports,
             rcache: RefCell::new(FxHashMap()),
index be344176fd25504242365da61f765047ca5a552e..89f01226113cbc059a4cdf51773ebb694bae59d0 100644 (file)
@@ -20,6 +20,7 @@
 use rustc::lint;
 use rustc::middle::{self, dependency_format, stability, reachable};
 use rustc::middle::privacy::AccessLevels;
+use rustc::mir::transform::{MIR_CONST, MIR_VALIDATED, MIR_OPTIMIZED};
 use rustc::ty::{self, TyCtxt, Resolutions, GlobalArenas};
 use rustc::util::common::time;
 use rustc::util::nodemap::NodeSet;
@@ -903,9 +904,43 @@ macro_rules! try_with_f {
     // FIXME(eddyb) get rid of this once we replace const_eval with miri.
     rustc_const_eval::provide(&mut extern_providers);
 
+    // Setup the MIR passes that we want to run.
+    let mut passes = sess.mir_passes.borrow().clone();
+    passes.push_hook(mir::transform::dump_mir::DumpMir);
+
+    // What we need to do constant evaluation.
+    passes.push_pass(MIR_CONST, mir::transform::simplify::SimplifyCfg::new("initial"));
+    passes.push_pass(MIR_CONST, mir::transform::type_check::TypeckMir);
+
+    // What we need to run borrowck etc.
+    passes.push_pass(MIR_VALIDATED, mir::transform::qualify_consts::QualifyAndPromoteConstants);
+    passes.push_pass(MIR_VALIDATED, mir::transform::simplify_branches::SimplifyBranches::new("initial"));
+    passes.push_pass(MIR_VALIDATED, mir::transform::simplify::SimplifyCfg::new("qualify-consts"));
+
+    // Optimizations begin.
+    passes.push_pass(MIR_OPTIMIZED, mir::transform::no_landing_pads::NoLandingPads);
+    passes.push_pass(MIR_OPTIMIZED, mir::transform::simplify::SimplifyCfg::new("no-landing-pads"));
+
+    // From here on out, regions are gone.
+    passes.push_pass(MIR_OPTIMIZED, mir::transform::erase_regions::EraseRegions);
+    passes.push_pass(MIR_OPTIMIZED, mir::transform::add_call_guards::AddCallGuards);
+    passes.push_pass(MIR_OPTIMIZED, borrowck::ElaborateDrops);
+    passes.push_pass(MIR_OPTIMIZED, mir::transform::no_landing_pads::NoLandingPads);
+    passes.push_pass(MIR_OPTIMIZED, mir::transform::simplify::SimplifyCfg::new("elaborate-drops"));
+
+    // No lifetime analysis based on borrowing can be done from here on out.
+    passes.push_pass(MIR_OPTIMIZED, mir::transform::inline::Inline);
+    passes.push_pass(MIR_OPTIMIZED, mir::transform::instcombine::InstCombine);
+    passes.push_pass(MIR_OPTIMIZED, mir::transform::deaggregator::Deaggregator);
+    passes.push_pass(MIR_OPTIMIZED, mir::transform::copy_prop::CopyPropagation);
+    passes.push_pass(MIR_OPTIMIZED, mir::transform::simplify::SimplifyLocals);
+    passes.push_pass(MIR_OPTIMIZED, mir::transform::add_call_guards::AddCallGuards);
+    passes.push_pass(MIR_OPTIMIZED, mir::transform::dump_mir::Marker("PreTrans"));
+
     TyCtxt::create_and_enter(sess,
                              local_providers,
                              extern_providers,
+                             Rc::new(passes),
                              arenas,
                              arena,
                              resolutions,
@@ -971,18 +1006,8 @@ macro_rules! try_with_f {
         }
 
         time(time_passes, "MIR cleanup and validation", || {
-            let mut passes = sess.mir_passes.borrow_mut();
-            // Push all the built-in validation passes.
-            // NB: if you’re adding an *optimisation* it ought to go to another set of passes
-            // in stage 4 below.
-            passes.push_hook(mir::transform::dump_mir::DumpMir);
-            passes.push_pass(mir::transform::simplify::SimplifyCfg::new("initial"));
-            passes.push_pass(mir::transform::type_check::TypeckMir);
-            passes.push_pass(mir::transform::qualify_consts::QualifyAndPromoteConstants);
-            passes.push_pass(mir::transform::simplify_branches::SimplifyBranches::new("initial"));
-            passes.push_pass(mir::transform::simplify::SimplifyCfg::new("qualify-consts"));
-            // And run everything.
-            passes.run_passes(tcx);
+            tcx.mir_passes.run_passes(tcx, MIR_CONST);
+            tcx.mir_passes.run_passes(tcx, MIR_VALIDATED);
         });
 
         time(time_passes,
@@ -1040,30 +1065,7 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // Run the passes that transform the MIR into a more suitable form for translation to LLVM
     // code.
     time(time_passes, "MIR optimisations", || {
-        let mut passes = ::rustc::mir::transform::Passes::new();
-        passes.push_hook(mir::transform::dump_mir::DumpMir);
-        passes.push_pass(mir::transform::no_landing_pads::NoLandingPads);
-        passes.push_pass(mir::transform::simplify::SimplifyCfg::new("no-landing-pads"));
-
-        // From here on out, regions are gone.
-        passes.push_pass(mir::transform::erase_regions::EraseRegions);
-
-        passes.push_pass(mir::transform::add_call_guards::AddCallGuards);
-        passes.push_pass(borrowck::ElaborateDrops);
-        passes.push_pass(mir::transform::no_landing_pads::NoLandingPads);
-        passes.push_pass(mir::transform::simplify::SimplifyCfg::new("elaborate-drops"));
-
-        // No lifetime analysis based on borrowing can be done from here on out.
-        passes.push_pass(mir::transform::inline::Inline);
-        passes.push_pass(mir::transform::instcombine::InstCombine);
-        passes.push_pass(mir::transform::deaggregator::Deaggregator);
-        passes.push_pass(mir::transform::copy_prop::CopyPropagation);
-
-        passes.push_pass(mir::transform::simplify::SimplifyLocals);
-        passes.push_pass(mir::transform::add_call_guards::AddCallGuards);
-        passes.push_pass(mir::transform::dump_mir::Marker("PreTrans"));
-
-        passes.run_passes(tcx);
+        tcx.mir_passes.run_passes(tcx, MIR_OPTIMIZED);
     });
 
     if tcx.sess.opts.debugging_opts.mir_stats {