From d56ce9e8bfa0eaf8e3af5c13d92d7b4ea0dcde5c Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Wed, 24 Jan 2018 13:44:51 -0800 Subject: [PATCH] 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. --- lib/cretonne/src/dominator_tree.rs | 2 +- lib/cretonne/src/regalloc/coalescing.rs | 34 +++++++++++++++++-------- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/lib/cretonne/src/dominator_tree.rs b/lib/cretonne/src/dominator_tree.rs index 4d4e73d406..f7b7273681 100644 --- a/lib/cretonne/src/dominator_tree.rs +++ b/lib/cretonne/src/dominator_tree.rs @@ -138,7 +138,7 @@ impl DominatorTree { /// Find the last instruction in `a` that dominates `b`. /// If no instructions in `a` dominate `b`, return `None`. - fn last_dominator(&self, a: Ebb, b: B, layout: &Layout) -> Option + pub fn last_dominator(&self, a: Ebb, b: B, layout: &Layout) -> Option where B: Into, { diff --git a/lib/cretonne/src/regalloc/coalescing.rs b/lib/cretonne/src/regalloc/coalescing.rs index 2471c74284..416783b6c0 100644 --- a/lib/cretonne/src/regalloc/coalescing.rs +++ b/lib/cretonne/src/regalloc/coalescing.rs @@ -779,21 +779,33 @@ impl DomForest { // 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 // `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 // will be on the stack. We just need to find the last stack entry that actually // dominates. - // - // TODO: This search could be more efficient if we had access to - // `domtree.last_dominator()`. Each call to `dominates()` here ends up walking up - // the dominator tree starting from `node.ebb`. - let last_dom = self.stack[0..self.stack.len() - 1].iter().rposition(|n| { - domtree.dominates(n.def, node.def, &func.layout) - }); + let mut last_dom = node.def; + for &n in self.stack.iter().rev().skip(1) { + // If the node is defined at the EBB header, it does in fact dominate + // everything else pushed on the stack. + let def_inst = match n.def { + ExpandedProgramPoint::Ebb(_) => return Some(n), + ExpandedProgramPoint::Inst(i) => i, + }; - // If there is a dominating parent value, return it for interference checking. - return last_dom.map(|pos| self.stack[pos]); + // We need to find the last program point in `n.ebb` to dominate `node.def`. + 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; } }