Optimize DomForest::push_node().
The dominator tree pre-order is defined at the EBB granularity, but we are looking for dominating nodes at the instruction level. This means that we sometimes need to look higher up the DomForest stack for a dominating node, using DominatorTree::dominates() instead of DominatorTreePreorder::dominates(). Each dominance check involves the domtree.last_dominator() function scanning up the dominator tree, starting from the new node that was pushed. We can eliminate this duplicate work by exposing the last_dominator() function to push_node(). As we are searching through nodes on the stack, maintain a last_dom program point representing the previous return value from last_dominator(). This way, we're only scanning the dominator tree once.
This commit is contained in:
@@ -138,7 +138,7 @@ impl DominatorTree {
|
|||||||
|
|
||||||
/// Find the last instruction in `a` that dominates `b`.
|
/// Find the last instruction in `a` that dominates `b`.
|
||||||
/// If no instructions in `a` dominate `b`, return `None`.
|
/// If no instructions in `a` dominate `b`, return `None`.
|
||||||
fn last_dominator<B>(&self, a: Ebb, b: B, layout: &Layout) -> Option<Inst>
|
pub fn last_dominator<B>(&self, a: Ebb, b: B, layout: &Layout) -> Option<Inst>
|
||||||
where
|
where
|
||||||
B: Into<ExpandedProgramPoint>,
|
B: Into<ExpandedProgramPoint>,
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -779,21 +779,33 @@ impl DomForest {
|
|||||||
// not necessarily mean that `top.def` dominates `node.def`, though. The `top.def`
|
// not necessarily mean that `top.def` dominates `node.def`, though. The `top.def`
|
||||||
// program point may be below the last branch in `top.ebb` that dominates
|
// program point may be below the last branch in `top.ebb` that dominates
|
||||||
// `node.def`.
|
// `node.def`.
|
||||||
debug_assert!(domtree.dominates(top.ebb, node.def, &func.layout));
|
//
|
||||||
|
|
||||||
// We do know, though, that if there is a nearest value dominating `node.def`, it
|
// We do know, though, that if there is a nearest value dominating `node.def`, it
|
||||||
// will be on the stack. We just need to find the last stack entry that actually
|
// will be on the stack. We just need to find the last stack entry that actually
|
||||||
// dominates.
|
// dominates.
|
||||||
//
|
let mut last_dom = node.def;
|
||||||
// TODO: This search could be more efficient if we had access to
|
for &n in self.stack.iter().rev().skip(1) {
|
||||||
// `domtree.last_dominator()`. Each call to `dominates()` here ends up walking up
|
// If the node is defined at the EBB header, it does in fact dominate
|
||||||
// the dominator tree starting from `node.ebb`.
|
// everything else pushed on the stack.
|
||||||
let last_dom = self.stack[0..self.stack.len() - 1].iter().rposition(|n| {
|
let def_inst = match n.def {
|
||||||
domtree.dominates(n.def, node.def, &func.layout)
|
ExpandedProgramPoint::Ebb(_) => return Some(n),
|
||||||
});
|
ExpandedProgramPoint::Inst(i) => i,
|
||||||
|
};
|
||||||
|
|
||||||
// If there is a dominating parent value, return it for interference checking.
|
// We need to find the last program point in `n.ebb` to dominate `node.def`.
|
||||||
return last_dom.map(|pos| self.stack[pos]);
|
last_dom = match domtree.last_dominator(n.ebb, last_dom, &func.layout) {
|
||||||
|
None => n.ebb.into(),
|
||||||
|
Some(inst) => {
|
||||||
|
if func.layout.cmp(def_inst, inst) != cmp::Ordering::Greater {
|
||||||
|
return Some(n);
|
||||||
|
}
|
||||||
|
inst.into()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// No real dominator found on the stack.
|
||||||
|
return None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user