340 likes | 490 Views
Factored Use-Def Chains and Static Single Assignment Forms. Addresses use-def difficulty with optimization: Multiple defs of the same register Which def reaches use? Is RHS expression available? FUD/SSA forms: Each def of a variable is given a unique name
E N D
Factored Use-Def Chains and Static Single Assignment Forms • Addresses use-def difficulty with optimization: • Multiple defs of the same register • Which def reaches use? • Is RHS expression available? • FUD/SSA forms: • Each def of a variable is given a unique name • All uses reached by that assignment are renamed • DU chains become obvious • FUD chains and SSA forms are similar r2 = r2 + r3r6 = r4 - r5 r4 = 4r6 = 8 r6 = r2 + r6r7 = r4
Reaching Defs • Keeping all reaching defs for each use is not space efficient • FUD properties: • Each use of a var is reached by a single def • Insert pseudo assignments with nodes where multiple defs meet r23 = r21?+r32?r67 = r45?-r56? r48 = 4r69 = 8 r612 = r2103+r6117,9r714 = r413?,8 r6117,9 use defs
Converting to FUD Form r23 = r21?+r32?r67 = r45?-r56? r23 = r21?+r32?r67 = r45?-r56? r48 = 4r69 = 8 r48 = 4r69 = 8 r612 = r2103+r6117,9r714 = r413?,8 (r4)10?,8(r6)117,9r614 = r2123+r61311r716 = r41510
Converting to SSA Form r2 = r2 + r3r6 = r4 - r5 r22 = r21 + r31r61 = r41 - r51 r4 = 4r6 = 8 r42 = 4r62 = 8 r6 = r2 + r6r7 = r4 r43 = (r41,r42)r63 = (r61,r62)r64 = r22 + r63r71 = r43
Converting Loops to SSA Form r1 = 0 r11 = 0 r1 = r1 + 1… r12 = (r11,r13)r13 = r12 + 1…
FUD/SSA Pros and Cons • Pro • Trivial to find what defs reach a use: each use has exactly one def • Explicit merging of values at nodes • Simplifies optimizations that need use-def info • Cons • When transforming code, must either recompute (slow) or incrementally update (tedious)
Phi Nodes • A node merges two reaching definitions for a variable (or register) V • A node for V is required when two non-empty paths XZ and YZ converge at node Z, and nodes X and Y contain assignments to V • More precisely: • Z is a node with two distinct predecessors Y1 and Y2 • p1 : X1*Y1 and p2 : X2*Y2 are two paths in the CFG • p1 and p2 have no nodes in common • And there are no defs of V along either p1 or p2 (except at X1 and X2)
FUD/SSA Construction • Naïve algorithm • Insert nodes at every join for every variable • Solve reaching definitions • Rename each use to the def that reaches it • Problem: too many nodes • Precision • Space • Time
FUD Construction • Step 1: -term placement using an algorithm that similar to SSA insertion, but for FUD we also add a slicing edge • Step 2: FUD chaining connects each variable use with its unique reaching definition, similar to SSA variable renaming
SSA Construction • Step 1: Insert nodes • Step 2: Rename variables
Phi Node Insertion Algorithm • Compute dominance frontiers • Find global names: • Global if name is live on entry to some block • For each name build a list of blocks that define it • Insert nodes (-term placement): • For each global name N For each basic block B in which N is defined For each basic block D in B’s dominance frontier insert a node for N in D add N to the list of defining basic blocks
Dominance Frontiers • The dominance frontier of a node X is the set of nodesZ = DF(X) such that:If there are two predecessors Y1 and Y2 of Z and X dominates Y1 but not Y2 • A node dominates itself • A node Xdominates a node Y if every path from entry to Y goes through X
Computing Dominance Frontiers • Algorithm • Compute dominator tree • For each join point X in the CFG For each predecessor of X in the CFG go up to the immediate dominator D of X in the dominator tree, adding X to DF(Y) for each Y up to D (excluding X and D)
Computing Dominance Frontiers (Example Dom. Tree) BB0 BB0 BB1 BB1 BB2 BB3 BB2 BB3 BB7 BB4 BB5 BB4 BB5 BB6 Dominator tree BB6 BB7
Computing Dominance Frontiers (Example 1) BB0 BB0 BB1 BB1 BB2 BB3 BB7 BB2 BB3 BB4 BB5 BB6 BB4 BB5 BB6 For each join point X in the CFG For each predecessor of X in the CFG go up to the immediate dominator D of X in the dominator tree, adding X to DF(Y) for each Y up to D (excluding X and D) Dominatorfrontiers BB7
Computing Dominance Frontiers (Example 2) BB0 BB0 BB1 D = BB1 BB2 BB3 BB7 Y = BB2 BB3 BB4 BB5 BB6 BB4 BB5 BB6 For each join point X in the CFG For each predecessor of X in the CFG go up to the immediate dominator D of X in the dominator tree, adding X to DF(Y) for each Y up to D (excluding X and D) Dominatorfrontiers X = BB7
Computing Dominance Frontiers (Example 3) BB0 BB0 BB1 D = BB1 BB2 BB3 BB7 BB2 Y = BB3 BB4 BB5 BB6 BB4 BB5 Y = BB6 For each join point X in the CFG For each predecessor of X in the CFG go up to the immediate dominator D of X in the dominator tree, adding X to DF(Y) for each Y up to D (excluding X and D) Dominatorfrontiers X = BB7
Computing Dominance Frontiers (Example 4) BB0 BB0 BB1 BB1 BB2 BB3 BB7 BB2 D = BB3 BB4 BB5 BB6 Y = BB4 BB5 X = BB6 For each join point X in the CFG For each predecessor of X in the CFG go up to the immediate dominator D of X in the dominator tree, adding X to DF(Y) for each Y up to D (excluding X and D) Dominatorfrontiers BB7
Computing Dominance Frontiers (Example 5) BB0 D = BB0 BB1 X = BB1 BB2 BB3 BB7 BB2 BB3 BB4 BB5 BB6 BB4 BB5 BB6 For each join point X in the CFG For each predecessor of X in the CFG go up to the immediate dominator D of X in the dominator tree, adding X to DF(Y) for each Y up to D (excluding X and D) Dominatorfrontiers Y = BB7
Phi Node Insertion Algorithm • Compute dominance frontiers • Find global names: • Global if name is live on entry to some block • For each name build a list of blocks that define it • Insert nodes: • For each global name N For each basic block B in which N is defined For each basic block D in B’s dominance frontier insert a node for N in D add N to the list of defining basic blocks
Phi Node Insertion a is defined in 0, 1, 3: add in 7then a is defined in 7: add in 1b is defined in 0, 2, 6: add in 7then b is defined in 7: add in 1c is defined in 0, 1, 2, 5: add in 6, 7then c is defined in 6, 7: add in 1d is defined in 2, 3, 4: add in 6, 7then d is defined in 6, 7: add in 1i is defined in 7: add in 1 BB0 a = b =c =i = a = (a,a) b = (b,b) c = (c,c) d = (d,d) i = (i,i) a = c = BB1 BB2 BB3 b =c = d = a = d = BB4 BB5 d = c = a = (a,a) b = (b,b) c = (c,c) d = (d,d) c = (c,c) d = (d,d) BB6 b = For each global name N For each basic block B in which N is defined For each basic block D in B’s dominance frontier insert a node for N in D add N to the list of defining basic blocks BB7 i =
SSA Construction • Step 1: Insert nodes • Step 2: Rename variables
Rename Variables • Algorithm (outline) • Use an array of stacks, one per global variable V • For each basic block B in a preorder traversal of the dominator tree: • Generate unique names for each node • Rewrite each operation in the basic block: for uses of V: get current name from stack for defs of V: create and push new name • Fill in node parameters of successor blocks • Recurse on B’s children in the dominator tree • On exit from B: pop names generated in B from stacks
Renaming Variables:Initial State BB0 a = b =c =i = a = (a,a) b = (b,b) c = (c,c) d = (d,d) i = (i,i) a = c = BB1 BB2 BB3 b =c = d = a = d = BB0 BB4 BB5 d = c = BB1 a = (a,a) b = (b,b) c = (c,c) d = (d,d) c = (c,c) d = (d,d) BB2 BB3 BB7 BB6 b = BB4 BB5 BB6 BB7 i = Preorder traversalof dominator tree
Renaming Variables:After BB0 BB0 a0 = b0 =c0 =i0 = a = (a0,a) b = (b0,b) c = (c0,c) d = (d0,d) i = (i0,i) a = c = BB1 BB2 BB3 b =c = d = a = d = BB4 BB5 d = c = a = (a,a) b = (b,b) c = (c,c) d = (d,d) c = (c,c) d = (d,d) BB6 b = BB7 i =
Renaming Variables:After BB1 BB0 a0 = b0 =c0 =i0 = a1 = (a0,a) b1 = (b0,b) c1 = (c0,c) d1 = (d0,d) i1 = (i0,i) a2 = c2 = BB1 BB2 BB3 b =c = d = a = d = BB4 BB5 d = c = a = (a,a) b = (b,b) c = (c,c) d = (d,d) c = (c,c) d = (d,d) BB6 b = BB7 i =
Renaming Variables:After BB2 BB0 a0 = b0 =c0 =i0 = a1 = (a0,a) b1 = (b0,b) c1 = (c0,c) d1 = (d0,d) i1 = (i0,i) a2 = c2 = BB1 BB2 BB3 b2 =c3 = d2 = a = d = BB4 BB5 d = c = a = (a2,a) b = (b2,b) c = (c3,c) d = (d2,d) c = (c,c) d = (d,d) BB6 b = BB7 i =
Renaming Variables:Backtrack (Before BB3) BB0 a0 = b0 =c0 =i0 = a1 = (a0,a) b1 = (b0,b) c1 = (c0,c) d1 = (d0,d) i1 = (i0,i) a2 = c2 = BB1 BB2 BB3 b2 =c3 = d2 = a = d = BB4 BB5 d = c = a = (a2,a) b = (b2,b) c = (c3,c) d = (d2,d) c = (c,c) d = (d,d) BB6 b = BB7 i =
Renaming Variables:After BB3 BB0 a0 = b0 =c0 =i0 = a1 = (a0,a) b1 = (b0,b) c1 = (c0,c) d1 = (d0,d) i1 = (i0,i) a2 = c2 = BB1 BB2 BB3 b2 =c3 = d2 = a3 = d3 = BB4 BB5 d = c = a = (a2,a) b = (b2,b) c = (c3,c) d = (d2,d) c = (c,c) d = (d,d) BB6 b = BB7 i =
Renaming Variables:After BB4 BB0 a0 = b0 =c0 =i0 = a1 = (a0,a) b1 = (b0,b) c1 = (c0,c) d1 = (d0,d) i1 = (i0,i) a2 = c2 = BB1 BB2 BB3 b2 =c3 = d2 = a3 = d3 = BB4 BB5 d4 = c = a = (a2,a) b = (b2,b) c = (c3,c) d = (d2,d) c = (c2,c) d = (d4,d) BB6 b = BB7 i =
Renaming Variables:Backtrack to BB3 & After BB5 BB0 a0 = b0 =c0 =i0 = a1 = (a0,a) b1 = (b0,b) c1 = (c0,c) d1 = (d0,d) i1 = (i0,i) a2 = c2 = BB1 BB2 BB3 b2 =c3 = d2 = a3 = d3 = BB4 BB5 d4 = c4 = a = (a2,a) b = (b2,b) c = (c3,c) d = (d2,d) c = (c2,c4) d = (d4,d3) BB6 b = BB7 i =
Renaming Variables:Backtrack to BB3 & After BB6 BB0 a0 = b0 =c0 =i0 = a1 = (a0,a) b1 = (b0,b) c1 = (c0,c) d1 = (d0,d) i1 = (i0,i) a2 = c2 = BB1 BB2 BB3 b2 =c3 = d2 = a3 = d3 = BB4 BB5 d4 = c4 = a = (a2,a3) b = (b2,b3) c = (c3,c5) d = (d2,d5) c5 = (c2,c4) d5 = (d4,d3) BB6 b3 = BB7 i =
Renaming Variables:Backtrack to BB1 & After BB7 BB0 a0 = b0 =c0 =i0 = a1 = (a0,a2) b1 = (b0,b4) c1 = (c0,c6) d1 = (d0,d6) i1 = (i0,i2) a2 = c2 = BB1 BB2 BB3 b2 =c3 = d2 = a3 = d3 = BB4 BB5 d4 = c4 = a4 = (a2,a3) b4 = (b2,b3) c6 = (c3,c5) d6 = (d2,d5) c5 = (c2,c4) d5 = (d4,d3) BB6 b3 = BB7 i2 =
Homework:Convert to SSA Form • Tasks: • Compute dominator tree • Compute dominance frontiers • Find global names • Insert nodes • Rename variables BB0 a = b = BB1 BB2 BB3 c = b = a = BB4 b = BB5 a = c =