Skip to content

Commit f5aa456

Browse files
authored
Rollup merge of #132022 - Zalathar:dominator-order, r=tmiasko
Move `cmp_in_dominator_order` out of graph dominator computation Dominator-order information is only needed for coverage graphs, and is easy enough to collect by just traversing the graph again. This avoids wasted work when computing graph dominators for any other purpose.
2 parents 56eae72 + 7f4dd9b commit f5aa456

File tree

2 files changed

+24
-24
lines changed
  • compiler
    • rustc_data_structures/src/graph/dominators
    • rustc_mir_transform/src/coverage

2 files changed

+24
-24
lines changed

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

+1-22
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@
99
//! Thomas Lengauer and Robert Endre Tarjan.
1010
//! <https://www.cs.princeton.edu/courses/archive/spr03/cs423/download/dominators.pdf>
1111
12-
use std::cmp::Ordering;
13-
1412
use rustc_index::{Idx, IndexSlice, IndexVec};
1513

1614
use super::ControlFlowGraph;
@@ -64,9 +62,6 @@ fn is_small_path_graph<G: ControlFlowGraph>(g: &G) -> bool {
6462
}
6563

6664
fn dominators_impl<G: ControlFlowGraph>(graph: &G) -> Inner<G::Node> {
67-
// compute the post order index (rank) for each node
68-
let mut post_order_rank = IndexVec::from_elem_n(0, graph.num_nodes());
69-
7065
// We allocate capacity for the full set of nodes, because most of the time
7166
// most of the nodes *are* reachable.
7267
let mut parent: IndexVec<PreorderIndex, PreorderIndex> =
@@ -83,12 +78,10 @@ fn dominators_impl<G: ControlFlowGraph>(graph: &G) -> Inner<G::Node> {
8378
pre_order_to_real.push(graph.start_node());
8479
parent.push(PreorderIndex::ZERO); // the parent of the root node is the root for now.
8580
real_to_pre_order[graph.start_node()] = Some(PreorderIndex::ZERO);
86-
let mut post_order_idx = 0;
8781

8882
// Traverse the graph, collecting a number of things:
8983
//
9084
// * Preorder mapping (to it, and back to the actual ordering)
91-
// * Postorder mapping (used exclusively for `cmp_in_dominator_order` on the final product)
9285
// * Parents for each vertex in the preorder tree
9386
//
9487
// These are all done here rather than through one of the 'standard'
@@ -104,8 +97,6 @@ fn dominators_impl<G: ControlFlowGraph>(graph: &G) -> Inner<G::Node> {
10497
continue 'recurse;
10598
}
10699
}
107-
post_order_rank[pre_order_to_real[frame.pre_order_idx]] = post_order_idx;
108-
post_order_idx += 1;
109100

110101
stack.pop();
111102
}
@@ -282,7 +273,7 @@ fn dominators_impl<G: ControlFlowGraph>(graph: &G) -> Inner<G::Node> {
282273

283274
let time = compute_access_time(start_node, &immediate_dominators);
284275

285-
Inner { post_order_rank, immediate_dominators, time }
276+
Inner { immediate_dominators, time }
286277
}
287278

288279
/// Evaluate the link-eval virtual forest, providing the currently minimum semi
@@ -348,7 +339,6 @@ fn compress(
348339
/// Tracks the list of dominators for each node.
349340
#[derive(Clone, Debug)]
350341
struct Inner<N: Idx> {
351-
post_order_rank: IndexVec<N, usize>,
352342
// Even though we track only the immediate dominator of each node, it's
353343
// possible to get its full list of dominators by looking up the dominator
354344
// of each dominator.
@@ -379,17 +369,6 @@ impl<Node: Idx> Dominators<Node> {
379369
}
380370
}
381371

382-
/// Provide deterministic ordering of nodes such that, if any two nodes have a dominator
383-
/// relationship, the dominator will always precede the dominated. (The relative ordering
384-
/// of two unrelated nodes will also be consistent, but otherwise the order has no
385-
/// meaning.) This method cannot be used to determine if either Node dominates the other.
386-
pub fn cmp_in_dominator_order(&self, lhs: Node, rhs: Node) -> Ordering {
387-
match &self.kind {
388-
Kind::Path => lhs.index().cmp(&rhs.index()),
389-
Kind::General(g) => g.post_order_rank[rhs].cmp(&g.post_order_rank[lhs]),
390-
}
391-
}
392-
393372
/// Returns true if `a` dominates `b`.
394373
///
395374
/// # Panics

compiler/rustc_mir_transform/src/coverage/graph.rs

+23-2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ pub(crate) struct CoverageGraph {
2121
pub(crate) successors: IndexVec<BasicCoverageBlock, Vec<BasicCoverageBlock>>,
2222
pub(crate) predecessors: IndexVec<BasicCoverageBlock, Vec<BasicCoverageBlock>>,
2323
dominators: Option<Dominators<BasicCoverageBlock>>,
24+
/// Allows nodes to be compared in some total order such that _if_
25+
/// `a` dominates `b`, then `a < b`. If neither node dominates the other,
26+
/// their relative order is consistent but arbitrary.
27+
dominator_order_rank: IndexVec<BasicCoverageBlock, u32>,
2428
}
2529

2630
impl CoverageGraph {
@@ -54,10 +58,27 @@ impl CoverageGraph {
5458
}
5559
}
5660

57-
let mut this = Self { bcbs, bb_to_bcb, successors, predecessors, dominators: None };
61+
let num_nodes = bcbs.len();
62+
let mut this = Self {
63+
bcbs,
64+
bb_to_bcb,
65+
successors,
66+
predecessors,
67+
dominators: None,
68+
dominator_order_rank: IndexVec::from_elem_n(0, num_nodes),
69+
};
70+
assert_eq!(num_nodes, this.num_nodes());
5871

5972
this.dominators = Some(dominators::dominators(&this));
6073

74+
// The dominator rank of each node is just its index in a reverse-postorder traversal.
75+
let reverse_post_order = graph::iterate::reverse_post_order(&this, this.start_node());
76+
// The coverage graph is created by traversal, so all nodes are reachable.
77+
assert_eq!(reverse_post_order.len(), this.num_nodes());
78+
for (rank, bcb) in (0u32..).zip(reverse_post_order) {
79+
this.dominator_order_rank[bcb] = rank;
80+
}
81+
6182
// The coverage graph's entry-point node (bcb0) always starts with bb0,
6283
// which never has predecessors. Any other blocks merged into bcb0 can't
6384
// have multiple (coverage-relevant) predecessors, so bcb0 always has
@@ -162,7 +183,7 @@ impl CoverageGraph {
162183
a: BasicCoverageBlock,
163184
b: BasicCoverageBlock,
164185
) -> Ordering {
165-
self.dominators.as_ref().unwrap().cmp_in_dominator_order(a, b)
186+
self.dominator_order_rank[a].cmp(&self.dominator_order_rank[b])
166187
}
167188

168189
/// Returns the source of this node's sole in-edge, if it has exactly one.

0 commit comments

Comments
 (0)