Compilers & Code Generation

static single assignment form

/ SSA /

Imagine taking notes where you are never allowed to cross out and rewrite a value — if a quantity changes, you must give it a fresh name. So instead of 'x = 5 ... later x = 9', you write 'x1 = 5 ... x2 = 9'. It looks pedantic, but it makes one thing trivial: any name you see was set in exactly one place. Static single assignment form is an IR that follows precisely this rule.

In SSA, every variable is assigned exactly once, statically — that is, there is only one instruction in the whole function that defines a given name. When the original program reassigns a variable, the compiler renames it: x becomes x1, then x2, then x3 at each new assignment. The 'static' matters: a definition inside a loop still has one textual definition site even though it runs many times. This gives every use of a value an unambiguous, single source. The one wrinkle is control flow: when two different paths each defined a version of x and then merge, which version is in scope? SSA answers that with a special phi node that picks the right incoming version based on which path was taken.

It matters because single-assignment form makes dataflow analysis dramatically simpler. To ask 'what produced this value?' the compiler follows one link, not a search through every prior assignment; this makes constant propagation, dead-code elimination, and common-subexpression elimination cleaner and faster. SSA is the backbone IR of LLVM and most modern optimizers. A caveat: SSA is an internal form, not a feature of any source language — it is constructed by the compiler and torn back down (out of SSA) before register allocation, since real registers do get reassigned.

// original: // SSA form (rename on each assignment): x = 1; x1 = 1 x = x + 4; x2 = x1 + 4 y = x * 2; y1 = x2 * 2

Each name is defined once. Any use (like x2) points back to exactly one definition — no ambiguity.

SSA is a compiler-internal form, not a source-language rule: the compiler builds it, optimizes in it, then leaves it (de-SSA) before register allocation, because physical registers are genuinely reassigned at run time.

Also called
SSASSA form靜態單賦值形式