blob: ae332913c642125031a53f8d0fdc75a273719bf1 [file] [log] [blame]
use rustc_index::bit_set::DenseBitSet;
use super::*;
/// Compute the set of loop headers in the given body. A loop header is usually defined as a block
/// which dominates one of its predecessors. This definition is only correct for reducible CFGs.
/// However, computing dominators is expensive, so we approximate according to the post-order
/// traversal order. A loop header for us is a block which is visited after its predecessor in
/// post-order. This is ok as we mostly need a heuristic.
pub fn maybe_loop_headers(body: &Body<'_>) -> DenseBitSet<BasicBlock> {
let mut maybe_loop_headers = DenseBitSet::new_empty(body.basic_blocks.len());
let mut visited = DenseBitSet::new_empty(body.basic_blocks.len());
for (bb, bbdata) in traversal::postorder(body) {
// Post-order means we visit successors before the block for acyclic CFGs.
// If the successor is not visited yet, consider it a loop header.
for succ in bbdata.terminator().successors() {
if !visited.contains(succ) {
maybe_loop_headers.insert(succ);
}
}
// Only mark `bb` as visited after we checked the successors, in case we have a self-loop.
// bb1: goto -> bb1;
let _new = visited.insert(bb);
debug_assert!(_new);
}
maybe_loop_headers
}