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:
Jakob Stoklund Olesen
2017-04-21 13:35:20 -07:00
parent 225ed39fbd
commit 85f277a2fb
6 changed files with 220 additions and 23 deletions

View File

@@ -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(())
}
}

View File

@@ -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.