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:
@@ -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.
|
||||||
|
|||||||
@@ -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 => {}
|
|
||||||
Ordering::Equal => {
|
|
||||||
return err!(val, "Value in {} has same def as {}", vreg, prev_val);
|
|
||||||
}
|
|
||||||
Ordering::Greater => {
|
|
||||||
return err!(
|
return err!(
|
||||||
val,
|
val,
|
||||||
"Value in {} in wrong order relative to {}",
|
"Value in {} = {} def dominates previous {}",
|
||||||
vreg,
|
vreg,
|
||||||
|
DisplayList(values),
|
||||||
prev_val
|
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
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user