Web page for IU Compiler Course for Fall 2020
View the Project on GitHub IUCompilerCourse/IU-P423-P523-E313-E513-Fall-2020
Goal: map each variable to a register such that no two interfering variables get mapped to the same register.
Secondary goal: minimize the number of stack locations that need to be used.
In the interference graph, this means that adjacent vertices must be mapped to different registers.
If we think of registers and stack locations as colors, then this becomes an instance of the graph coloring problem.
If you aren’t familiar with graph coloring, you might instead be familiar with another instance of it, Sudoku.
Review Sudoku and relate it to graph coloring.
-------------------
| 9 |5 3 7| 1 4|
| 3 8| 4 6| 9 |
|4 |1 |2 |
-------------------
| | | 2|
|7 9|8 2|1 5|
|6 | | |
-------------------
| 4| 8| 6|
| 6 |4 9 |7 2 |
|8 7 |6 2 3| 4 |
-------------------
What strategies do you use to play Sudoku?
We’ll use the DSATUR algorithm of Brelaz (1979). Use natural numbers for colors. The set W is our worklist, that is, the vertices that still need to be colored.
W <- vertices(G)
while W /= {} do
pick a vertex u from W with maximal saturation
find the lowest color c not in { color[v] | v in adjacent(u) }.
color[u] <- c
W <- W - {u}
Initial state:
{} {} {}
t ---- z x
|\_ |
| \__ |
| \|
y ---- w ---- v
{} {} {}
There’s a tie amogst all vertices. Color t 0. Update saturation of adjacent.
{} {0} {}
t:0----z x
|\_ |
| \__ |
| \|
y ---- w ---- v
{} {} {}
Vertex z is the most saturated. Color z 1. Update saturation of adjacent.
{1} {0} {}
t:0----z:1 x
|\_ |
| \__ |
| \|
y ---- w ---- v
{1} {1} {}
There is a tie between y and w. Color w 0.
{1} {0} {0}
t:0----z:1 x
|\_ |
| \__ |
| \|
y ----w:0---- v
{0,1} {1} {0}
Vertex y is the most saturated. Color y 2.
{1} {0,2} {0}
t:0----z:1 x
|\_ |
| \__ |
| \|
y:2----w:0---- v
{0,1} {1,2} {0}
Vertex x and v are the most saturated. Color v 1.
{1} {0,2} {0}
t:0----z:1 x
|\_ |
| \__ |
| \|
y:2----w:0----v:1
{0,1} {1,2} {0}
Vertex x is the most saturated. Color x 1.
{1} {0,2} {0}
t:0----z:1 x:1
|\_ |
| \__ |
| \|
y:2----w:0----v:1
{0,1} {1,2} {0}
Create variable to register/stack location mapping:
We’re going to reserve rax
and r15
for other purposes,
and we use rsp
and rbp
for maintaining the stack,
so we have 12 remaining registers to use:
rbx rcx rdx rsi rdi r8 r9 r10 r11 r12 r13 r14
Map the first 12 colors to the above registers, and map the rest of
the colors to stack locations (starting with a -8 offset from rbp
and going down in increments of 8 bytes.
0 -> rbx
1 -> rcx
2 -> rdx
3 -> rsi
...
12 -> -8(%rbp)
13 -> -16(%rbp)
14 -> -24(%rbp)
...
So we have the following variable-to-home mapping
v -> rcx
w -> rbx
x -> rcx
y -> rdx
z -> rcx
t -> rbx
Update the program, replacing variables according to the variable-to-home mapping. We also record the number of bytes needed of stack space for the local variables, which in this case is 0.
Recall the example program after instruction selection:
locals: v w x y z t
start:
movq $1, v
movq $42, w
movq v, x
addq $7, x
movq x, y
movq x, z
addq w, z
movq y, t
negq t
movq z, %rax
addq t, %rax
jmp conclusion
Here’s the output of register allocation, after applying the variable-to-home mapping.
stack-space: 0
start:
movq $1, %rcx
movq $42, %rbx
movq %rcx, %rcx
addq $7, %rcx
movq %rcx, %rdx
movq %rcx, %rcx
addq %rbx, %rcx
movq %rdx, %rbx
negq %rbx
movq %rcx, %rax
addq %rbx, %rax
jmp conclusion
In the above output code there are two movq instructions that can be removed because their source and target are the same. A better register allocation would have put t, v, x, and y into the same register, thereby removing the need for three of the movq instructions.
Here is the move-graph for the example program.
t z --- x
\_ _/ \_
\_ _/ \_
\ / \
y w v
Let’s redo the coloring, fast-forwarding past the coloring of t and z.
{1} {0} {}
t:0----z:1 x
|\_ |
| \__ |
| \|
y ---- w ---- v
{1} {1} {}
There is a tie between y and w regarding saturation, but this time we note that y is move related to t, which has color 0, whereas w is not move related. So we color y to 0.
{1} {0} {}
t:0----z:1 x
|\_ |
| \__ |
| \|
y:0---- w ---- v
{1} {0,1} {}
Next we color w to 2.
{1} {0,2} {2}
t:0----z:1 x
|\_ |
| \__ |
| \|
y:0----w:2---- v
{1,2} {0,1} {2}
Now x and v are equally saturated, but x is move related to y and z whereas v is not move related to any vertex that has already been colored. So we color x to 0.
{1} {0,2} {2}
t:0----z:1 x:0
|\_ |
| \__ |
| \|
y:0----w:2----v:0
{1,2} {0,1} {2}
Finally, we color v to 0.
So we have the assignment:
v -> rbx
w -> rdx
x -> rbx
y -> rbx
z -> rcx
t -> rbx
and generate the following code.
movq $1, %rbx
movq $42, %rdx
movq %rbx, %rbx
addq $7, %rbx
movq %rbx, %rbx
movq %rbx, %rcx
addq %rdx, %rcx
movq %rbx, %rbx
negq %rbx
movq %rcx, %rax
addq %rbx, %rax
jmp conclusion
As promised, there are three trivial movq’s that can be removed in patch-instructions.
movq $1, %rbx
movq $42, %rdx
addq $7, %rbx
movq %rbx, %rcx
addq %rdx, %rcx
negq %rbx
movq %rcx, %rax
addq %rbx, %rax
jmp conclusion