rewrite Passes
to have sets of passes
Also, store the completed set of passes in the tcx.
This commit is contained in:
parent
e9e6ccc042
commit
668886a6cc
3 changed files with 79 additions and 55 deletions
|
@ -167,24 +167,46 @@ impl<T: MirPass> DefIdPass for T {
|
||||||
/// A manager for MIR passes.
|
/// A manager for MIR passes.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Passes {
|
pub struct Passes {
|
||||||
passes: Vec<Rc<Pass>>,
|
|
||||||
pass_hooks: Vec<Rc<PassHook>>,
|
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 {
|
impl<'a, 'tcx> Passes {
|
||||||
pub fn new() -> Passes {
|
pub fn new() -> Passes {
|
||||||
let passes = Passes {
|
Passes {
|
||||||
passes: Vec::new(),
|
|
||||||
pass_hooks: Vec::new(),
|
pass_hooks: Vec::new(),
|
||||||
plugin_passes: Vec::new()
|
sets: (0..MIR_PASS_SETS).map(|_| PassSet { passes: Vec::new() }).collect(),
|
||||||
};
|
}
|
||||||
passes
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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.
|
// 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 {
|
for hook in &self.pass_hooks {
|
||||||
hook.on_mir_pass(tcx, &**pass, pass_num, false);
|
hook.on_mir_pass(tcx, &**pass, pass_num, false);
|
||||||
}
|
}
|
||||||
|
@ -198,8 +220,8 @@ impl<'a, 'tcx> Passes {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Pushes a built-in pass.
|
/// Pushes a built-in pass.
|
||||||
pub fn push_pass<T: Pass + 'static>(&mut self, pass: T) {
|
pub fn push_pass<T: Pass + 'static>(&mut self, set: usize, pass: T) {
|
||||||
self.passes.push(Rc::new(pass));
|
self.sets[set].passes.push(Rc::new(pass));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Pushes a pass hook.
|
/// Pushes a pass hook.
|
||||||
|
@ -207,10 +229,3 @@ impl<'a, 'tcx> Passes {
|
||||||
self.pass_hooks.push(Rc::new(hook));
|
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ use middle::region::{CodeExtent, CodeExtentData};
|
||||||
use middle::resolve_lifetime;
|
use middle::resolve_lifetime;
|
||||||
use middle::stability;
|
use middle::stability;
|
||||||
use mir::Mir;
|
use mir::Mir;
|
||||||
|
use mir::transform::Passes;
|
||||||
use ty::subst::{Kind, Substs};
|
use ty::subst::{Kind, Substs};
|
||||||
use ty::ReprOptions;
|
use ty::ReprOptions;
|
||||||
use traits;
|
use traits;
|
||||||
|
@ -47,11 +48,12 @@ use arena::{TypedArena, DroplessArena};
|
||||||
use rustc_data_structures::indexed_vec::IndexVec;
|
use rustc_data_structures::indexed_vec::IndexVec;
|
||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell};
|
||||||
|
use std::cmp::Ordering;
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use std::cmp::Ordering;
|
use std::rc::Rc;
|
||||||
use syntax::abi;
|
use syntax::abi;
|
||||||
use syntax::ast::{self, Name, NodeId};
|
use syntax::ast::{self, Name, NodeId};
|
||||||
use syntax::attr;
|
use syntax::attr;
|
||||||
|
@ -441,8 +443,11 @@ pub struct GlobalCtxt<'tcx> {
|
||||||
pub named_region_map: resolve_lifetime::NamedRegionMap,
|
pub named_region_map: resolve_lifetime::NamedRegionMap,
|
||||||
|
|
||||||
pub hir: hir_map::Map<'tcx>,
|
pub hir: hir_map::Map<'tcx>,
|
||||||
|
|
||||||
pub maps: maps::Maps<'tcx>,
|
pub maps: maps::Maps<'tcx>,
|
||||||
|
|
||||||
|
pub mir_passes: Rc<Passes>,
|
||||||
|
|
||||||
// Records the free variables refrenced by every closure
|
// Records the free variables refrenced by every closure
|
||||||
// expression. Do not track deps for this, just recompute it from
|
// expression. Do not track deps for this, just recompute it from
|
||||||
// scratch every time.
|
// 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,
|
pub fn create_and_enter<F, R>(s: &'tcx Session,
|
||||||
local_providers: ty::maps::Providers<'tcx>,
|
local_providers: ty::maps::Providers<'tcx>,
|
||||||
extern_providers: ty::maps::Providers<'tcx>,
|
extern_providers: ty::maps::Providers<'tcx>,
|
||||||
|
mir_passes: Rc<Passes>,
|
||||||
arenas: &'tcx GlobalArenas<'tcx>,
|
arenas: &'tcx GlobalArenas<'tcx>,
|
||||||
arena: &'tcx DroplessArena,
|
arena: &'tcx DroplessArena,
|
||||||
resolutions: ty::Resolutions,
|
resolutions: ty::Resolutions,
|
||||||
|
@ -746,6 +752,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||||
fulfilled_predicates: RefCell::new(fulfilled_predicates),
|
fulfilled_predicates: RefCell::new(fulfilled_predicates),
|
||||||
hir: hir,
|
hir: hir,
|
||||||
maps: maps::Maps::new(dep_graph, providers),
|
maps: maps::Maps::new(dep_graph, providers),
|
||||||
|
mir_passes,
|
||||||
freevars: RefCell::new(resolutions.freevars),
|
freevars: RefCell::new(resolutions.freevars),
|
||||||
maybe_unused_trait_imports: resolutions.maybe_unused_trait_imports,
|
maybe_unused_trait_imports: resolutions.maybe_unused_trait_imports,
|
||||||
rcache: RefCell::new(FxHashMap()),
|
rcache: RefCell::new(FxHashMap()),
|
||||||
|
|
|
@ -20,6 +20,7 @@ use rustc::session::search_paths::PathKind;
|
||||||
use rustc::lint;
|
use rustc::lint;
|
||||||
use rustc::middle::{self, dependency_format, stability, reachable};
|
use rustc::middle::{self, dependency_format, stability, reachable};
|
||||||
use rustc::middle::privacy::AccessLevels;
|
use rustc::middle::privacy::AccessLevels;
|
||||||
|
use rustc::mir::transform::{MIR_CONST, MIR_VALIDATED, MIR_OPTIMIZED};
|
||||||
use rustc::ty::{self, TyCtxt, Resolutions, GlobalArenas};
|
use rustc::ty::{self, TyCtxt, Resolutions, GlobalArenas};
|
||||||
use rustc::util::common::time;
|
use rustc::util::common::time;
|
||||||
use rustc::util::nodemap::NodeSet;
|
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.
|
// FIXME(eddyb) get rid of this once we replace const_eval with miri.
|
||||||
rustc_const_eval::provide(&mut extern_providers);
|
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,
|
TyCtxt::create_and_enter(sess,
|
||||||
local_providers,
|
local_providers,
|
||||||
extern_providers,
|
extern_providers,
|
||||||
|
Rc::new(passes),
|
||||||
arenas,
|
arenas,
|
||||||
arena,
|
arena,
|
||||||
resolutions,
|
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", || {
|
time(time_passes, "MIR cleanup and validation", || {
|
||||||
let mut passes = sess.mir_passes.borrow_mut();
|
tcx.mir_passes.run_passes(tcx, MIR_CONST);
|
||||||
// Push all the built-in validation passes.
|
tcx.mir_passes.run_passes(tcx, MIR_VALIDATED);
|
||||||
// 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);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
time(time_passes,
|
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
|
// Run the passes that transform the MIR into a more suitable form for translation to LLVM
|
||||||
// code.
|
// code.
|
||||||
time(time_passes, "MIR optimisations", || {
|
time(time_passes, "MIR optimisations", || {
|
||||||
let mut passes = ::rustc::mir::transform::Passes::new();
|
tcx.mir_passes.run_passes(tcx, MIR_OPTIMIZED);
|
||||||
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);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if tcx.sess.opts.debugging_opts.mir_stats {
|
if tcx.sess.opts.debugging_opts.mir_stats {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue