Add a liveness verifier.
The liveness verifier will check that the live ranges are consistent with the function. It runs as part of the register allocation pipeline when enable_verifier is set. The initial implementation checks the live ranges, but not the ISA-specific constraints and affinities.
This commit is contained in:
@@ -11,6 +11,8 @@ use isa::TargetIsa;
|
||||
use regalloc::coloring::Coloring;
|
||||
use regalloc::live_value_tracker::LiveValueTracker;
|
||||
use regalloc::liveness::Liveness;
|
||||
use result::CtonResult;
|
||||
use verifier::verify_liveness;
|
||||
|
||||
/// Persistent memory allocations for register allocation.
|
||||
pub struct Context {
|
||||
@@ -40,7 +42,8 @@ impl Context {
|
||||
isa: &TargetIsa,
|
||||
func: &mut Function,
|
||||
cfg: &ControlFlowGraph,
|
||||
domtree: &DominatorTree) {
|
||||
domtree: &DominatorTree)
|
||||
-> CtonResult {
|
||||
// `Liveness` and `Coloring` are self-clearing.
|
||||
// Tracker state (dominator live sets) is actually reused between the spilling and coloring
|
||||
// phases.
|
||||
@@ -49,10 +52,16 @@ impl Context {
|
||||
// First pass: Liveness analysis.
|
||||
self.liveness.compute(isa, func, cfg);
|
||||
|
||||
if isa.flags().enable_verifier() {
|
||||
verify_liveness(isa, func, cfg, &self.liveness)?;
|
||||
}
|
||||
|
||||
// TODO: Second pass: Spilling.
|
||||
|
||||
// Third pass: Reload and coloring.
|
||||
self.coloring
|
||||
.run(isa, func, domtree, &mut self.liveness, &mut self.tracker);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,12 +174,12 @@ pub struct LiveRange {
|
||||
/// for contiguous EBBs where all but the last live-in interval covers the whole EBB.
|
||||
///
|
||||
#[derive(Copy, Clone)]
|
||||
struct Interval {
|
||||
pub struct Interval {
|
||||
/// Interval starting point.
|
||||
///
|
||||
/// Since this interval does not represent the def of the value, it must begin at an EBB header
|
||||
/// where the value is live-in.
|
||||
begin: Ebb,
|
||||
pub begin: Ebb,
|
||||
|
||||
/// Interval end point.
|
||||
///
|
||||
@@ -190,7 +190,7 @@ struct Interval {
|
||||
/// When this represents multiple contiguous live-in intervals, this is the end point of the
|
||||
/// last interval. The other intervals end at the terminator instructions of their respective
|
||||
/// EBB.
|
||||
end: Inst,
|
||||
pub end: Inst,
|
||||
}
|
||||
|
||||
impl Interval {
|
||||
@@ -368,6 +368,11 @@ impl LiveRange {
|
||||
.ok()
|
||||
.map(|n| self.liveins[n].end)
|
||||
}
|
||||
|
||||
/// Get all the live-in intervals.
|
||||
pub fn liveins(&self) -> &[Interval] {
|
||||
&self.liveins
|
||||
}
|
||||
}
|
||||
|
||||
/// Allow a `LiveRange` to be stored in a `SparseMap` indexed by values.
|
||||
|
||||
Reference in New Issue
Block a user