• ↑↓ pour naviguer
  • pour ouvrir
  • pour sélectionner
  • ⌘ ⌥ ↵ pour ouvrir dans un panneau
  • ←→ pour naviguer
  • esc pour rejeter
⌘ '
raccourcis clavier

The Problem

Loops are where programs spend most of their execution time. To optimize effectively (loop invariant code motion, induction variable elimination), the compiler must first identify which instructions belong to loops and what kind of loops they are.

Core Idea

Loop detection in TAC identifies loop structures in the control-flow graph (CFG). A loop in the CFG is a set of nodes (basic blocks) where: every node can reach the loop header, and the header dominates all nodes in the loop. The key concept is dominators — node d dominates node n if every path from entry to n goes through d.

How It Works

The compiler builds a control-flow graph from TAC instructions. It computes the dominator tree (which nodes dominate which). A back edge is identified when an edge from node n to node h has h dominating n. The loop consists of all nodes that can reach n without going through h. Natural loops have a single entry (the header) and are amenable to optimization.

Visual Explanation

loop_detection cluster_cfg Control-Flow Graph (TAC Basic Blocks) Entry B1: Entry Header B2: Loop Header (L1: t1 = i < n) Entry->Header Body1 B3: Loop Body (sum = sum + a[i]) Header->Body1 back edge Exit B5: Continue Header->Exit i >= n Body2 B4: i = i + 1 Body1->Body2 back edge Body2->Header back edge DomTree Dominator Tree: B1 dominates B2 B2 dominates B3, B4, B5 Back edge: B4 → B2 Loop = {B2, B3, B4} CFG CFG CFG->DomTree

Key Properties

  • Control-flow graph: Nodes are basic blocks; edges are jumps
  • Dominator: h dominates n if all paths from entry to n include h
  • Back edge: Edge from n to h where h dominates n
  • Natural loop: Header h + all nodes that can reach a back edge without passing through h
  • Nested loops: A loop inside another — inner loop is optimized first

Connections

Edge Cases & Gotchas

  • Irreducible loops: Multiple entry points (from goto) — cannot be identified as natural loops, require special handling
  • Outer vs inner loops: When loops are nested, the inner loop should be optimized first (maximizes benefit)
  • Infinite loops: A loop with no exit edge — the compiler must detect this to avoid infinite optimization
  • Loop-invariant code: Instructions inside the loop that produce the same value every iteration — should be moved to the pre-header