diff --git a/compiler/rustc_data_structures/src/graph/dominators/mod.rs b/compiler/rustc_data_structures/src/graph/dominators/mod.rs index b1f62636b89..eb6e2b296cd 100644 --- a/compiler/rustc_data_structures/src/graph/dominators/mod.rs +++ b/compiler/rustc_data_structures/src/graph/dominators/mod.rs @@ -65,16 +65,16 @@ fn dominators_given_rpo(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 { @@ -91,6 +91,10 @@ fn dominators_given_rpo(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] { @@ -111,28 +115,39 @@ fn dominators_given_rpo(graph: G, rpo: &[G::Node]) -> Domin fn eval( pre_order_index: &IndexVec>, ancestor: &mut IndexVec>, + lastlinked: Option, semi: &IndexVec, label: &mut IndexVec, 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( + pre_order_index: &IndexVec>, + v: N, + lastlinked: Option, +) -> bool { + if let Some(ll) = lastlinked { pre_order_index[v] >= pre_order_index[ll] } else { false } +} + fn compress( pre_order_index: &IndexVec>, ancestor: &mut IndexVec>, + lastlinked: Option, semi: &IndexVec, label: &mut IndexVec, 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]; } @@ -140,10 +155,6 @@ fn compress( } } -fn link(ancestor: &mut IndexVec>, parent: &IndexVec>, w: N) { - ancestor[w] = Some(parent[w].unwrap()); -} - #[derive(Clone, Debug)] pub struct Dominators { post_order_rank: IndexVec,