CMPUT 680 Fall 2003 Topic 7 Register Allocation

  • Slides: 76
Download presentation
CMPUT 680 - Fall 2003 Topic 7: Register Allocation and Instruction Scheduling José Nelson

CMPUT 680 - Fall 2003 Topic 7: Register Allocation and Instruction Scheduling José Nelson Amaral http: //www. cs. ualberta. ca/~amaral/courses/680 CMPUT 680 - Compiler Design and Optimization 1

Reading List z. Tiger book: chapter 10 and 11 z. Dragon book: chapter 10

Reading List z. Tiger book: chapter 10 and 11 z. Dragon book: chapter 10 z. Other papers as assigned in class or homeworks CMPUT 680 - Compiler Design and Optimization 2

Register Allocation z. Motivation z. Live ranges and interference graphs z. Problem formulation z.

Register Allocation z. Motivation z. Live ranges and interference graphs z. Problem formulation z. Solution methods CMPUT 680 - Compiler Design and Optimization 3

Goals of Optimized Register Allocation z. To select variables that should be assigned to

Goals of Optimized Register Allocation z. To select variables that should be assigned to registers. z. Use the same register for multiple variables when it is legal, and profitable, to do so. CMPUT 680 - Compiler Design and Optimization 4

Liveness Intuitively a variable v is live if it holds a value that may

Liveness Intuitively a variable v is live if it holds a value that may be needed in the future. In other words, v is live at a point pi if: (i) v has been defined in a statement that precedes pi in any path, and (ii) v may be used by a statement sj, and there is a path from pi to sj. (iii) v is not killed between pi and sj. CMPUT 680 - Compiler Design and Optimization 5

Live Variables d: s 4 = s 1 - 4 A variable v is

Live Variables d: s 4 = s 1 - 4 A variable v is live between the point pi immediately after its definition and the point pj immediately after its last use. e: s 5 = s 1/2 f: s 6 = s 2 * s 3 The interval [pi, pj] is the live range of the variable v. s 1 a: s 1 = ld(x) s 2 b: s 2 = s 1 + 4 c: s 3 = s 1 8 g: s 7 = s 4 - s 5 h: s 8 = s 6 * s 7 Which variables have the longest live range in the example? Variables s 1 and s 2 have a live range of four statements. CMPUT 680 - Compiler Design and Optimization 6

Register Allocation a: s 1 = ld(x) b: s 2 = s 1 +

Register Allocation a: s 1 = ld(x) b: s 2 = s 1 + 4 c: s 3 = s 1 8 d: s 4 = s 1 - 4 e: s 5 = s 1/2 f: s 6 = s 2 * s 3 g: s 7 = s 4 - s 5 h: s 8 = s 6 * s 7 How can we find out what is the minimum number of registers required by this basic block to avoid spilling values to memory? We have to compute the live range of all variables and find the “fatest” statement. Which statements have the most variables live simultaneously? CMPUT 680 - Compiler Design and Optimization 7

Register Allocation s 1 a: s 1 = ld(x) s 2 b: s 2

Register Allocation s 1 a: s 1 = ld(x) s 2 b: s 2 = s 1 + 4 s 3 c: s 3 = s 1 8 d: s 4 = s 1 - 4 e: s 5 = s 1/2 f: s 6 = s 2 * s 3 g: s 7 = s 4 - s 5 h: s 8 = s 6 * s 7 At statement d variables s 1, s 2, s 3, and s 4 are live, and during statement e variables s 2, s 3, s 4, and s 5 are live. s 4 s 5 s 6 s 7 But we have to use some math: our choice is liveness analysis. CMPUT 680 - Compiler Design and Optimization 8

Live-in and Live-out s 1 a: s 1 = ld(x) s 2 b: s

Live-in and Live-out s 1 a: s 1 = ld(x) s 2 b: s 2 = s 1 + 4 s 3 c: s 3 = s 1 8 d: s 4 = s 1 - 4 e: s 5 = s 1/2 f: s 6 = s 2 * s 3 g: s 7 = s 4 - s 5 h: s 8 = s 6 * s 7 live-in(r): set of variables that are live at the point immediately before statement r. s 4 s 5 s 6 s 7 live-out(r): set of variables that are live at the point immediately after statement r. CMPUT 680 - Compiler Design and Optimization 9

Live-in and Live-out: Program Example s 1 a: s 1 = ld(x) s 2

Live-in and Live-out: Program Example s 1 a: s 1 = ld(x) s 2 b: s 2 = s 1 + 4 s 3 c: s 3 = s 1 8 d: s 4 = s 1 - 4 e: s 5 = s 1/2 f: s 6 = s 2 * s 3 g: s 7 = s 4 - s 5 h: s 8 = s 6 * s 7 s 4 s 5 s 6 s 7 What are live-in(e) and live-out(e)? live-in(e) = {s 1, s 2, s 3, 680 s 4} live-out(e) = {s 2, s 3, s 4, s 5} CMPUT - Compiler Design and Optimization 10

Live-in and Live-out in Control Flow Graphs The entry point of a basic block

Live-in and Live-out in Control Flow Graphs The entry point of a basic block B is the point before its first statement. The exit point is the point after its last statement. live-in(B): set of variables that are live at the entry point of the basic block B. live-out(B): set of variables that are live at the exit point of the basic block B. CMPUT 680 - Compiler Design and Optimization 11

Live-in and Live-out of basic blocks B 1 a : = b + c

Live-in and Live-out of basic blocks B 1 a : = b + c d : = d - b e : = a + f B 2 f : = a - d B 3 b : = d + f e : = a - c B 4 b : = d + c • live-in(B 1)={b, c, d, f} • live-in(B 2)={a, c, d, e} • live-in(B 3)={a, c, d, f} • live-in(B 4)={c, d, e, f} • live-out(B 1)={a, c, d, e, f} • live-out(B 2)={c, d, e, f} • live-out(B 3)={b, c, d, e, f} • live-out(B 4)={b, c, d, e, f} b, d, e, f live b, c, d, e, f live CMPUT 680 - Compiler Design and Optimization Compute live-in and live-out for each basic block 12 (Aho-Sethi-Ullman, pp. 544)

Register-Interference Graph A register-interference graph is an undirected graph that summarizes live analysis at

Register-Interference Graph A register-interference graph is an undirected graph that summarizes live analysis at the variable level as follows: z A node is a variable/temporary that is a candidate for register allocation. z An edge connects nodes v 1 and v 2 if there is some statement in the program where variables v 1 and v 2 are live simultaneously. (Variables v 1 and v 2 are said to interfere, in this case). CMPUT 680 - Compiler Design and Optimization 13

Register Interference Graph: Program Example s 1 s 7 s 2 a: s 1

Register Interference Graph: Program Example s 1 s 7 s 2 a: s 1 = ld(x) b: s 2 = s 1 + 4 c: s 3 = s 1 8 d: s 4 = s 1 - 4 s 3 s 6 s 5 s 4 e: s 5 = s 1/2 f: s 6 = s 2 * s 3 s 2 s 3 s 4 s 5 s 6 s 7 g: s 7 = s 4 - s 5 h: s 8 = s 6 * s 7 CMPUT 680 - Compiler Design and Optimization 14

Register Allocation by Graph Coloring Background: A graph is k-colorable if each node can

Register Allocation by Graph Coloring Background: A graph is k-colorable if each node can be assigned one of k colors in such a way that no two adjacent nodes have the same color. Basic idea: A k-coloring of the interference graph can be directly mapped to a legal register allocation by mapping each color to a distinct register. The coloring property ensures that no two variables that interfere with each other are assigned the same register. CMPUT 680 - Compiler Design and Optimization 15

Register Allocation by Graph Coloring The basic idea behind register allocation by graph coloring

Register Allocation by Graph Coloring The basic idea behind register allocation by graph coloring is to 1. Build the register interference graph, 2. Attempt to find a k-coloring for the interference graph. CMPUT 680 - Compiler Design and Optimization 16

Complexity of the Graph Coloring Problem z. The problem of determining if an undirected

Complexity of the Graph Coloring Problem z. The problem of determining if an undirected graph is kcolorable is NP-hard for k 3. z. It is also hard to find approximate solutions to the graph coloring problem. CMPUT 680 - Compiler Design and Optimization 17

Register Allocation Question: What to do if a register-interference graph is not k-colorable? Or

Register Allocation Question: What to do if a register-interference graph is not k-colorable? Or if the compiler cannot efficiently find a k-coloring even if the graph is k-colorable? Answer: Repeatedly select less profitable variables for “spilling” (i. e. not to be assigned to registers) and remove them from the interference graph until the graph becomes k-colorable. CMPUT 680 - Compiler Design and Optimization 18

Estimating Register Profitability CMPUT 680 - Compiler Design and Optimization 19

Estimating Register Profitability CMPUT 680 - Compiler Design and Optimization 19

Heuristic Solution for Graph Coloring Key observation: Let G be an undirected graph. Let

Heuristic Solution for Graph Coloring Key observation: Let G be an undirected graph. Let x be a node of G such that degree(x) < k. graph G Remove node x and all associate edges graph G’ Then G is k-colorable if G’ is k-colorable. CMPUT 680 - Compiler Design and Optimization 20

A 2 -Phase Register Allocation Algorithm Build IG Simplify Forward pass CMPUT 680 -

A 2 -Phase Register Allocation Algorithm Build IG Simplify Forward pass CMPUT 680 - Compiler Design and Optimization Select and Spill Reverse pass 21

Heuristic “Optimistic” Algorithm /* neighbor(v) contains a list of the neighbors of v. */

Heuristic “Optimistic” Algorithm /* neighbor(v) contains a list of the neighbors of v. */ /* Build step */ Build G, the register-interference graph; /* Forward pass */ Initialize an empty stack; repeat while G has a node v such that |neighbors(v)| < k do /* Simplify step */ Push (v, neighbors(v), no-spill) Delete v and its edges from G end while if G is non-empty then /* Spill step */ Choose “least profitable” node v as a potential spill node; Push (v, neighbors(v), may-spill) Delete v and its edges from G end if until G is an empty graph; CMPUT 680 - Compiler Design and Optimization 22

Heuristic “Optimistic” Algorithm /* Reverse Pass */ while the stack is non-empty do Pop

Heuristic “Optimistic” Algorithm /* Reverse Pass */ while the stack is non-empty do Pop (v, neighbors(v), tag) N : = set of nodes in neighbors(v); if (tag = no-spill) then /* Select step */ Select a register R for v such that R is not assigned to nodes in N; Insert v as a new node in G; Insert edges in G from v to each node in N; else /* tag = may-spill */ if v can be assigned a register R such that R is not assigned to nodes in N then /* Optimism paid off: need not spill */ Assign register R to v; Insert v as a new node in G; Insert edges in G from v to each node in N; else /* Need to spill v */ Mark v as a node that needs spill end if end while CMPUT 680 - Compiler Design and Optimization 23

Remarks This register allocation algorithm, based on graph coloring, is both efficient (linear time)

Remarks This register allocation algorithm, based on graph coloring, is both efficient (linear time) and effective (good assignment). It has been used in many industrystrength compilers to obtain significant improvements over simpler register allocation heuristics. CMPUT 680 - Compiler Design and Optimization 24

Extensions z. Coalescing z. Live range splitting CMPUT 680 - Compiler Design and Optimization

Extensions z. Coalescing z. Live range splitting CMPUT 680 - Compiler Design and Optimization 25

Coalescing In the sequence of intermediate level instructions with a copy statement below, assume

Coalescing In the sequence of intermediate level instructions with a copy statement below, assume that registers are allocated to both variables x and y. x : = …. . . y : = x. . . … : = y There is an opportunity for further optimization by eliminating the copy statement if x and y are assigned the same register. The constraint that x and y receive the same register can be modeled by coalescing the nodes for x and y in the interference graph i. e. , by treating them as the same variable. CMPUT 680 - Compiler Design and Optimization 26

An Extension with Coalesce Build IG Simplify Coalesce CMPUT 680 - Compiler Design and

An Extension with Coalesce Build IG Simplify Coalesce CMPUT 680 - Compiler Design and Optimization Select and Spill 27

Register Allocation with Coalescing 1. Build: build the register interference graph G and categorize

Register Allocation with Coalescing 1. Build: build the register interference graph G and categorize nodes as move-related or non-move-related. 2. Simplify: one at a time, remove non-move-related nodes of low (< k) degree from G. 3. Coalesce: conservatively coalesce G: only coalesce nodes a and b if the resulting a-b node has less than k neighbors. 4. Freeze: If neither coalesce nor simplify works, freeze a move-related node of low degree, making it non-move-related and available for simplify. CMPUT 680 - Compiler Design and Optimization (Appel, pp. 240) 28

Register Allocation with Coalescing 5. Spill: if there are no low-degree nodes, select a

Register Allocation with Coalescing 5. Spill: if there are no low-degree nodes, select a node for potential spilling. 6. Select: pop each element of the stack assigning colors. (re)build actual spill simplify coalesce select CMPUT 680 - Compiler Design and Optimization freeze potential spill (Appel, pp. 240) 29

Example: Step 1: Compute Live Ranges k j LIVE-IN: k j g : =

Example: Step 1: Compute Live Ranges k j LIVE-IN: k j g : = mem[j+12] h : = k -1 f : = g + h e : = mem[j+8] g h f m : = mem[j+16] b : = mem[f] e m b c c : = e + 8 d : = c d k : = m + 4 j : = b LIVE-OUT: d k j CMPUT 680 - Compiler Design and Optimization 30

Example: Step 3: Simplify (K=4) stack f e j k b m d c

Example: Step 3: Simplify (K=4) stack f e j k b m d c h g CMPUT 680 - Compiler Design and Optimization (Appel, pp. 237) 31

Example: Step 3: Simplify (K=4) stack f (h, no-spill) e j k b m

Example: Step 3: Simplify (K=4) stack f (h, no-spill) e j k b m d c h g CMPUT 680 - Compiler Design and Optimization (Appel, pp. 237) 32

Example: Step 3: Simplify (K=4) stack (g, no-spill) (h, no-spill) f e j k

Example: Step 3: Simplify (K=4) stack (g, no-spill) (h, no-spill) f e j k b m d c g CMPUT 680 - Compiler Design and Optimization (Appel, pp. 237) 33

Example: Step 3: Simplify (K=4) stack f (k, no-spill) (g, no-spill) (h, no-spill) e

Example: Step 3: Simplify (K=4) stack f (k, no-spill) (g, no-spill) (h, no-spill) e j k b m d c CMPUT 680 - Compiler Design and Optimization (Appel, pp. 237) 34

Example: Step 3: Simplify (K=4) stack f (f, no-spill) (k, no-spill) (g, no-spill) (h,

Example: Step 3: Simplify (K=4) stack f (f, no-spill) (k, no-spill) (g, no-spill) (h, no-spill) e j b m d c CMPUT 680 - Compiler Design and Optimization (Appel, pp. 237) 35

Example: Step 3: Simplify (K=4) stack (e, no-spill) (f, no-spill) (k, no-spill) (g, no-spill)

Example: Step 3: Simplify (K=4) stack (e, no-spill) (f, no-spill) (k, no-spill) (g, no-spill) (h, no-spill) e j b m d c CMPUT 680 - Compiler Design and Optimization (Appel, pp. 237) 36

Example: Step 3: Simplify (K=4) stack j b m (m, no-spill) (e, no-spill) (f,

Example: Step 3: Simplify (K=4) stack j b m (m, no-spill) (e, no-spill) (f, no-spill) (k, no-spill) (g, no-spill) (h, no-spill) d c CMPUT 680 - Compiler Design and Optimization (Appel, pp. 237) 37

Example: Step 3: Coalesce (K=4) stack j b (m, no-spill) (e, no-spill) (f, no-spill)

Example: Step 3: Coalesce (K=4) stack j b (m, no-spill) (e, no-spill) (f, no-spill) (k, no-spill) (g, no-spill) (h, no-spill) d c Why we cannot simplify? Cannot simplify move-related nodes. CMPUT 680 - Compiler Design and Optimization (Appel, pp. 237) 38

Example: Step 3: Coalesce (K=4) stack j b (m, no-spill) (e, no-spill) (f, no-spill)

Example: Step 3: Coalesce (K=4) stack j b (m, no-spill) (e, no-spill) (f, no-spill) (k, no-spill) (g, no-spill) (h, no-spill) d c CMPUT 680 - Compiler Design and Optimization (Appel, pp. 237) 39

Example: Step 3: Simplify (K=4) stack j b (c-d, no-spill) (m, no-spill) (e, no-spill)

Example: Step 3: Simplify (K=4) stack j b (c-d, no-spill) (m, no-spill) (e, no-spill) (f, no-spill) (k, no-spill) (g, no-spill) (h, no-spill) c-d CMPUT 680 - Compiler Design and Optimization (Appel, pp. 237) 40

Example: Step 3: Coalesce (K=4) stack j b (c-d, no-spill) (m, no-spill) (e, no-spill)

Example: Step 3: Coalesce (K=4) stack j b (c-d, no-spill) (m, no-spill) (e, no-spill) (f, no-spill) (k, no-spill) (g, no-spill) (h, no-spill) CMPUT 680 - Compiler Design and Optimization (Appel, pp. 237) 41

Example: Step 3: Simplify (K=4) stack b-j (b-j, no-spill) (c-d, no-spill) (m, no-spill) (e,

Example: Step 3: Simplify (K=4) stack b-j (b-j, no-spill) (c-d, no-spill) (m, no-spill) (e, no-spill) (f, no-spill) (k, no-spill) (g, no-spill) (h, no-spill) CMPUT 680 - Compiler Design and Optimization (Appel, pp. 237) 42

Example: Step 3: Select (K=4) stack f e j k b d c h

Example: Step 3: Select (K=4) stack f e j k b d c h m (b-j, no-spill) (c-d, no-spill) (m, no-spill) (e, no-spill) (f, no-spill) (k, no-spill) (g, no-spill) (h, no-spill) R 1 R 2 R 3 R 4 g CMPUT 680 - Compiler Design and Optimization (Appel, pp. 237) 43

Example: Step 3: Select (K=4) stack f e j k b d c h

Example: Step 3: Select (K=4) stack f e j k b d c h m (b-j, no-spill) (c-d, no-spill) (m, no-spill) (e, no-spill) (f, no-spill) (k, no-spill) (g, no-spill) (h, no-spill) R 1 R 2 R 3 R 4 g CMPUT 680 - Compiler Design and Optimization (Appel, pp. 237) 44

Example: Step 3: Select (K=4) stack f e j k b d c h

Example: Step 3: Select (K=4) stack f e j k b d c h m (b-j, no-spill) (c-d, no-spill) (m, no-spill) (e, no-spill) (f, no-spill) (k, no-spill) (g, no-spill) (h, no-spill) R 1 R 2 R 3 R 4 g CMPUT 680 - Compiler Design and Optimization (Appel, pp. 237) 45

Example: Step 3: Select (K=4) stack f e j k b d c h

Example: Step 3: Select (K=4) stack f e j k b d c h m (b-j, no-spill) (c-d, no-spill) (m, no-spill) (e, no-spill) (f, no-spill) (k, no-spill) (g, no-spill) (h, no-spill) R 1 R 2 R 3 R 4 g CMPUT 680 - Compiler Design and Optimization (Appel, pp. 237) 46

Example: Step 3: Select (K=4) stack f e j k b d c h

Example: Step 3: Select (K=4) stack f e j k b d c h m (b-j, no-spill) (c-d, no-spill) (m, no-spill) (e, no-spill) (f, no-spill) (k, no-spill) (g, no-spill) (h, no-spill) R 1 R 2 R 3 R 4 g CMPUT 680 - Compiler Design and Optimization (Appel, pp. 237) 47

Example: Step 3: Select (K=4) stack f e j k b d c h

Example: Step 3: Select (K=4) stack f e j k b d c h m (b-j, no-spill) (c-d, no-spill) (m, no-spill) (e, no-spill) (f, no-spill) (k, no-spill) (g, no-spill) (h, no-spill) R 1 R 2 R 3 R 4 g CMPUT 680 - Compiler Design and Optimization (Appel, pp. 237) 48

Example: Step 3: Select (K=4) stack f e j k b d c h

Example: Step 3: Select (K=4) stack f e j k b d c h m (b-j, no-spill) (c-d, no-spill) (m, no-spill) (e, no-spill) (f, no-spill) (k, no-spill) (g, no-spill) (h, no-spill) R 1 R 2 R 3 R 4 g CMPUT 680 - Compiler Design and Optimization (Appel, pp. 237) 49

Example: Step 3: Select (K=4) stack f e j k b d c h

Example: Step 3: Select (K=4) stack f e j k b d c h m (b-j, no-spill) (c-d, no-spill) (m, no-spill) (e, no-spill) (f, no-spill) (k, no-spill) (g, no-spill) (h, no-spill) R 1 R 2 R 3 R 4 g CMPUT 680 - Compiler Design and Optimization (Appel, pp. 237) 50

Could we do the allocation in the previous example with 3 registers? CMPUT 680

Could we do the allocation in the previous example with 3 registers? CMPUT 680 - Compiler Design and Optimization 51

Example: Step 3: Simplify (K=3) stack f (h, no-spill) e j k b m

Example: Step 3: Simplify (K=3) stack f (h, no-spill) e j k b m d c h g CMPUT 680 - Compiler Design and Optimization (Appel, pp. 237) 52

Example: Step 3: Simplify (K=3) stack (g, no-spill) (h, no-spill) f e j k

Example: Step 3: Simplify (K=3) stack (g, no-spill) (h, no-spill) f e j k b m d c g CMPUT 680 - Compiler Design and Optimization (Appel, pp. 237) 53

Example: Step 5: Freeze (K=3) stack (g, no-spill) (h, no-spill) f e j k

Example: Step 5: Freeze (K=3) stack (g, no-spill) (h, no-spill) f e j k b d c m Coalescing would make things worse. We can freeze the move d-c. CMPUT 680 - Compiler Design and Optimization (Appel, pp. 237) 54

Example: Step 3: Simplify (K=3) stack (c, no-spill) (g, no-spill) (h, no-spill) f e

Example: Step 3: Simplify (K=3) stack (c, no-spill) (g, no-spill) (h, no-spill) f e j k b m d c CMPUT 680 - Compiler Design and Optimization (Appel, pp. 237) 55

Example: Step 6: Spill (K=3) stack (e, may-spill) (c, no-spill) (g, no-spill) (h, no-spill)

Example: Step 6: Spill (K=3) stack (e, may-spill) (c, no-spill) (g, no-spill) (h, no-spill) f e j k b d m Neither coalescing nor freezing help us. At this point we should use some profitability analysis to choose a node as may-spill. CMPUT 680 - Compiler Design and Optimization (Appel, pp. 237) 56

Example: Step 3: Simplify (K=3) stack (f, no-spill) (e, may-spill) (c, no-spill) (g, no-spill)

Example: Step 3: Simplify (K=3) stack (f, no-spill) (e, may-spill) (c, no-spill) (g, no-spill) (h, no-spill) f j k b m d CMPUT 680 - Compiler Design and Optimization (Appel, pp. 237) 57

Example: Step 3: Simplify (K=3) j k b stack (m, no-spill) (f, no-spill) (e,

Example: Step 3: Simplify (K=3) j k b stack (m, no-spill) (f, no-spill) (e, may-spill) (c, no-spill) (g, no-spill) m (h, no-spill) d CMPUT 680 - Compiler Design and Optimization (Appel, pp. 237) 58

Example: Step 3: Coalesce (K=3) j k b stack (m, no-spill) (f, no-spill) (e,

Example: Step 3: Coalesce (K=3) j k b stack (m, no-spill) (f, no-spill) (e, may-spill) (c, no-spill) (g, no-spill) (h, no-spill) d CMPUT 680 - Compiler Design and Optimization (Appel, pp. 237) 59

Example: Step 3: Coalesce (K=3) j-b stack (d, no-spill) (m, no-spill) (f, no-spill) (e,

Example: Step 3: Coalesce (K=3) j-b stack (d, no-spill) (m, no-spill) (f, no-spill) (e, may-spill) (c, no-spill) (g, no-spill) (h, no-spill) k d CMPUT 680 - Compiler Design and Optimization (Appel, pp. 237) 60

Example: Step 3: Coalesce (K=3) j-b k stack (k, no-spill) (d, no-spill) (m, no-spill)

Example: Step 3: Coalesce (K=3) j-b k stack (k, no-spill) (d, no-spill) (m, no-spill) (f, no-spill) (e, may-spill) (c, no-spill) (g, no-spill) (h, no-spill) CMPUT 680 - Compiler Design and Optimization (Appel, pp. 237) 61

Example: Step 3: Coalesce (K=3) j-b stack (j-b, no-spill) (k, no-spill) (d, no-spill) (m,

Example: Step 3: Coalesce (K=3) j-b stack (j-b, no-spill) (k, no-spill) (d, no-spill) (m, no-spill) (f, no-spill) (e, may-spill) (c, no-spill) (g, no-spill) (h, no-spill) CMPUT 680 - Compiler Design and Optimization (Appel, pp. 237) 62

Example: Step 3: Select (K=3) stack f e j k b d c h

Example: Step 3: Select (K=3) stack f e j k b d c h m (j-b, no-spill) (k, no-spill) (d, no-spill) (m, no-spill) (f, no-spill) (e, may-spill) (c, no-spill) (g, no-spill) (h, no-spill) R 1 R 2 R 3 g CMPUT 680 - Compiler Design and Optimization (Appel, pp. 237) 63

Example: Step 3: Select (K=3) stack f e j k b d c h

Example: Step 3: Select (K=3) stack f e j k b d c h m (j-b, no-spill) (k, no-spill) (d, no-spill) (m, no-spill) (f, no-spill) (e, may-spill) (c, no-spill) (g, no-spill) (h, no-spill) R 1 R 2 R 3 g CMPUT 680 - Compiler Design and Optimization (Appel, pp. 237) 64

Example: Step 3: Select (K=3) stack f e j k b d c h

Example: Step 3: Select (K=3) stack f e j k b d c h m (j-b, no-spill) (k, no-spill) (d, no-spill) (m, no-spill) (f, no-spill) (e, may-spill) (c, no-spill) (g, no-spill) (h, no-spill) R 1 R 2 R 3 g CMPUT 680 - Compiler Design and Optimization (Appel, pp. 237) 65

Example: Step 3: Select (K=3) stack f e j k b d c h

Example: Step 3: Select (K=3) stack f e j k b d c h m (j-b, no-spill) (k, no-spill) (d, no-spill) (m, no-spill) (f, no-spill) (e, may-spill) (c, no-spill) (g, no-spill) (h, no-spill) R 1 R 2 R 3 g CMPUT 680 - Compiler Design and Optimization (Appel, pp. 237) 66

Example: Step 3: Select (K=3) stack f e j k b d c h

Example: Step 3: Select (K=3) stack f e j k b d c h m (j-b, no-spill) (k, no-spill) (d, no-spill) (m, no-spill) (f, no-spill) (e, may-spill) (c, no-spill) (g, no-spill) (h, no-spill) R 1 R 2 R 3 g CMPUT 680 - Compiler Design and Optimization (Appel, pp. 237) 67

Example: Step 3: Select (K=3) stack f e j k b d c h

Example: Step 3: Select (K=3) stack f e j k b d c h g m (j-b, no-spill) (k, no-spill) (d, no-spill) (m, no-spill) (f, no-spill) (e, may-spill) (c, no-spill) (g, no-spill) (h, no-spill) R 1 R 2 R 3 This is when our optimism could have paid off. CMPUT 680 - Compiler Design and Optimization (Appel, pp. 237) 68

Example: Step 3: Select (K=3) stack f e j k b d c h

Example: Step 3: Select (K=3) stack f e j k b d c h m (j-b, no-spill) (k, no-spill) (d, no-spill) (m, no-spill) (f, no-spill) (e, may-spill) (c, no-spill) (g, no-spill) (h, no-spill) R 1 R 2 R 3 g CMPUT 680 - Compiler Design and Optimization (Appel, pp. 237) 69

Example: Step 3: Select (K=3) stack f e j k b d c h

Example: Step 3: Select (K=3) stack f e j k b d c h m (j-b, no-spill) (k, no-spill) (d, no-spill) (m, no-spill) (f, no-spill) (e, may-spill) (c, no-spill) (g, no-spill) (h, no-spill) R 1 R 2 R 3 g CMPUT 680 - Compiler Design and Optimization (Appel, pp. 237) 70

Example: Step 3: Select (K=3) stack f e j k b d c h

Example: Step 3: Select (K=3) stack f e j k b d c h m (j-b, no-spill) (k, no-spill) (d, no-spill) (m, no-spill) (f, no-spill) (e, may-spill) (c, no-spill) (g, no-spill) (h, no-spill) R 1 R 2 R 3 g CMPUT 680 - Compiler Design and Optimization (Appel, pp. 237) 71

Live Range Splitting The basic coloring algorithm does not consider cases in which a

Live Range Splitting The basic coloring algorithm does not consider cases in which a variable can be allocated to a register for part of its live range. Some compilers split live ranges within the iteration structure of the coloring algorithm. When a variable is split into two new variables, one of the new variables might be profitably assigned to a register while the other is not. CMPUT 680 - Compiler Design and Optimization 72

Length of Live Ranges The interference graph does not contain information of where in

Length of Live Ranges The interference graph does not contain information of where in the CFG variables interfere and what the length of a variable’s live range is. For example, if we only had few available registers in the following intermediatecode example, the right choice would be to spill variable w because it has the longest live range: x = w + 1 c = a - 2 y = x * 3 z = w + y CMPUT 680 - Compiler Design and Optimization 73

Effect of Instruction Reordering on Register Pressure The coloring algorithm does not take into

Effect of Instruction Reordering on Register Pressure The coloring algorithm does not take into account the fact that reordering IL instructions can reduce interference. Consider the following example: Original Ordering Optimized Ordering (needs 3 registers) t 1 t 2 t 3 t 4 t 5 : = A[i] : = A[j] : = A[k] : = t 2 * t 3 : = t 1 + t 4 (needs 2 registers) t 2 t 3 t 4 t 1 t 5 ; = : = : = A[j] A[k] t 2 * t 3 A[i] t 1 + t 4 CMPUT 680 - Compiler Design and Optimization 74

Brief History of Register Allocation Chaitin: ACM SIGPLAN Notices 1982 Use the simple stack

Brief History of Register Allocation Chaitin: ACM SIGPLAN Notices 1982 Use the simple stack heuristic for register allocation. Spill/no-spill decisions are made during the stack construction phase of the algorithm Briggs: PLDI 1989 Finds out that Chaitin’s algorithm spills even when there available registers. Solution: the optimistic approach: may-spill during stack construction, decide at spilling time. CMPUT 680 - Compiler Design and Optimization 75

Brief History of Register Allocation Chow-Hennessy: Priority-based coloring. SIGPLAN Integrate spilling decisions in the

Brief History of Register Allocation Chow-Hennessy: Priority-based coloring. SIGPLAN Integrate spilling decisions in the 1984 coloring decisions: spill a variable ASPLOS for a limited life range. 1990 Favor dense over sparse use regions. Consider parameter passing convention. Callahan: PLDI 1991 Hierarchical Coloring Graph, register preferencing, profitability of spilling. CMPUT 680 - Compiler Design and Optimization 76