Basic block 2026-11-05
A basic block is a sequence of operations with one entry at its beginning and no internal control transfer to another block. In LLVM's intermediate representation, it ends in a terminator that determines the next control transfer, such as a branch or return. Phi nodes at the beginning account for values arriving from different predecessors.[ref]
LLVM Language Reference Manual. Functions, basic-block structure; Terminator Instructions
For example,
a=x+1; b=2*a; branch next can form one basic block. A conditional branch after the first assignment would end that block and create successors. Grouping operations this way exposes paths through a control-flow graph while letting a compiler reason locally about an uninterrupted sequence. A basic block can execute repeatedly when it lies inside a loop; it is a static program region, not one execution event. Control-flow graph 2026-11-05
A control-flow graph is a directed graph whose vertices represent program regions, commonly basic blocks, and whose edges represent possible immediate control transfers. It describes which execution paths the representation permits, rather than which path one particular run takes. Compiler optimization and data-flow analysis use this structure.
For
if c then x=1 else x=2; return x, use an entry vertex with edges to separate true and false basic blocks, each leading to one join basic block. The graph has a diamond shape. The join needs the incoming value selected by the executed path; static single-assignment form represents that choice using a phi node. LLVM's tutorial constructs precisely this branch-and-join structure.[ref]Kaleidoscope: Extending the Language: Control Flow in the LLVM documentation. §5.2.4, LLVM IR for If/Then/Else and control-flow graph
Loops add backward edges, so a control-flow graph need not be acyclic. Data-flow analysis 2026-11-05
Data-flow analysis propagates facts about values or variable uses through a control-flow graph. Each program operation transforms incoming facts, and a join combines information from possible predecessor paths. A compiler can use the result to justify compiler optimization or issue warnings. Clang's introduction develops this method using sets of possible values and iteration to a fixed point.[ref]
For example, live-variable analysis asks which current values might be read later before being overwritten. For a basic block , with uses before any local definition in and definitions in , the backward equations areA use requires the incoming value; an intervening definition removes that requirement. Iterating from empty sets terminates for a finite graph and finite variable set because these equations only add facts. The result guides register allocation.
Live range 2026-11-05
A live range is the portion of a program during which a computed value must remain available for a possible future use. It connects a definition with uses reached before that value is replaced. The concept concerns a particular value's lifetime, which need not occupy the whole textual scope of its source program variable.[ref]
The LLVM Target-Independent Code Generator. Live Intervals and Live Variable Analysis
In
a = read(); b = a + 1; return b;, the value assigned to a must survive until the addition reads it. After that read it can be discarded, while b must survive until the return. Register allocation can reuse storage for values whose live ranges do not overlap. Branches and loops can make a live range span several regions of a control-flow graph, rather than one uninterrupted interval of source lines. Live-variable analysis 2026-11-05
Live-variable analysis computes which program variables may be read in the future before their current values are overwritten. It is a backward data-flow analysis: future uses make information flow toward earlier instructions. For a basic block , let contain values read before being defined in that block and let contain its definitions. ThenA value is needed on entry if the block itself first reads it, or if a successor needs it and the block does not replace it.[ref]
The LLVM Target-Independent Code Generator. Live Variable Analysis and Live Intervals
For a block
x = y + 1; return x;, y is live on entry but the old x is not. Iterating the equations over a finite control-flow graph yields a conservative answer useful for register allocation. Syntactically possible paths may include paths that execution can never take, so computed liveness need not prove that a use actually occurs. Static program analysis 2026-11-05
Static program analysis derives information about a computer program from its representation and programming language semantics, without executing each concrete input case. An analysis commonly approximates many possible executions at once. Data-flow analysis propagates such information between locations in a control-flow graph.[ref]
Data flow analysis: an informal introduction in the Clang documentation. Introduction, symbolic values and joins
For example, after
if c then x=1 else x=2, an analysis can infer that x belongs to at the join and hence is nonzero. More complicated paths may force a less precise answer. A conservative warning can therefore flag a possible failure that no actual input reaches. The guarantee depends on what the approximation includes: failing to model an external call or integer overflow can invalidate an apparent proof. Static single-assignment form 2026-11-05
Static single-assignment form is an intermediate representation in which each named value has one static definition. Repeated source assignments receive different names:
x=1; x=x+2 becomes definitions such as x1=1; x2=x1+2. This makes def-use relationships explicit without requiring a search backward for which assignment supplied a value.At a join in a control-flow graph, a phi node selects the value associated with the edge actually taken. If one branch defines
x1=1 and another defines x2=2, the join defines x3=phi(x1,left; x2,right). The node selects an incoming value, not their arithmetic average. Loop-carried values similarly use entry and back-edge arguments. LLVM specifies that phi instructions occur first in a basic block, with an incoming value for each predecessor.[ref] Static uniqueness concerns program definitions, not the number of times a loop instruction executes.