rewrite Passes to have sets of passes

Also, store the completed set of passes in the tcx.
This commit is contained in:
Niko Matsakis 2017-04-27 13:04:57 -04:00
parent e9e6ccc042
commit 668886a6cc
3 changed files with 79 additions and 55 deletions

View File

@ -167,24 +167,46 @@ impl<T: MirPass> DefIdPass for T {
/// 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 @@ impl<'a, 'tcx> Passes {
}
/// 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 @@ impl<'a, 'tcx> Passes {
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);
}
}

View File

@ -25,6 +25,7 @@ use middle::region::{CodeExtent, CodeExtentData};
use middle::resolve_lifetime;
use middle::stability;
use mir::Mir;
use mir::transform::Passes;
use ty::subst::{Kind, Substs};
use ty::ReprOptions;
use traits;
@ -47,11 +48,12 @@ use arena::{TypedArena, DroplessArena};
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 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
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 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
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()),

View File

@ -20,6 +20,7 @@ use rustc::session::search_paths::PathKind;
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 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
// 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 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
}
time(time_passes, "MIR cleanup and validation", || {
let mut passes = sess.mir_passes.borrow_mut();
// Push all the built-in validation passes.
// NB: if youre 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 {