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]
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] Loops add backward edges, so a control-flow graph need not be acyclic.
Phi node 2026-11-05
A phi node supplies the value at a join in static single-assignment form by selecting among values associated with incoming edges. In LLVM, it lists a value and predecessor basic block for each incoming edge, and phi nodes occur before ordinary operations in their block.[ref]
For example, if the left branch defines x1=10 and the right defines x2=20, the join can define x3=phi(x1,left; x2,right). Arriving from the left gives ten; arriving from the right gives twenty. It does not average the arguments or evaluate both branches. At a loop header, another phi node can select an initial value on first entry and the updated value on later iterations. The node has one static definition even though its selected value can change across executions.
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.