Efficiently Computing SSA
Static Single Assignment form Each name is defined exactly once Each use refers to exactly one name Why use SSA form?
Joins What to do when two different values meet on the Control Flow Graph? Φ-Functions A Φ-function is a special kind of copy that selects one of its parameters
Sparse Representation Only want to propagate facts where relevant Don’t care about the rest Use the SSA Graph
SSA Graph Add edges from definitions to uses
Example i = j = k = l = 1 repeat if (p) then begin j = i if Q then l = 2 else l = 3 k = k + 1 end else k = k + 2 print (i,j,k,l) if R then l = l + 4 until S i = i + 6 until T
Example Number existing defns i = j = k = l = 1 repeat if (p) then begin j = i if Q then l = 2 else l = 3 k = k + 1 end else k = k + 2 print (i,j,k,l) if R then l = l + 4 until S i = i + 6 until T i1 = j = k = l = 1 repeat if (p) then begin j = i if Q then l = 2 else l = 3 k = k + 1 end else k = k + 2 print (i,j,k,l) if R then l = l + 4 until S i2 = i + 6 until T
Example Add ϕ-functions where needed i1 = j = k = l = 1 repeat i3 = ϕ() if (p) then begin j = i if Q then l = 2 else l = 3 k = k + 1 end else k = k + 2 print (i,j,k,l) if R then l = l + 4 until S i2 = i + 6 until T i = j = k = l = 1 repeat if (p) then begin j = i if Q then l = 2 else l = 3 k = k + 1 end else k = k + 2 print (i,j,k,l) if R then l = l + 4 until S i = i + 6 until T
Example Fill in the use numbers --- Then repeat for other variables i1 = j = k = l = 1 repeat i3 = ϕ(i1,i2) if (p) then begin j = i3 if Q then l = 2 else l = 3 k = k + 1 end else k = k + 2 print (i3,j,k,l) if R then l = l + 4 until S i2 = i3 + 6 until T i = j = k = l = 1 repeat if (p) then begin j = i if Q then l = 2 else l = 3 k = k + 1 end else k = k + 2 print (i,j,k,l) if R then l = l + 4 until S i = i + 6 until T
Example i = j = k = l = 1 repeat if (p) then begin j = i if Q then l = 2 else l = 3 k = k + 1 end else k = k + 2 print (i,j,k,l) if R then l = l + 4 until S i = i + 6 until T i1 = j1 = k1 = l1 = 1 repeat i3 = f(i1,i2) j2 = f(j1,j4) k2 = f(k5,k1) l2 = f(l9,l1) if (p) then begin j3 = i2 if Q then l3 = 2 else l4 = 3 l5 = f(l3,l4) k3 = k2 + 1 end else k4 = k2 + 2 j4 = f(j3,j2) k5 = f(k3,k4) l6 = f(l2,l5) print (i3,j4,k5,l6) l7 = f(l9,l6) if R then l8 = l7 + 4 l9 = f(l7,l8) until S i2 = i3 + 6 until T
Example - CFG Entry 1 2 3 4 5 7 6 8 9 10 11 Exit 12 i = j = k = l = 1 repeat if (p) then begin j = i if Q then l = 2 else l = 3 k = k + 1 end else k = k + 2 print (i,j,k,l) if R then l = l + 4 until S i = i + 6 until T 3 4 5 7 6 8 9 10 11 Exit 12
Constructing SSA (Naively) Insert Φ-functions at every join for every name Solve Reaching Definitions Rename each use to the definition that reaches it
Constructing SSA (Naively) Why is the previous bad? Too many ϕ-functions! Can we do better?
Efficiently Constructing SSA Perform Control-flow analysis Insert ϕ-Functions Rename Values However – where do we put the ϕ-Functions?
Formalizing ϕ placement We need a Φ function at node Z if Two non-null CFG paths that both define v Such that both paths start at two distinct nodes and end at Z
Dominance Frontiers Illustration Dominated by X Dominance Frontier of X (Not Dominated by X)
Dominance Frontiers If z is the first node we encounter on the path from x which x does not strictly dominate, z is in the dominance frontier of x For this to happen, there is some path from node x to z, x … y z where (x SDOM y) but not (x SDOM z).
Example {1} {7} {6} {6} {1, 7} {7} ∅ DF(1) = DF(2) = DF(3) = DF(4) =
Computing Dominance Frontiers Two components to DF(X): DFlocal(X) = {Y∊ succ(X) | X> Y} Any child of X not (strictly) dominated by X is in DF(X) Let Z be such that idom(Z) = X idom(Z) is the parent of Z in the dominator tree DFup(Z) = {Y∊ DF(Z) | X>Y} Nodes from DF(Z) that are not strictly dominated by X are also in DF(X)
Algorithm Let SDOM(X) = {Y | X>Y} For each Z such that idom(Z) = X do DF(X) = DFlocal(X) ∪ (DF(Z) - SDOM(X)) I.e., DF(X) = DFlocal(X) ∪ DFup(Z)
SSA f-placement For each variable M in the program Set Worklist = DM, the set of CFG nodes that contain assignments to variable M. While items left in the Worklist remove some node X from the Worklist for all W in DF(X), if W has never been in M's Worklist, add a f-term at W. Place W into the Worklist.
CFG for example – Variable k Entry 1 2 i = j = k = l = 1 repeat if (p) then begin j = i if Q then l = 2 else l = 3 k = k + 1 end else k = k + 2 print (i,j,k,l) if R then l = l + 4 until S i = i + 6 until T 1 3 2 4 5 7 3 7 8 6 4 5 6 9 8 10 11 9 12 10 11 Exit 12
Worklist = {1,6,7} – location of k’s assignments 1 dominates the entire graph Worklist = {1,6,7} – location of k’s assignments Compute DF(1) = {2,3,4,5,6,7,8,9,10,11,12,Exit } – {2,3,4,5,6,7,8,9,10,11,12,Exit} = { } Remember that DF(x) = (SUCC(DOM-1(x)) – SDOM-1(x) where SUCC(x) is set of successors of x in the CFG) Entry 1 2 3 4 5 7 6 8 9 10 11 Exit 12
Compute DF(6) = {8} – {} = {8} put f in node 8 Worklist = {6,7} Compute DF(6) = {8} – {} = {8} put f in node 8 Remember that DF(x) = (SUCC(DOM-1(x)) – SDOM-1(x) where SUCC(x) is set of successors of x in the CFG) Entry 1 2 3 4 5 7 node 6 only dominates itself 6 8 f 9 10 11 Exit 12
Compute DF(7) = {8} – {} = {8} node 8 already in worklist Remember that DF(x) = (SUCC(DOM-1(x)) – SDOM-1(x) where SUCC(x) is set of successors of x in the CFG) Entry 1 2 3 4 5 7 node 7 only dominates itself 6 8 f 9 10 11 Exit 12
Compute DF(8) = {2,9,10,11,12, exit} – {9,10,11,12,exit} = {2} Worklist = {8} Compute DF(8) = {2,9,10,11,12, exit} – {9,10,11,12,exit} = {2} put f in node 2 Remember that DF(x) = (SUCC(DOM-1(x)) – SDOM-1(x) where SUCC(x) is set of successors of x in the CFG) Entry 1 2 f 3 4 5 7 node 8 dominates {8,9,10,11,12,exit} 6 8 f 9 10 11 Exit 12
Compute DF(2) = {2-12, exit} – {3-12,exit} = {2} Worklist = {2} Compute DF(2) = {2-12, exit} – {3-12,exit} = {2} Remember that DF(x) = (SUCC(DOM-1(x)) – SDOM-1(x) where SUCC(x) is set of successors of x in the CFG) Entry 1 2 f 3 4 5 7 node 2 dominates {2-12,exit} 6 8 f 9 10 11 Exit 12
CFG for example – Variable k Entry 1 k = 1 2 k = f(k,k) 3 i = j = k = l = 1 repeat if (p) then begin j = i if Q then l = 2 else l = 3 k = k + 1 end else k = k + 2 print (i,j,k,l) if R then l = l + 4 until S i = i + 6 until T 4 5 7 k = k + 2 6 k = k + 1 8 k = f(k,k) 9 10 11 12 Exit
Linking it all together Initially, for each variable V C(V) = 0 /* counter */ S(V) = Empty /* stack for each variable*/ Other important information: RHS(A) = set of variables used on right side of assignment LHS(A) = set of variables assigned to on left side WhichPred(X,Y) = j where Y is the jth predecessor of X in CFG Children(X) = children in the IDOM tree ‘Search(entry)’ will do renaming of all variables in program.
New assignment – update the counter and push Search (X: CFG node) for each statement A in X If A is an ordinary assignment statement For each v in RHS(A) replace the use of v with vi, where i = top(S(v)) For each v in LHS(A) i = C(v); replace v by vi push i on S(v); C(v)++ end For each Y in Succ(X) do J = WhichPred(X,Y) /* predecessors have unique # wrt successor */ For each f-function F in Y Replace j-th operand v in RHS(F) by vi where i = Top(S(v)) End For each Y in Children() call Search() end For each assignment A in X For each v in LHS(A) pop S(v) end top(S(v)) will hold the ‘current’ # for variable v New assignment – update the counter and push
Look at successors of this node in CFG Search (X: CFG node) for each statement A in X If A is an ordinary assignment statement For each v in RHS(A) replace the use of v with vi, where i = top(S(v)) For each v in LHS(A) i = C(v); replace v by vi push i on S(v); C(v)++ end For each Y in Succ(X) do j = WhichPred(X,Y) /* predecessors have unique # wrt successor */ For each f-function F in Y Replace j-th operand v in RHS(F) by vi where i = Top(S(v)) End For each Y in Children() call Search() end For each assignment A in X For each v in LHS(A) pop S(v) end Look at successors of this node in CFG Resolve any ϕ functions in successors
Look at all nodes dominated by X Search (X: CFG node) for each statement A in X If A is an ordinary assignment statement For each v in RHS(A) replace the use of v with vi, where i = top(S(v)) For each v in LHS(A) i = C(v); replace v by vi push i on S(v); C(v)++ end For each Y in Succ(X) do J = WhichPred(X,Y) /* predecessors have unique # wrt successor */ For each f-function F in Y Replace j-th operand v in RHS(F) by vi where i = Top(S(v)) End For each D in Children(X) call Search(D) end For each assignment A in X For each v in LHS(A) pop S(v) end Look at all nodes dominated by X
Pop the var # pushed earlier Search (X: CFG node) for each statement A in X If A is an ordinary assignment statement For each v in RHS(A) replace the use of v with vi, where i = top(S(v)) For each v in LHS(A) i = C(v); replace v by vi push i on S(v); C(v)++ end For each Y in Succ(X) do J = WhichPred(X,Y) /* predecessors have unique # wrt successor */ For each f-function F in Y Replace j-th operand v in RHS(F) by vi where i = Top(S(v)) End For each D in Children(X) call Search(D) end For each assignment A in X For each v in LHS(A) pop S(v) end Pop the var # pushed earlier
1 1 2 2 3 3 7 8 4 5 7 4 5 6 9 10 11 6 12 8 9 10 11 12
Just deal with k in this example Search(1) C(k) = 1 S(k) = {0} Children(1) = {2} k0 = 1 1 2 k = f(k0,k) 3 4 5 7 1 k = k + 2 6 2 k = k + 1 8 3 7 8 k = f(k,k) 9 4 5 6 9 10 10 11 12 11 Exit 12
Search(2) C(k) = 2 S(k) = {0,1} None of the successors have f functions Children(2) = {3,7,8} k0 = 1 1 2 k1 = f(k0,k) 3 4 5 7 1 k = k + 2 6 2 k = k + 1 8 3 7 8 k = f(k,k) 9 4 5 6 9 10 10 11 12 11 Exit 12
Search(3) C(k) = 2 S(k) = {0,1} Children(3) = {4,5,6} Search(4) Children(4) = {} Search(5) Children(5) = {} Search(6) C(k) = 3 S(k) = {0,1,2} Children(6) = {} Pop(S(k)) = {0,1} 1 k0 = 1 2 k1 = f(k0,k) 3 4 5 7 k = k + 2 6 1 k2 = k1 + 1 8 k = f(k2,k) 2 9 3 7 8 10 4 5 6 9 11 10 11 Exit 12 12
Search(7) C(k) = 4 S(k) = {0,1,3} Children(7) = { } Pop(S(k)) = {0,1} 1 k0 = 1 2 k1 = f(k0,k) 3 4 5 7 1 k3 = k1 + 2 6 2 k2 = k1 + 1 8 k = f(k2,k3) 3 7 8 9 4 5 6 9 10 10 11 11 12 Exit 12
Search(8) C(k) = 5 S(k) = {0,1,4} Children(8) = {9} Search(9) Children(9) = {10,11} Search(10) Search(11) 1 k0 = 1 2 k1 = f(k0,k) 3 4 5 7 k3 = k1 + 2 1 6 k2 = k1 + 1 2 8 k4 = f(k2,k3) 9 3 7 8 4 5 6 9 10 10 11 11 Exit 12 12
Search(12) C(k) = 5 S(k) = {0,1,4} 1 k0 = 1 2 k1 = f(k0,k4) 3 4 5 7 k3 = k1 + 2 1 6 2 k2 = k1 + 1 8 k4 = f(k2,k3) 3 7 8 9 4 5 6 9 10 10 11 11 12 Exit 12
i = j = k1 = l = 1 Repeat k2 = f(k1,k5) if (p) then begin j = i if Q then l = 2 else l = 3 k3 = k2 + 1 end else k4 = k2 + 2 k5 = f(k3,k4) print (i,j,k5,l) repeat if R then l = l + 4 until S i = i + 6 until T i = j = k = l = 1 Repeat if (p) then begin j = i if Q then l = 2 else l = 3 k = k + 1 end else k = k + 2 print (i,j,k,l) repeat if R then l = l + 4 until S i = i + 6 until T
Consider L i = j = k = l = 1 repeat if (p) then begin j = i Entry 1 l = 2 3 i = j = k = l = 1 repeat if (p) then begin j = i if Q then l = 2 else l = 3 k = k + 1 end else k = k + 2 print (i,j,k,l) if R then l = l + 4 until S i = i + 6 until T 4 5 7 l = l = 6 8 print l 9 10 l = l + 11 Exit 12
Computing the DF i = j = k = l = 1 repeat if (p) then begin j = i Entry 1 l = 2 l = f 3 i = j = k = l = 1 repeat if (p) then begin j = i if Q then l = 2 else l = 3 k = k + 1 end else k = k + 2 print (i,j,k,l) if R then l = l + 4 until S i = i + 6 until T 1 2 4 5 7 l = l = 3 7 8 6 l = f l = f 4 5 6 9 8 print l 10 11 9 l = f 10 12 l = l + l = f 11 Exit 12
i = j = k = l = 1 repeat l = f(l,l) if (p) then begin j = i if Q then l = 2 else l = 3 k = k + 1 end else k = k + 2 print (i,j,k,l) if R then l = l + 4 until S i = i + 6 until T i = j = k = l = 1 repeat if (p) then begin j = i if Q then l = 2 else l = 3 k = k + 1 end else k = k + 2 print (i,j,k,l) if R then l = l + 4 until S i = i + 6 until T
Adding the numbers: search(1) Entry 1 l1 = 2 l = f(l1) 3 i = j = k = l = 1 repeat if (p) then begin j = i if Q then l = 2 else l = 3 k = k + 1 end else k = k + 2 print (i,j,k,l) if R then l = l + 4 until S i = i + 6 until T 1 2 4 5 7 l = l = 3 7 8 6 l = f l = f 4 5 6 9 8 print l 10 11 9 l = f 10 12 l = l + l = f 11 Exit 12
Adding the numbers: search(2) Entry 1 l1 = 2 l2 = f(l1) 3 i = j = k = l = 1 repeat if (p) then begin j = i if Q then l = 2 else l = 3 k = k + 1 end else k = k + 2 print (i,j,k,l) if R then l = l + 4 until S i = i + 6 until T 1 2 4 5 7 l = l = 3 7 8 6 l = f l = f 4 5 6 9 8 print l 10 11 9 l = f 10 12 l = l + l = f 11 Exit 12
Adding the numbers: search(3) Entry 1 l1 = 2 l2 = f(l1) 3 i = j = k = l = 1 repeat if (p) then begin j = i if Q then l = 2 else l = 3 k = k + 1 end else k = k + 2 print (i,j,k,l) if R then l = l + 4 until S i = i + 6 until T 1 2 4 5 7 l = l = 3 7 8 6 l = f l = f 4 5 6 9 8 print l 10 11 9 l = f 10 12 l = l + l = f 11 Exit 12
Adding the numbers: search(4) Entry 1 l1 = 2 l2 = f(l1) 3 i = j = k = l = 1 repeat if (p) then begin j = i if Q then l = 2 else l = 3 k = k + 1 end else k = k + 2 print (i,j,k,l) if R then l = l + 4 until S i = i + 6 until T 1 2 4 5 7 l = l3 = 3 7 8 6 l = f(l3) l = f 4 5 6 9 8 print l 10 11 9 l = f 10 12 l = l + l = f 11 Exit 12
Adding the numbers: search(5) Entry 1 l1 = 2 l2 = f(l1) 3 i = j = k = l = 1 repeat if (p) then begin j = i if Q then l = 2 else l = 3 k = k + 1 end else k = k + 2 print (i,j,k,l) if R then l = l + 4 until S i = i + 6 until T 1 2 4 5 7 l4 = l3 = 3 7 8 6 l = f(l3,l4) l = f 4 5 6 9 8 print l 10 11 9 l = f 10 12 l = l + l = f 11 Exit 12
Adding the numbers: search(6) Entry 1 l1 = 2 l2 = f(l1) 3 i = j = k = l = 1 repeat if (p) then begin j = i if Q then l = 2 else l = 3 k = k + 1 end else k = k + 2 print (i,j,k,l) if R then l = l + 4 until S i = i + 6 until T 1 2 4 5 7 l4 = l3 = 3 7 8 6 l5 = f(l3,l4) l = f(l5 4 5 6 9 8 print l 10 11 9 l = f 10 12 l = l + l = f 11 Exit 12
Adding the numbers: search(7) Entry 1 l1 = 2 l2 = f(l1) 3 i = j = k = l = 1 repeat if (p) then begin j = i if Q then l = 2 else l = 3 k = k + 1 end else k = k + 2 print (i,j,k,l) if R then l = l + 4 until S i = i + 6 until T 1 2 4 5 7 l4 = l3 = 3 7 8 6 l5 = f(l3,l4) l = f(l5,l2) 4 5 6 9 8 print l 10 11 9 l = f 10 12 l = l + l = f 11 Exit 12
Adding the numbers: search(8) Entry 1 l1 = 2 l2 = f(l1) 3 i = j = k = l = 1 repeat if (p) then begin j = i if Q then l = 2 else l = 3 k = k + 1 end else k = k + 2 print (i,j,k,l) if R then l = l + 4 until S i = i + 6 until T 1 2 4 5 7 l4 = l3 = 3 7 8 6 l5 = f(l3,l4) l6 = f(l5,l2) 4 5 6 9 8 print l6 10 11 9 l = f(l6) 10 12 l = l + l = f 11 Exit 12
Adding the numbers: search(9) Entry 1 l1 = 2 l2 = f(l1) 3 i = j = k = l = 1 repeat if (p) then begin j = i if Q then l = 2 else l = 3 k = k + 1 end else k = k + 2 print (i,j,k,l) if R then l = l + 4 until S i = i + 6 until T 1 2 4 5 7 l4 = l3 = 3 7 8 6 l5 = f(l3,l4) l6 = f(l5,l2) 4 5 6 9 8 print l6 10 11 9 l7 = f(l6) 10 12 l = l + l = f(l7) 11 Exit 12
Adding the numbers: search(10) Entry 1 l1 = 2 l2 = f(l1) 3 i = j = k = l = 1 repeat if (p) then begin j = i if Q then l = 2 else l = 3 k = k + 1 end else k = k + 2 print (i,j,k,l) if R then l = l + 4 until S i = i + 6 until T 1 2 4 5 7 l4 = l3 = 3 7 8 6 l5 = f(l3,l4) l6 = f(l5,l2) 4 5 6 9 8 print l6 10 11 9 l7 = f(l6) 10 12 l8 = l7 + l = f(l7,l8) 11 Exit 12
Adding the numbers: search(11) Entry 1 l1 = 2 l2 = f(l1) 3 i = j = k = l = 1 repeat if (p) then begin j = i if Q then l = 2 else l = 3 k = k + 1 end else k = k + 2 print (i,j,k,l) if R then l = l + 4 until S i = i + 6 until T 1 2 4 5 7 l4 = l3 = 3 7 8 6 l5 = f(l3,l4) l6 = f(l5,l2) 4 5 6 9 8 print l6 10 11 9 l7 = f(l6,l9) 10 12 l8 = l7 + l9 = f(l7,l8) 11 Exit 12
Adding the numbers: search(12) Entry 1 l1 = l2 = f(l1,l9) 2 3 i = j = k = l = 1 repeat if (p) then begin j = i if Q then l = 2 else l = 3 k = k + 1 end else k = k + 2 print (i,j,k,l) if R then l = l + 4 until S i = i + 6 until T 1 2 4 5 7 l4 = l3 = 3 7 8 6 l5 = f(l3,l4) l6 = f(l5,l2) 4 5 6 9 8 print l6 10 11 9 l7 = f(l6,l9) 10 12 l8 = l7 + l9 = f(l7,l8) 11 Exit 12
i = j = k = l1 = 1 repeat l2 = f(l1,l9) if (p) then begin j = i if Q then l3 = 2 else l4 = 3 l5 = f(l3,l4) k = k + 1 end else k = k + 2 l6 = f(l5,l2) print (i,j,k,l6) l7 = f(l6,l9) if R then l8 = l7 + 4 l9 = f(l7,l8) until S i = i + 6 until T i = j = k = l = 1 repeat if (p) then begin j = i if Q then l = 2 else l = 3 k = k + 1 end else k = k + 2 print (i,j,k,l) if R then l = l + 4 until S i = i + 6 until T
SSA Deconstruction At some point, we need executable code X17 Ø(x10,x11) ... x17 ... At some point, we need executable code Few machines implement ϕ operations Need to fix up the flow of values Basic idea Insert copies ϕ-function pred’s Simple algorithm Works in most cases Adds lots of copies Most of them coalesce away ... x17 X17 x10 X17 x11 *
i = j = k0 = l = 1 k1 = k0 repeat if (p) then begin j = i if Q then l = 2 else l = 3 k2 = k2 + 1 k4 = k2 end else k3 = k1 + 2 k4 = k3 print (i,j,k4,l) if R then l = l + 4 until S i = i + 6 k1 = k4 until T 1 k0 = 1 k1 = k0 2 k1 = f(k0,k4) 3 4 5 7 k3 = k1 + 2 k4 = k3 6 k2 = k1 + 1 k4 = k2 8 k4 = f(k2,k3) 9 10 11 Exit 12 k1 = k4