Loosen the required order of values in a virtual register.

Instead of requiring the values in a virtual register to be sorted
according to the domtree.rpo_cmp() order, just require any topological
ordering w.r.t. dominance.

The coalescer with stop using the RPO shortly.
This commit is contained in:
Jakob Stoklund Olesen
2017-12-12 16:16:01 -06:00
parent a825427786
commit 2473661d49
2 changed files with 23 additions and 25 deletions

View File

@@ -33,9 +33,6 @@ pub struct VirtRegs {
pool: ListPool<Value>, pool: ListPool<Value>,
/// The primary table of virtual registers. /// The primary table of virtual registers.
///
/// The list of values ion a virtual register is kept sorted according to the dominator tree's
/// RPO of the value defs.
vregs: PrimaryMap<VirtReg, ValueList>, vregs: PrimaryMap<VirtReg, ValueList>,
/// Each value belongs to at most one virtual register. /// Each value belongs to at most one virtual register.
@@ -65,8 +62,8 @@ impl VirtRegs {
self.value_vregs[value].into() self.value_vregs[value].into()
} }
/// Get the list of values in `vreg`. The values are ordered according to `DomTree::rpo_cmp` of /// Get the list of values in `vreg`.
/// their definition points. /// The values are topologically ordered according dominance of their definition points.
pub fn values(&self, vreg: VirtReg) -> &[Value] { pub fn values(&self, vreg: VirtReg) -> &[Value] {
self.vregs[vreg].as_slice(&self.pool) self.vregs[vreg].as_slice(&self.pool)
} }
@@ -103,7 +100,7 @@ impl VirtRegs {
/// If a value belongs to a virtual register, all of the values in that register must be /// If a value belongs to a virtual register, all of the values in that register must be
/// present. /// present.
/// ///
/// The values are assumed to already be in RPO order. /// The values are assumed to already be in topological order.
pub fn unify(&mut self, values: &[Value]) -> VirtReg { pub fn unify(&mut self, values: &[Value]) -> VirtReg {
// Start by clearing all virtual registers involved. // Start by clearing all virtual registers involved.
// Pick a virtual register to reuse (the smallest number) or allocate a new one. // Pick a virtual register to reuse (the smallest number) or allocate a new one.

View File

@@ -1,11 +1,11 @@
//! Verify conventional SSA form. //! Verify conventional SSA form.
use dbg::DisplayList;
use dominator_tree::DominatorTree; use dominator_tree::DominatorTree;
use flowgraph::ControlFlowGraph; use flowgraph::ControlFlowGraph;
use ir::Function; use ir::Function;
use regalloc::liveness::Liveness; use regalloc::liveness::Liveness;
use regalloc::virtregs::VirtRegs; use regalloc::virtregs::VirtRegs;
use std::cmp::Ordering;
use timing; use timing;
use verifier::Result; use verifier::Result;
@@ -20,7 +20,7 @@ use verifier::Result;
/// ///
/// Additionally, we verify this property of virtual registers: /// Additionally, we verify this property of virtual registers:
/// ///
/// - The values in a virtual register are ordered according to the dominator tree's `rpo_cmp()`. /// - The values in a virtual register are topologically ordered w.r.t. dominance.
/// ///
/// We don't verify that virtual registers are minimal. Minimal CSSA is not required. /// We don't verify that virtual registers are minimal. Minimal CSSA is not required.
pub fn verify_cssa( pub fn verify_cssa(
@@ -67,33 +67,34 @@ impl<'a> CssaVerifier<'a> {
return err!(val, "Value in {} has no live range", vreg); return err!(val, "Value in {} has no live range", vreg);
}; };
// Check RPO ordering with the previous values in the virtual register. // Check topological ordering with the previous values in the virtual register.
let def = self.func.dfg.value_def(val).into(); let def = self.func.dfg.value_def(val).into();
let def_ebb = self.func.layout.pp_ebb(def); let def_ebb = self.func.layout.pp_ebb(def);
for &prev_val in &values[0..idx] { for &prev_val in &values[0..idx] {
let prev_def = self.func.dfg.value_def(prev_val); let prev_def = self.func.dfg.value_def(prev_val);
// Enforce RPO of defs in the virtual register. // Enforce topological ordering of defs in the virtual register.
match self.domtree.rpo_cmp(prev_def, def, &self.func.layout) { if self.domtree.dominates(def, prev_def, &self.func.layout) {
Ordering::Less => {} return err!(
Ordering::Equal => { val,
return err!(val, "Value in {} has same def as {}", vreg, prev_val); "Value in {} = {} def dominates previous {}",
} vreg,
Ordering::Greater => { DisplayList(values),
return err!( prev_val
val, );
"Value in {} in wrong order relative to {}",
vreg,
prev_val
);
}
} }
// Knowing that values are in RPO order, we can check for interference this // Knowing that values are in topo order, we can check for interference this
// way. // way.
let ctx = self.liveness.context(&self.func.layout); let ctx = self.liveness.context(&self.func.layout);
if self.liveness[prev_val].overlaps_def(def, def_ebb, ctx) { if self.liveness[prev_val].overlaps_def(def, def_ebb, ctx) {
return err!(val, "Value def in {} interferes with {}", vreg, prev_val); return err!(
val,
"Value def in {} = {} interferes with {}",
vreg,
DisplayList(values),
prev_val
);
} }
} }
} }