Skip to content

Commit

Permalink
Optimization: Merge parent and ancestor arrays
Browse files Browse the repository at this point in the history
As the paper indicates, the unprocessed vertices in the DFS tree and processed
vertices are disjoint, and we can use them in the same space, tracking only the index
of the split.
  • Loading branch information
Mark-Simulacrum committed Dec 6, 2021
1 parent e8d7248 commit c82fe0e
Showing 1 changed file with 21 additions and 10 deletions.
31 changes: 21 additions & 10 deletions compiler/rustc_data_structures/src/graph/dominators/mod.rs
Expand Up @@ -65,16 +65,16 @@ fn dominators_given_rpo<G: ControlFlowGraph>(graph: G, rpo: &[G::Node]) -> Domin
stack.pop();
}

let mut ancestor = IndexVec::from_elem_n(None, graph.num_nodes());
let mut idom = IndexVec::from_elem_n(graph.start_node(), graph.num_nodes());
let mut semi = IndexVec::from_fn_n(std::convert::identity, graph.num_nodes());
let mut label = semi.clone();
let mut bucket = IndexVec::from_elem_n(vec![], graph.num_nodes());
let mut lastlinked = None;

for &w in pre_order_nodes[1..].iter().rev() {
semi[w] = w;
for v in graph.predecessors(w) {
let x = eval(&pre_order_index, &mut ancestor, &semi, &mut label, v);
let x = eval(&pre_order_index, &mut parent, lastlinked, &semi, &mut label, v);
semi[w] = if pre_order_index[semi[w]].unwrap() < pre_order_index[semi[x]].unwrap() {
semi[w]
} else {
Expand All @@ -91,6 +91,10 @@ fn dominators_given_rpo<G: ControlFlowGraph>(graph: G, rpo: &[G::Node]) -> Domin
let y = eval(&pre_order_index, &mut ancestor, &semi, &mut label, v);
idom[v] = if pre_order_index[semi[y]] < pre_order_index[z] { y } else { z };
}

// Optimization: We share the parent array between processed and not
// processed elements; lastlinked represents the divider.
lastlinked = Some(w);
}
for &w in pre_order_nodes.iter().skip(1) {
if idom[w] != semi[w] {
Expand All @@ -111,39 +115,46 @@ fn dominators_given_rpo<G: ControlFlowGraph>(graph: G, rpo: &[G::Node]) -> Domin
fn eval<N: Idx>(
pre_order_index: &IndexVec<N, Option<usize>>,
ancestor: &mut IndexVec<N, Option<N>>,
lastlinked: Option<N>,
semi: &IndexVec<N, N>,
label: &mut IndexVec<N, N>,
node: N,
) -> N {
if ancestor[node].is_some() {
compress(pre_order_index, ancestor, semi, label, node);
if is_processed(pre_order_index, node, lastlinked) {
compress(pre_order_index, ancestor, lastlinked, semi, label, node);
label[node]
} else {
node
}
}

fn is_processed<N: Idx>(
pre_order_index: &IndexVec<N, Option<usize>>,
v: N,
lastlinked: Option<N>,
) -> bool {
if let Some(ll) = lastlinked { pre_order_index[v] >= pre_order_index[ll] } else { false }
}

fn compress<N: Idx>(
pre_order_index: &IndexVec<N, Option<usize>>,
ancestor: &mut IndexVec<N, Option<N>>,
lastlinked: Option<N>,
semi: &IndexVec<N, N>,
label: &mut IndexVec<N, N>,
v: N,
) {
assert!(is_processed(pre_order_index, v, lastlinked));
let u = ancestor[v].unwrap();
if ancestor[u].is_some() {
compress(pre_order_index, ancestor, semi, label, u);
if is_processed(pre_order_index, u, lastlinked) {
compress(pre_order_index, ancestor, lastlinked, semi, label, u);
if pre_order_index[semi[label[u]]] < pre_order_index[semi[label[v]]] {
label[v] = label[u];
}
ancestor[v] = ancestor[u];
}
}

fn link<N: Idx>(ancestor: &mut IndexVec<N, Option<N>>, parent: &IndexVec<N, Option<N>>, w: N) {
ancestor[w] = Some(parent[w].unwrap());
}

#[derive(Clone, Debug)]
pub struct Dominators<N: Idx> {
post_order_rank: IndexVec<N, usize>,
Expand Down

0 comments on commit c82fe0e

Please sign in to comment.