Skip to content

Commit c82fe0e

Browse files
Optimization: Merge parent and ancestor arrays
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.
1 parent e8d7248 commit c82fe0e

File tree

1 file changed

+21
-10
lines changed
  • compiler/rustc_data_structures/src/graph/dominators

1 file changed

+21
-10
lines changed

compiler/rustc_data_structures/src/graph/dominators/mod.rs

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -65,16 +65,16 @@ fn dominators_given_rpo<G: ControlFlowGraph>(graph: G, rpo: &[G::Node]) -> Domin
6565
stack.pop();
6666
}
6767

68-
let mut ancestor = IndexVec::from_elem_n(None, graph.num_nodes());
6968
let mut idom = IndexVec::from_elem_n(graph.start_node(), graph.num_nodes());
7069
let mut semi = IndexVec::from_fn_n(std::convert::identity, graph.num_nodes());
7170
let mut label = semi.clone();
7271
let mut bucket = IndexVec::from_elem_n(vec![], graph.num_nodes());
72+
let mut lastlinked = None;
7373

7474
for &w in pre_order_nodes[1..].iter().rev() {
7575
semi[w] = w;
7676
for v in graph.predecessors(w) {
77-
let x = eval(&pre_order_index, &mut ancestor, &semi, &mut label, v);
77+
let x = eval(&pre_order_index, &mut parent, lastlinked, &semi, &mut label, v);
7878
semi[w] = if pre_order_index[semi[w]].unwrap() < pre_order_index[semi[x]].unwrap() {
7979
semi[w]
8080
} else {
@@ -91,6 +91,10 @@ fn dominators_given_rpo<G: ControlFlowGraph>(graph: G, rpo: &[G::Node]) -> Domin
9191
let y = eval(&pre_order_index, &mut ancestor, &semi, &mut label, v);
9292
idom[v] = if pre_order_index[semi[y]] < pre_order_index[z] { y } else { z };
9393
}
94+
95+
// Optimization: We share the parent array between processed and not
96+
// processed elements; lastlinked represents the divider.
97+
lastlinked = Some(w);
9498
}
9599
for &w in pre_order_nodes.iter().skip(1) {
96100
if idom[w] != semi[w] {
@@ -111,39 +115,46 @@ fn dominators_given_rpo<G: ControlFlowGraph>(graph: G, rpo: &[G::Node]) -> Domin
111115
fn eval<N: Idx>(
112116
pre_order_index: &IndexVec<N, Option<usize>>,
113117
ancestor: &mut IndexVec<N, Option<N>>,
118+
lastlinked: Option<N>,
114119
semi: &IndexVec<N, N>,
115120
label: &mut IndexVec<N, N>,
116121
node: N,
117122
) -> N {
118-
if ancestor[node].is_some() {
119-
compress(pre_order_index, ancestor, semi, label, node);
123+
if is_processed(pre_order_index, node, lastlinked) {
124+
compress(pre_order_index, ancestor, lastlinked, semi, label, node);
120125
label[node]
121126
} else {
122127
node
123128
}
124129
}
125130

131+
fn is_processed<N: Idx>(
132+
pre_order_index: &IndexVec<N, Option<usize>>,
133+
v: N,
134+
lastlinked: Option<N>,
135+
) -> bool {
136+
if let Some(ll) = lastlinked { pre_order_index[v] >= pre_order_index[ll] } else { false }
137+
}
138+
126139
fn compress<N: Idx>(
127140
pre_order_index: &IndexVec<N, Option<usize>>,
128141
ancestor: &mut IndexVec<N, Option<N>>,
142+
lastlinked: Option<N>,
129143
semi: &IndexVec<N, N>,
130144
label: &mut IndexVec<N, N>,
131145
v: N,
132146
) {
147+
assert!(is_processed(pre_order_index, v, lastlinked));
133148
let u = ancestor[v].unwrap();
134-
if ancestor[u].is_some() {
135-
compress(pre_order_index, ancestor, semi, label, u);
149+
if is_processed(pre_order_index, u, lastlinked) {
150+
compress(pre_order_index, ancestor, lastlinked, semi, label, u);
136151
if pre_order_index[semi[label[u]]] < pre_order_index[semi[label[v]]] {
137152
label[v] = label[u];
138153
}
139154
ancestor[v] = ancestor[u];
140155
}
141156
}
142157

143-
fn link<N: Idx>(ancestor: &mut IndexVec<N, Option<N>>, parent: &IndexVec<N, Option<N>>, w: N) {
144-
ancestor[w] = Some(parent[w].unwrap());
145-
}
146-
147158
#[derive(Clone, Debug)]
148159
pub struct Dominators<N: Idx> {
149160
post_order_rank: IndexVec<N, usize>,

0 commit comments

Comments
 (0)