rustc_middle/mir/loops.rs
1use rustc_index::bit_set::DenseBitSet;
2
3use super::*;
4
5/// Compute the set of loop headers in the given body. A loop header is usually defined as a block
6/// which dominates one of its predecessors. This definition is only correct for reducible CFGs.
7/// However, computing dominators is expensive, so we approximate according to the post-order
8/// traversal order. A loop header for us is a block which is visited after its predecessor in
9/// post-order. This is ok as we mostly need a heuristic.
10pub fn maybe_loop_headers(body: &Body<'_>) -> DenseBitSet<BasicBlock> {
11 let mut maybe_loop_headers = DenseBitSet::new_empty(body.basic_blocks.len());
12 let mut visited = DenseBitSet::new_empty(body.basic_blocks.len());
13 for (bb, bbdata) in traversal::postorder(body) {
14 // Post-order means we visit successors before the block for acyclic CFGs.
15 // If the successor is not visited yet, consider it a loop header.
16 for succ in bbdata.terminator().successors() {
17 if !visited.contains(succ) {
18 maybe_loop_headers.insert(succ);
19 }
20 }
21
22 // Only mark `bb` as visited after we checked the successors, in case we have a self-loop.
23 // bb1: goto -> bb1;
24 let _new = visited.insert(bb);
25 debug_assert!(_new);
26 }
27
28 maybe_loop_headers
29}