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}