Add a register allocation context module.
Collect the data structures that hang around between function compilations. Provide a main entry point to the register allocator passes.
This commit is contained in:
@@ -3,10 +3,18 @@
|
|||||||
//! When compiling many small functions, it is important to avoid repeatedly allocating and
|
//! When compiling many small functions, it is important to avoid repeatedly allocating and
|
||||||
//! deallocating the data structures needed for compilation. The `Context` struct is used to hold
|
//! deallocating the data structures needed for compilation. The `Context` struct is used to hold
|
||||||
//! on to memory allocations between function compilations.
|
//! on to memory allocations between function compilations.
|
||||||
|
//!
|
||||||
|
//! The context does not hold a `TargetIsa` instance which has to be provided as an argument
|
||||||
|
//! instead. This is because an ISA instance is immutable and can be used by multiple compilation
|
||||||
|
//! contexts concurrently. Typically, you would have one context per compilation thread and only a
|
||||||
|
//! single ISA instance.
|
||||||
|
|
||||||
use cfg::ControlFlowGraph;
|
use cfg::ControlFlowGraph;
|
||||||
use dominator_tree::DominatorTree;
|
use dominator_tree::DominatorTree;
|
||||||
use ir::Function;
|
use ir::Function;
|
||||||
|
use isa::TargetIsa;
|
||||||
|
use legalize_function;
|
||||||
|
use regalloc;
|
||||||
|
|
||||||
/// Persistent data structures and compilation pipeline.
|
/// Persistent data structures and compilation pipeline.
|
||||||
pub struct Context {
|
pub struct Context {
|
||||||
@@ -18,6 +26,9 @@ pub struct Context {
|
|||||||
|
|
||||||
/// Dominator tree for `func`.
|
/// Dominator tree for `func`.
|
||||||
pub domtree: DominatorTree,
|
pub domtree: DominatorTree,
|
||||||
|
|
||||||
|
/// Register allocation context.
|
||||||
|
pub regalloc: regalloc::Context,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Context {
|
impl Context {
|
||||||
@@ -30,12 +41,23 @@ impl Context {
|
|||||||
func: Function::new(),
|
func: Function::new(),
|
||||||
cfg: ControlFlowGraph::new(),
|
cfg: ControlFlowGraph::new(),
|
||||||
domtree: DominatorTree::new(),
|
domtree: DominatorTree::new(),
|
||||||
|
regalloc: regalloc::Context::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Run the legalizer for `isa` on the function.
|
||||||
|
pub fn legalize(&mut self, isa: &TargetIsa) {
|
||||||
|
legalize_function(&mut self.func, isa);
|
||||||
|
}
|
||||||
|
|
||||||
/// Recompute the control flow graph and dominator tree.
|
/// Recompute the control flow graph and dominator tree.
|
||||||
pub fn flowgraph(&mut self) {
|
pub fn flowgraph(&mut self) {
|
||||||
self.cfg.compute(&self.func);
|
self.cfg.compute(&self.func);
|
||||||
self.domtree.compute(&self.func, &self.cfg);
|
self.domtree.compute(&self.func, &self.cfg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Run the register allocator.
|
||||||
|
pub fn regalloc(&mut self, isa: &TargetIsa) {
|
||||||
|
self.regalloc.run(isa, &mut self.func, &self.cfg, &self.domtree);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
57
lib/cretonne/src/regalloc/context.rs
Normal file
57
lib/cretonne/src/regalloc/context.rs
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
//! 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 ir::Function;
|
||||||
|
use regalloc::coloring::Coloring;
|
||||||
|
use regalloc::live_value_tracker::LiveValueTracker;
|
||||||
|
use regalloc::liveness::Liveness;
|
||||||
|
use isa::TargetIsa;
|
||||||
|
use cfg::ControlFlowGraph;
|
||||||
|
|
||||||
|
/// Persistent memory allocations for register allocation.
|
||||||
|
pub struct Context {
|
||||||
|
liveness: Liveness,
|
||||||
|
tracker: LiveValueTracker,
|
||||||
|
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(),
|
||||||
|
tracker: LiveValueTracker::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) {
|
||||||
|
// `Liveness` and `Coloring` are self-clearing.
|
||||||
|
// Tracker state (dominator live sets) is actually reused between the spilling and coloring
|
||||||
|
// phases.
|
||||||
|
self.tracker.clear();
|
||||||
|
|
||||||
|
// First pass: Liveness analysis.
|
||||||
|
self.liveness.compute(isa, func, cfg);
|
||||||
|
|
||||||
|
// TODO: Second pass: Spilling.
|
||||||
|
|
||||||
|
// Third pass: Reload and coloring.
|
||||||
|
self.coloring.run(isa, func, domtree, &mut self.liveness, &mut self.tracker);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -291,7 +291,7 @@ impl Liveness {
|
|||||||
|
|
||||||
/// Compute the live ranges of all SSA values used in `func`.
|
/// Compute the live ranges of all SSA values used in `func`.
|
||||||
/// This clears out any existing analysis stored in this data structure.
|
/// This clears out any existing analysis stored in this data structure.
|
||||||
pub fn compute(&mut self, func: &Function, cfg: &ControlFlowGraph, isa: &TargetIsa) {
|
pub fn compute(&mut self, isa: &TargetIsa, func: &Function, cfg: &ControlFlowGraph) {
|
||||||
self.ranges.clear();
|
self.ranges.clear();
|
||||||
|
|
||||||
// Get ISA data structures used for computing live range affinities.
|
// Get ISA data structures used for computing live range affinities.
|
||||||
|
|||||||
@@ -9,3 +9,6 @@ pub mod live_value_tracker;
|
|||||||
pub mod coloring;
|
pub mod coloring;
|
||||||
|
|
||||||
mod affinity;
|
mod affinity;
|
||||||
|
mod context;
|
||||||
|
|
||||||
|
pub use self::context::Context;
|
||||||
|
|||||||
Reference in New Issue
Block a user