[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