Skip to content

Commit

Permalink
Process current bucket instead of parent's bucket when starting loop …
Browse files Browse the repository at this point in the history
…for dominators.
  • Loading branch information
cjgillot committed May 15, 2023
1 parent 2913ad6 commit 84339a6
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 8 deletions.
16 changes: 8 additions & 8 deletions compiler/rustc_data_structures/src/graph/dominators/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,28 +109,27 @@ pub fn dominators<G: ControlFlowGraph>(graph: G) -> Dominators<G::Node> {
// they have been placed in the bucket.
//
// We compute a partial set of immediate dominators here.
let z = parent[w];
for &v in bucket[z].iter() {
for &v in bucket[w].iter() {
// This uses the result of Lemma 5 from section 2 from the original
// 1979 paper, to compute either the immediate or relative dominator
// for a given vertex v.
//
// eval returns a vertex y, for which semi[y] is minimum among
// vertices semi[v] +> y *> v. Note that semi[v] = z as we're in the
// z bucket.
// vertices semi[v] +> y *> v. Note that semi[v] = w as we're in the
// w bucket.
//
// Given such a vertex y, semi[y] <= semi[v] and idom[y] = idom[v].
// If semi[y] = semi[v], though, idom[v] = semi[v].
//
// Using this, we can either set idom[v] to be:
// * semi[v] (i.e. z), if semi[y] is z
// * semi[v] (i.e. w), if semi[y] is w
// * idom[y], otherwise
//
// We don't directly set to idom[y] though as it's not necessarily
// known yet. The second preorder traversal will cleanup by updating
// the idom for any that were missed in this pass.
let y = eval(&mut parent, lastlinked, &semi, &mut label, v);
idom[v] = if semi[y] < z { y } else { z };
idom[v] = if semi[y] < w { y } else { w };
}

// This loop computes the semi[w] for w.
Expand Down Expand Up @@ -213,10 +212,11 @@ pub fn dominators<G: ControlFlowGraph>(graph: G) -> Dominators<G::Node> {
// If we don't yet know the idom directly, then push this vertex into
// our semidominator's bucket, where it will get processed at a later
// stage to compute its immediate dominator.
if parent[w] != semi[w] {
let z = parent[w];
if z != semi[w] {
bucket[semi[w]].push(w);
} else {
idom[w] = parent[w];
idom[w] = z;
}

// Optimization: We share the parent array between processed and not
Expand Down
27 changes: 27 additions & 0 deletions compiler/rustc_data_structures/src/graph/dominators/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,30 @@ fn immediate_dominator() {
assert_eq!(dominators.immediate_dominator(2), Some(1));
assert_eq!(dominators.immediate_dominator(3), Some(2));
}

#[test]
fn transitive_dominator() {
let graph = TestGraph::new(
0,
&[
// First tree branch.
(0, 1),
(1, 2),
(2, 3),
(3, 4),
// Second tree branch.
(1, 5),
(5, 6),
// Third tree branch.
(0, 7),
// These links make 0 the dominator for 2 and 3.
(7, 2),
(5, 3),
],
);

let dom_tree = dominators(&graph);
let immediate_dominators = &dom_tree.immediate_dominators;
assert_eq!(immediate_dominators[2], Some(0));
assert_eq!(immediate_dominators[3], Some(0)); // This used to return Some(1).
}

0 comments on commit 84339a6

Please sign in to comment.