
Ordinary source code lets a variable be written over and over — x = 1, then later x = x + 1, then later still x = f(x) — and a compiler trying to reason about what x actually holds at any point has to track a shifting history through every line. Static Single Assignment form refuses that ambiguity by a simple rule: every name gets exactly one assignment, for its entire life. Reassign x in the source and the compiler invents x1, x2, x3 — new names for each new definition — so that anywhere a name appears, there is exactly one place upstream that put a value into it. The question "where did this come from" always has one answer.
The trouble comes at the seams where control flow rejoins — after an if/else, after a loop — where two different definitions of what used to be the same variable might both be live, depending on which branch executed. SSA answers this with a small, honest fiction: a φ-function sitting at the join point, one for each variable with more than one incoming definition, that says "this name equals x1 if we arrived from the left, x2 if from the right." It doesn't resolve the ambiguity, it names it, precisely, at the one point where it exists.
Deciding exactly where a φ-function is needed is not guesswork — it follows directly from a variable's dominance frontier, the set of places reachable from a definition where that definition's exclusive rule of "one true value" first breaks down because some other path could have arrived instead. Compute dominance once, over the whole control-flow graph, and every join point that needs reconciling reveals itself as a fact of the graph's shape, not a rule anyone has to invent case by case.
All that renamed clarity is scaffolding, in the end. Before the code can run on real hardware, the finite population of physical registers has to absorb this unlimited invented cast of names — allocation as graph coloring, φ-functions dissolving back into ordinary moves at the boundaries they once marked. The single assignment was never permanent. It was a way of thinking clearly for exactly as long as thinking clearly was needed.
Seed: Compiler Intermediate Representations — Static Single Assignment (SSA) Form, Dominance Frontiers, Register Allocation.