[llvm] [CycleInfo] Identify cycles with a single-pass DFS algorithm (PR #210491)
Alexis Engelke via llvm-commits
llvm-commits at lists.llvm.org
Sat Jul 18 00:09:07 PDT 2026
aengelke wrote:
For reference, this is the pseudo-code from the paper (which unfortunately is not easily accessible):
```
procedure identify_loops(CFG G=(N,E,h0)):
foreach(Block b in N): // init
initialize(b); // zeroize flags & properties
trav_loops_DFS(h0,1);
function trav_loops_DFS(Block b0, int DFSP_pos):
//return: innermost loop header of b0
Mark b0 as traversed;
b0.DFSP_pos := DFSP_pos;//Mark b0’s position in DFSP
foreach(Block b in Succ(b0)):
if(b is not traversed):
// case(A), new
Block nh := trav_loops_DFS(b, DFSP_pos+1);
tag_lhead(b0, nh);
else:
if(b.DFSP_pos > 0): // b in DFSP(b0)
// case(B)
Mark b as a loop header;
tag_lhead(b0, b);
else if(b.iloop_header == nil):
// case(C), do nothing
else:
Block h := b.iloop_header;
if(h.DFSP_pos > 0): // h in DFSP(b0)
// case(D)
tag_lhead(b0, h);
else: // h not in DFSP(b0)
// case(E), reentry
Mark b and (b0,b) as re-entry;
Mark the loop of h as irreducible;
while(h.iloop_header!=nil):
h := h.iloop_header;
if(h.DFSP_pos > 0): // h in DFSP(b0)
tag_lhead(b0, h);
break;
Mark the loop of h as irreducible;
b0.DFSP_pos := 0; // clear b0’s DFSP position
return b0.iloop_header;
procedure tag_lhead(Block b, Block h):
if(b == h or h == nil) return;
Block cur1 := b, cur2 := h;
while(cur1.iloop_header!=nil):
Block ih := cur1.iloop_header;
if(ih == cur2) return;
if(ih.DFSP_pos < cur2.DFSP_pos):
cur1.iloop_header := cur2;
cur1 := cur2;
cur2 := ih;
else:
cur1 := ih;
cur1.iloop_header := cur2;
```
The algorithm has a worst-case complexity of O(N+d*E) (d=max depth), which, although quadratic in the worst case, is acceptable, as the loop nesting depth is typically very small and the two loops in question are very tight. Also, some transforms have a runtime of O(d^3) already.
https://github.com/llvm/llvm-project/pull/210491
More information about the llvm-commits
mailing list