Files
wasmtime/lib/cretonne/src/regalloc/context.rs
Jakob Stoklund Olesen 6d6035b918 CSSA verifier.
During register allocation, the code must be kept in conventional SSA
form. Add a verifier that checks this property.
2017-07-13 13:18:18 -07:00

135 lines
4.4 KiB
Rust

//! Register allocator context.
//!
//! The `Context` struct contains data structures that should be preserved across invocations of
//! the register allocator algorithm. This doesn't preserve any data between functions, but it
//! avoids allocating data structures independently for each function begin compiled.
use dominator_tree::DominatorTree;
use flowgraph::ControlFlowGraph;
use ir::Function;
use isa::TargetIsa;
use regalloc::coalescing::Coalescing;
use regalloc::coloring::Coloring;
use regalloc::live_value_tracker::LiveValueTracker;
use regalloc::liveness::Liveness;
use regalloc::reload::Reload;
use regalloc::spilling::Spilling;
use regalloc::virtregs::VirtRegs;
use result::CtonResult;
use topo_order::TopoOrder;
use verifier::{verify_context, verify_liveness, verify_cssa};
/// Persistent memory allocations for register allocation.
pub struct Context {
liveness: Liveness,
virtregs: VirtRegs,
coalescing: Coalescing,
topo: TopoOrder,
tracker: LiveValueTracker,
spilling: Spilling,
reload: Reload,
coloring: Coloring,
}
impl Context {
/// Create a new context for register allocation.
///
/// This context should be reused for multiple functions in order to avoid repeated memory
/// allocations.
pub fn new() -> Context {
Context {
liveness: Liveness::new(),
virtregs: VirtRegs::new(),
coalescing: Coalescing::new(),
topo: TopoOrder::new(),
tracker: LiveValueTracker::new(),
spilling: Spilling::new(),
reload: Reload::new(),
coloring: Coloring::new(),
}
}
/// Allocate registers in `func`.
///
/// After register allocation, all values in `func` have been assigned to a register or stack
/// location that is consistent with instruction encoding constraints.
pub fn run(&mut self,
isa: &TargetIsa,
func: &mut Function,
cfg: &ControlFlowGraph,
domtree: &DominatorTree)
-> CtonResult {
// `Liveness` and `Coloring` are self-clearing.
self.virtregs.clear();
// Tracker state (dominator live sets) is actually reused between the spilling and coloring
// phases.
self.tracker.clear();
// Pass: Liveness analysis.
self.liveness.compute(isa, func, cfg);
if isa.flags().enable_verifier() {
verify_liveness(isa, func, cfg, &self.liveness)?;
}
// Pass: Coalesce and create conventional SSA form.
self.coalescing
.conventional_ssa(isa,
func,
cfg,
domtree,
&mut self.liveness,
&mut self.virtregs);
if isa.flags().enable_verifier() {
verify_context(func, cfg, domtree, Some(isa))?;
verify_liveness(isa, func, cfg, &self.liveness)?;
verify_cssa(func, cfg, domtree, &self.liveness, &self.virtregs)?;
}
// Pass: Spilling.
self.spilling
.run(isa,
func,
domtree,
&mut self.liveness,
&self.virtregs,
&mut self.topo,
&mut self.tracker);
if isa.flags().enable_verifier() {
verify_context(func, cfg, domtree, Some(isa))?;
verify_liveness(isa, func, cfg, &self.liveness)?;
verify_cssa(func, cfg, domtree, &self.liveness, &self.virtregs)?;
}
// Pass: Reload.
self.reload
.run(isa,
func,
domtree,
&mut self.liveness,
&mut self.topo,
&mut self.tracker);
if isa.flags().enable_verifier() {
verify_context(func, cfg, domtree, Some(isa))?;
verify_liveness(isa, func, cfg, &self.liveness)?;
verify_cssa(func, cfg, domtree, &self.liveness, &self.virtregs)?;
}
// Pass: Coloring.
self.coloring
.run(isa, func, domtree, &mut self.liveness, &mut self.tracker);
if isa.flags().enable_verifier() {
verify_context(func, cfg, domtree, Some(isa))?;
verify_liveness(isa, func, cfg, &self.liveness)?;
verify_cssa(func, cfg, domtree, &self.liveness, &self.virtregs)?;
}
Ok(())
}
}