Dampen quadratic behavior in check_cssa().
Use a dominator tree pre-order to speed up the dominance checks and only check for interference with the nearest dominating predecessor in a virtual register. This makes the CSSA verification about 2x as fast.
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
//! Verify conventional SSA form.
|
//! Verify conventional SSA form.
|
||||||
|
|
||||||
use dbg::DisplayList;
|
use dbg::DisplayList;
|
||||||
use dominator_tree::DominatorTree;
|
use dominator_tree::{DominatorTree, DominatorTreePreorder};
|
||||||
use flowgraph::ControlFlowGraph;
|
use flowgraph::ControlFlowGraph;
|
||||||
use ir::{Function, ExpandedProgramPoint};
|
use ir::{Function, ExpandedProgramPoint};
|
||||||
use regalloc::liveness::Liveness;
|
use regalloc::liveness::Liveness;
|
||||||
@@ -31,12 +31,17 @@ pub fn verify_cssa(
|
|||||||
virtregs: &VirtRegs,
|
virtregs: &VirtRegs,
|
||||||
) -> Result {
|
) -> Result {
|
||||||
let _tt = timing::verify_cssa();
|
let _tt = timing::verify_cssa();
|
||||||
|
|
||||||
|
let mut preorder = DominatorTreePreorder::new();
|
||||||
|
preorder.compute(domtree, &func.layout);
|
||||||
|
|
||||||
let verifier = CssaVerifier {
|
let verifier = CssaVerifier {
|
||||||
func,
|
func,
|
||||||
cfg,
|
cfg,
|
||||||
domtree,
|
domtree,
|
||||||
virtregs,
|
virtregs,
|
||||||
liveness,
|
liveness,
|
||||||
|
preorder,
|
||||||
};
|
};
|
||||||
verifier.check_virtregs()?;
|
verifier.check_virtregs()?;
|
||||||
verifier.check_cssa()?;
|
verifier.check_cssa()?;
|
||||||
@@ -49,6 +54,7 @@ struct CssaVerifier<'a> {
|
|||||||
domtree: &'a DominatorTree,
|
domtree: &'a DominatorTree,
|
||||||
virtregs: &'a VirtRegs,
|
virtregs: &'a VirtRegs,
|
||||||
liveness: &'a Liveness,
|
liveness: &'a Liveness,
|
||||||
|
preorder: DominatorTreePreorder,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> CssaVerifier<'a> {
|
impl<'a> CssaVerifier<'a> {
|
||||||
@@ -72,6 +78,7 @@ impl<'a> CssaVerifier<'a> {
|
|||||||
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: ExpandedProgramPoint = self.func.dfg.value_def(prev_val).into();
|
let prev_def: ExpandedProgramPoint = self.func.dfg.value_def(prev_val).into();
|
||||||
|
let prev_ebb = self.func.layout.pp_ebb(prev_def);
|
||||||
|
|
||||||
if prev_def == def {
|
if prev_def == def {
|
||||||
return err!(
|
return err!(
|
||||||
@@ -85,7 +92,9 @@ impl<'a> CssaVerifier<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Enforce topological ordering of defs in the virtual register.
|
// Enforce topological ordering of defs in the virtual register.
|
||||||
if self.domtree.dominates(def, prev_def, &self.func.layout) {
|
if self.preorder.dominates(def_ebb, prev_ebb) &&
|
||||||
|
self.domtree.dominates(def, prev_def, &self.func.layout)
|
||||||
|
{
|
||||||
return err!(
|
return err!(
|
||||||
val,
|
val,
|
||||||
"Value in {} = {} def dominates previous {}",
|
"Value in {} = {} def dominates previous {}",
|
||||||
@@ -94,18 +103,30 @@ impl<'a> CssaVerifier<'a> {
|
|||||||
prev_val
|
prev_val
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Knowing that values are in topo 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);
|
// We only have to check against the nearest dominating value.
|
||||||
if self.liveness[prev_val].overlaps_def(def, def_ebb, ctx) {
|
for &prev_val in values[0..idx].iter().rev() {
|
||||||
return err!(
|
let prev_def: ExpandedProgramPoint = self.func.dfg.value_def(prev_val).into();
|
||||||
val,
|
let prev_ebb = self.func.layout.pp_ebb(prev_def);
|
||||||
"Value def in {} = {} interferes with {}",
|
|
||||||
vreg,
|
if self.preorder.dominates(prev_ebb, def_ebb) &&
|
||||||
DisplayList(values),
|
self.domtree.dominates(prev_def, def, &self.func.layout)
|
||||||
prev_val
|
{
|
||||||
);
|
let ctx = self.liveness.context(&self.func.layout);
|
||||||
|
if self.liveness[prev_val].overlaps_def(def, def_ebb, ctx) {
|
||||||
|
return err!(
|
||||||
|
val,
|
||||||
|
"Value def in {} = {} interferes with {}",
|
||||||
|
vreg,
|
||||||
|
DisplayList(values),
|
||||||
|
prev_val
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user