Download presentation
Presentation is loading. Please wait.
Published byChrystal Sparks Modified over 9 years ago
1
Compiler Principles Fall 2014-2015 Compiler Principles Lecture 12: Register Allocation Roman Manevich Ben-Gurion University
2
Syllabus Front End Scanning Top-down Parsing (LL) Bottom-up Parsing (LR) Intermediate Representation Lowering Optimizations Local Optimizations Dataflow Analysis Loop Optimizations Code Generation Register Allocation 2 mid-termexam
3
Previously Dataflow framework – Conditions for termination Finite lattice height Monotone transfer functions – Loop optimizations 3
4
agenda The need for register allocation Global register allocation 4
5
5 Register allocation motivation
6
Registers Most machines have a set of registers, dedicated memory locations that – can be accessed quickly, – can have computations performed on them, and – exist in small quantity Using registers intelligently is a critical step in any compiler – A good register allocator can generate code orders of magnitude better than a bad register allocator 6
7
Register allocation In TAC, there are an unlimited number of variables On a physical machine there are a small number of registers: – x86 has four general-purpose registers and a number of specialized registers – MIPS has twenty-four general-purpose registers and eight special-purpose registers Register allocation is the process of assigning variables to registers and managing data transfer in and out of registers 7
8
Challenges in register allocation Registers are scarce – Often substantially more IR variables than registers – Need to find a way to reuse registers whenever possible Registers are complicated – x86: Each register made of several smaller registers; can't use a register and its constituent registers at the same time – x86: Certain instructions must store their results in specific registers; can't store values there if you want to use those instructions – MIPS: Some registers reserved for the assembler or operating system – Most architectures: Some registers must be preserved across function calls 8
9
9 naive register allocation
10
Simple approach Problem: program execution very inefficient – moving data back and forth between memory and registers 10 x = y + z mov 16(%ebp), %eax mov 20(%ebp), %ebx add %ebx, %eax mov %eax, 24(%ebx) Straightforward solution: Allocate each variable in activation record At each instruction: bring values needed into registers (rematerialization), perform operation, then store result to memory
11
11 Reusing registers
12
Find a register allocation 12 b = a + 2 c = b * b b = c + 1 return b * a eax ebx register variable ?a ?b ?c
13
Is this a valid allocation? eax ebx register 13 b = a + 2 c = b * b b = c + 1 return b * a registervariable eaxa ebxb eaxc ebx = eax + 2 eax = ebx * ebx ebx = eax + 1 return ebx * eax Overwrites previous value of ‘a’ also stored in eax
14
Is this a valid allocation? eax ebx register 14 b = a + 2 c = b * b b = c + 1 return b * a registervariable ebxa eaxb c eax = ebx + 2 eax = eax * eax eax = eax + 1 return eax * ebx Value of ‘c’ stored in eax is not needed anymore so reuse it for ‘b’
15
15 Register interference graph
16
Main idea For every node n in CFG, we have out[n] – Set of temporaries live out of n Two variables interfere if they appear in the same out[n] of any node n – Cannot be allocated to the same register Conversely, if two variables do not interfere with each other, they can be assigned the same register – We say they have disjoint live ranges How to assign registers to variables? 16
17
Interference graph Nodes of the graph = variables Edges connect variables that interfere with one another Nodes will be assigned a color corresponding to the register assigned to the variable Two colors can’t be next to one another in the graph 17
18
Liveness analysis b = a + 2 c = b * b b = c + 1 return b * a 18
19
Liveness analysis b = a + 2 c = b * b b = c + 1 {b, a} return b * a 19
20
Liveness analysis b = a + 2 c = b * b {a, c} b = c + 1 {b, a} return b * a 20
21
Liveness analysis b = a + 2 {b, a} c = b * b {a, c} b = c + 1 {b, a} return b * a 21
22
Liveness analysis {a} b = a + 2 {b, a} c = b * b {a, c} b = c + 1 {b, a} return b * a 22
23
Interference graph a cb eax ebx color register 23 {a} b = a + 2 {b, a} c = b * b {a, c} b = c + 1 {b, a} return b * a
24
Colored graph a cb eax ebx color register 24 {a} b = a + 2 {b, a} c = b * b {a, c} b = c + 1 {b, a} return b * a
25
25
26
26
27
27 Graph coloring
28
This problem is equivalent to graph-coloring, which is NP-hard if there are at least three registers No good polynomial-time algorithms (or even good approximations!) are known for this problem We have to be content with a heuristic that is good enough for RIGs that arise in practice (or do we….?) 28
29
Coloring by simplification [Kempe 1879] How to find a K-coloring of a graph Intuition: – Suppose we are trying to K-color a graph and find a node with fewer than K edges – If we delete this node from the graph and color what remains, we can find a color for this node if we add it back in – Reason: fewer than K neighbors some color must be left over 29
30
Coloring by simplification [Kempe 1879] How to find a K-coloring of a graph Phase 1: Simplify – Repeatedly simplify graph – When a variable (i.e., graph node) is removed, push it on a stack Phase 2: Select – Unwind stack and reconstruct the graph as follows: Pop variable from the stack Add it back to the graph Color the node for that variable with a color that it doesn’t interfere with 30 simplify select
31
31 Coloring example
32
Coloring for K=2 b ed a c stack: eax ebx color register 32
33
Coloring for K=2 b ed a stack: c c eax ebx color register 33
34
Coloring for K=2 b ed a stack: e c c eax ebx color register 34
35
Coloring for K=2 b ed a stack: a e c c eax ebx color register 35
36
Coloring for K=2 b ed a stack: b a e c c eax ebx color register 36
37
Coloring for K=2 b ed a stack: d b a e c c eax ebx color register 37
38
Coloring for K=2 b ed eax ebx color register a stack: b a e c c 38
39
Coloring for K=2 b e a stack: a e c c eax ebx color register d 39
40
Coloring for K=2 e a stack: e c c eax ebx color register b d 40
41
Coloring for K=2 e stack: c c eax ebx color register a b d 41
42
Coloring for K=2 stack: c eax ebx color register e a b d 42
43
43 spilling
44
Failure of heuristic If the graph cannot be colored, it will eventually be simplified to graph in which every node has at least K neighbors Sometimes, the graph is still K-colorable! Finding a K-coloring in all situations is an NP-complete problem – We will have to approximate to make register allocators fast enough 44
45
Coloring for K=2 stack: c eax ebx color register e a b d 45
46
Coloring for K=2 c eax ebx color register e a b d stack: c b e a d Some graphs can’t be colored in K colors: 46
47
Coloring for K=2 c eax ebx color register e a b d Some graphs can’t be colored in K colors: stack: b e a d 47
48
Coloring for K=2 c eax ebx color register e a b d Some graphs can’t be colored in K colors: stack: e a d 48
49
Coloring for K=2 c eax ebx color register e a b d Some graphs can’t be colored in K colors: stack: e a d no colors left for e! What can we do? 49
50
Chaitin’s algorithm [CC’82] Choose and remove an arbitrary node, marking it “troublesome” – Use heuristics to choose which one: – When adding node back in, it may be possible to find a valid color – Otherwise, we have to spill that node 50 ?
51
Chaitin’s algorithm [CC’82] Choose and remove an arbitrary node, marking it “troublesome” – Use heuristics to choose which one: – When adding node back in, it may be possible to find a valid color – Otherwise, we have to spill that node (lowest priority) 51 spill priority = (uo + 10 ui) / deg uo = #use+defs outside of loop ui = #use+defs inside of loop
52
Spilling Phase 3: Spill – once all nodes have K or more neighbors, pick a node for spilling There are many heuristics that can be used to pick a node Try to pick node not used much, not in inner loop Assign its storage to activation record – Remove it from graph and mark it as potential spill (technically, push on a spill stack) We can now repeat phases 1-2 without this node 52
53
Chaitin’s algorithm [CC’82] Phase 1: Simplify Phase 2: Select – Unwind stack and reconstruct the graph as follows: Pop (non-spill) variable from the stack Add it back to the graph Color the node for that variable with a color that it doesn’t interfere with its neighbors – Unwind spill stack Pop spill variable If there is an available color add back to graph Otherwise mark variable as actual spill Phase 3: Spill – If all nodes have K or more neighbors, pick a “heavy” node for spilling and add to potential spill stack Phase 4: Rewrite – Rewrite code for actual spill variables – Recompute liveness information – Repeat phases 1-3 53
54
Chaitin’s algorithm [CC’82] 54 Simplify Mark potential spills Select colors and detect actual spills Rewrite code to implement actual spills Liveness analysis any actual spill done any potential spill done
55
Spill example (for K=2) c eax ebx color register e a b d stack: e a d no colors left for e! 55
56
Spill example (for K=2) c eax ebx color register e a b d stack: b e a d 56
57
Spill example (for K=2) c eax ebx color register e a b d stack: e a d 57
58
Spill example (for K=2) c eax ebx color register e a b d stack: a d 58
59
Spill example (for K=2) c eax ebx color register e a b d stack: d 59
60
Spill example (for K=2) c eax ebx color register e a b d stack: 60
61
61 Register constraints
62
Handling precolored nodes Some variables are pre-assigned to registers – e.g.: mul on x86/pentium Uses eax; defines eax, edx – e.g.: call on x86/pentium Defines (trashes) caller-save registers eax, ecx, edx To properly allocate registers, treat these register uses as special temporary variables and enter into interference graph as precolored nodes 62
63
Handling precolored nodes Simplify. Never remove a pre-colored node – it already has a color, i.e., it is a given register Select. Once simplified graph has all colored nodes, add other nodes back in and color them using precolored nodes as starting point 63
64
64 Optimizing moves
65
Optimizing move instructions Code generation produces a lot of extra MOVE instructions MOVE t5, t9 If we can assign t5 and t9 to same register, we can get rid of the MOVE– effectively, copy propagation at the register allocation level Idea: if t5 and t9 are not connected in inference graph, coalesce them into a single variable; the move will be redundant 65
66
RIG with MOVE edges Add a second type of edges – MOVE edges 66 b ed a c eax ebx color register
67
Coalescing Problem: coalescing nodes can make a graph un-colorable – Conservative coalescing heuristic What should we do ? 67 aba/b coalesce MOVE
68
Conservative coalescing Coalesce MOVE edge (a,b) if it does not affect colorability A node is heavy if its degree is ≥K and light otherwise Briggs criterion: coalesce only if the merged node ab has <K nodes heavy nodes Reason: – Simplify will first remove all light neighbors – ab will then be adjacent to <K neighbors – Simplify can remove ab 68
69
Conservative coalescing Coalesce MOVE edge (a,b) if it does not affect colorability A node is heavy if its degree is ≥K and light otherwise George criterion: coalesce only if all heavy neighbors of a are also neighbors of b Reason: – Simplify can remove all light neighbors of a – Remaining heavy neighbors of a are neighbors of b so coalescing does not increase the degree of any node 69
70
Coalescing criterion example c eax ebx color register e a b 70 Can we coalesce (a,e) ? By the Briggs criterion? – #(heavy-neighbors(a,e) < K By the George criterion? – All heavy neighbors of a are also neighbors of e
71
Coalescing criterion example c eax ebx color register e a b 71 Can we coalesce (a,e) ? By the Briggs criterion? NO – #(heavy-neighbors(a,e) < K By the George criterion? YES – All heavy neighbors of a are also neighbors of e
72
Simplify, coalesce and freeze Phase 1: Simplify – Step 1 (simplify): simplify as much as possible without removing nodes that are the source or destination of a move (MOVE-related nodes) – Step 2 (coalesce): coalesce a MOVE-related edge provided low-degree node results – Step 3 (freeze): if neither steps 1 or 2 apply, freeze a MOVE instruction: low-degree nodes involved are marked not MOVE-related (remove MOVE edge) and try step 1 again – Step 4 (spill): if all nodes are heavy select a candidate for spilling using a priority function and move to potential spill stack Phase 2: Select – Unwind stack and reconstruct the graph as follows: Pop variable from the stack Add it back to the graph Color the node node with a color that it doesn’t interfere with – Unwind potential spill stack and attempt to color node – if unable mark corresponding variable as actual spill Phase 4: Rewrite – Allocate position in frame for spilled variable v – On each usage of v load to v i from frame 72
73
Simplify, coalesce and freeze 73 Simplify: recursively remove non-MOVE nodes with <K neighbors, pushing them onto stack Coalesce: conservatively merge unconstrained MOVE-related nodes with <K “heavy” neighbors Freeze: give up coalescing on some low-degree MOVE-related node any coalesce done any freeze done any simplify done
74
Overall algorithm 74 Simplify, freeze and coalesce Simplify, freeze and coalesce Mark potential spills Select colors and detect actual spills Rewrite code to implement actual spills Liveness analysis any actual spill done any potential spill done
75
Recent advances [CC 2013] 75
76
76 Linear scan register allocation
77
Live ranges and live intervals The live range for a variable is the set of program points at which the variable is alive The live interval for a variable is the smallest sub-range of the IR code containing all of a variable’s live ranges – A property of the IR code, not the CFG – Less precise than live ranges, but simpler to work with 77
78
d Live ranges and live intervals 78 e := d + a f := b + c f := f + b IfZ e Goto _L0 d := e + f d := e - f Goto _L1; _L0: d := e-f _L1: g = d abc e fg
79
Register allocation with live ranges Given the live intervals for all the variables in the program, we can allocate registers using a simple greedy algorithm Idea: Track which registers are free at each point When a live interval begins, give that variable a free register When a live interval ends, the register is once again free We can't always fit everything into a register (spill) 79 dabc e fg
80
Example 80 R0R0 R1R1 R2R2 R3R3 dabc e fg Free registers
81
Example 81 R0R0 R1R1 R2R2 R3R3 dabc e fg Free registers
82
Example 82 R0R0 R1R1 R2R2 R3R3 dabc e fg Free registers
83
Example 83 R0R0 R1R1 R2R2 R3R3 dabc e fg Free registers
84
Example 84 R0R0 R1R1 R2R2 R3R3 dabc e fg Free registers
85
Example 85 R0R0 R1R1 R2R2 R3R3 dabc e fg Free registers
86
Example 86 R0R0 R1R1 R2R2 R3R3 dabc e fg Free registers
87
Example 87 R0R0 R1R1 R2R2 R3R3 dabc e fg Free registers
88
Example 88 R0R0 R1R1 R2R2 R3R3 dabc e fg Free registers
89
Example 89 dabc e fg Free registers R0R0 R1R1 R2R2 R3R3
90
Example 90 dabc e fg Free registers R0R0 R1R1 R2R2 R3R3
91
Example 91 dabc e fg Free registers R0R0 R1R1 R2R2 R3R3
92
Another example 92 R0R0 R1R1 R2R2 dabc e fg Free registers
93
Another example 93 R0R0 R1R1 R2R2 dabc e fg Free registers
94
Another example 94 R0R0 R1R1 R2R2 dabc e fg Free registers
95
Another example 95 R0R0 R1R1 R2R2 dabc e fg Free registers
96
Another example 96 R0R0 R1R1 R2R2 dabc e fg Free registers Which register should we use?
97
Another example 97 R0R0 R1R1 R2R2 dabc e fg Free registers Which variable should we spill? One with longer interval
98
Another example 98 R0R0 R1R1 R2R2 dabc e fg Free registers
99
Another example 99 R0R0 R1R1 R2R2 dabc e fg Free registers
100
Another example 100 R0R0 R1R1 R2R2 dabc e fg Free registers
101
Another example 101 R0R0 R1R1 R2R2 dabc e fg Free registers
102
Another example 102 R0R0 R1R1 R2R2 dabc e fg Free registers
103
Another example 103 R0R0 R1R1 R2R2 dabc e fg Free registers
104
Another example 104 R0R0 R1R1 R2R2 dabc e fg Free registers
105
Another example 105 R0R0 R1R1 R2R2 dabc e fg Free registers
106
Another example 106 R0R0 R1R1 R2R2 dabc e fg Free registers
107
Linear scan register allocation A comparatively new algorithm (Polleto and Sarkar) Advantages: – Very efficient (after computing live intervals, runs in linear time) – Produces good code in many instances – Allocation step works in one pass; can generate code during iteration – Often used in JIT compilers like Java HotSpot Disadvantage – Imprecise due to use of live intervals rather than live ranges 107
108
Comparison to RA by coloring 108
109
RA recap Naïve allocation – per statement (Sethi-Ullman) – Done during lowering Graph-coloring Linear scan 109
110
Next lecture: Summary 110
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.