A dominator tree can be used to compute natural loops.
- For every node
H
in a post-order traversal of the dominator tree (or the original CFG), find all predecessors that are dominated byH
. This identifies all back edges. - Each back edge
T->H
identifies a natural loop withH
as the header.- Perform a flood fill starting from
T
in the reversed dominator tree (from exiting block to header) - All visited nodes reachable from the root belong to the natural loop
associated with the back edge. These nodes are guaranteed to be
reachable from
H
due to the dominator property. - Visited nodes unreachable from the root should be ignored.
- Loops associated with visited nodes are considered subloops.
- Perform a flood fill starting from
Here is an C++ implementation:
1 |
|
The code iterates over the dominator tree in post-order. Alternatively, a post-order traversal of the original control flow graph could be used.
worklist
may contain duplicate elements. This is
acceptable. You could also deduplicate elements.
Importantly, the header predecessor of a subloop can be another subloop.
In the final loops
array, parent loops are listed after
their child loops.
This example examines multiple subtle details: a self-loop (node 6), an unreachable node (node 8), and a scenario where the header predecessor of one subloop (nodes 2 and 3) leads to another subloop (nodes 4 and 5).
1 | 9 12 |
Use
awk 'BEGIN{print "digraph G{"} NR>1{print $1"->"$2} END{print "}"}'
to generate a graphviz dot file.