1
Alocação de registradores
Compiladores II
2
Fontes
Modern Compiler Implementation in
java: capítulos 10 e 11
Aho, Sethi, Ulman: capítulo 10
3
Alocação de Registradores
Motivação
Intervalo de Vidas e grafos de
interferência
Problema
Soluções
4
Alocação de Registradores
Selecionar variáveis para atribuírmos a
registradores.
Usar mesmo registrador para multiplas
variaveis.
5
Liveness
Intuitivamente uma variavel
v
está viva se tem
um valor que será utilizado no futuro. Em outras
palavras,
v
está viva em um ponto
p
ise:
(i)
v
foi definida em um comando que
antecede um
p
i(por qualquer caminho)
(ii)
v
pode ser usada em um comando
s
j,
e existe um caminho de
p
ium
s
j.
(iii)
v
não foi morta entre
p
ie
s
j.6
Variáveis vivas
a: s1 = ld(x) b: s2 = s1 + 4 c: s3 = s1 ∗∗∗∗ 8 d: s4 = s1 - 4 e: s5 = s1/2 f: s6 = s2 * s3 g: s7 = s4 - s5 h: s8 = s6 * s7A variável
v
está viva entre
o ponto
p
iimediatamente após
sua definição
e o ponto
p
jimediatamente apos seu
ultimo uso
.
O intervalo
[p
i, p
j]
é o
Interv-alo de Vida
da variável
v
.
Quais variáveis tem o maior
Intervalo de Vida no exemplo?
variáveis
s1
e
s2
tem um Intervalo de Vida
de 4 comandos.
s2 s1
7
Alocação de Registradores
a: s1 = ld(x) b: s2 = s1 + 4 c: s3 = s1 ∗∗∗∗ 8 d: s4 = s1 - 4 e: s5 = s1/2 f: s6 = s2 * s3 g: s7 = s4 - s5 h: s8 = s6 * s7Como podemos descobrir qual
o número minimo de
registrado-res é necessario neste bloco
básico sem que haja
neces-sidade de acessar memoria?
Temos que calcular o intervalo
de vida de todasl variáveis e
achar o comando mais
“largo”
.
Qual comando tem o maior numero
de variáveis vivas simultaneamente?
8
Alocação de Registradores
a: s1 = ld(x) b: s2 = s1 + 4 c: s3 = s1 ∗∗∗∗ 8 d: s4 = s1 - 4 e: s5 = s1/2 f: s6 = s2 * s3 g: s7 = s4 - s5 h: s8 = s6 * s7 s7 s6 s5 s4 s3 s2 s1No comando
d
as variáveis
s1
,
s2
,
s3
, e
s4
estão vivas,
e durante o comando
e
as
variáveis
s2
,
s3
,
s4
,
e
s5
estão vivas.
9live-in e live-out
a: s1 = ld(x) b: s2 = s1 + 4 c: s3 = s1 ∗∗∗∗ 8 d: s4 = s1 - 4 e: s5 = s1/2 f: s6 = s2 * s3 g: s7 = s4 - s5 h: s8 = s6 * s7 s7 s6 s5 s4 s3 s2s1
live-in
(
r
): conjunto de variáveis
que estão vivas no ponto
imediatamente anterior ao
comando
r
.
live-out
(
r
): conjunto of
variáveis que estão vivas no
ponto imediatamente após o
comando
r
.
10
live-in e live-out: Programa exemplo
a: s1 = ld(x) b: s2 = s1 + 4 c: s3 = s1 ∗∗∗∗ 8 d: s4 = s1 - 4 e: s5 = s1/2 f: s6 = s2 * s3 g: s7 = s4 - s5 h: s8 = s6 * s7 s7 s6 s5 s4 s3 s2 s1
Quais são os live-in(e) e live-out(e)?
live-in(e) = {s1, s2, s3, s4} live-out(e) = {s2, s3, s4, s5}
11
live-in e live-out no CFG
O
ponto de entrada
do bloco básico
B
é o ponto
ante-rior ao seu primeiro comando. o
ponto de saída
é o
ponto posterior ao seu último comando.
live-in
(
B
): conjunto de variáveis vivas no ponto de
entrada do bloco básico
B
.
live-out
(
B
): conjunto de variáveis vivas no ponto de
saída do bloco básico
B
.
12
live-in e live-out de bloco básicos
a := b + c
d := d - b
e := a + f
b := d + c
b := d + f
e := - c
f := a - d
B
4B
3B
2B
1•
live-in(
B
4)={c,d,e,f}
•
live-out(
B
4)={b,c,d,e,f}
b, d, e, f vivas
b, c, d, e, f vivas
•
live-in(
B
1)={b,c,d,f}
•
live-out(
B
1)={a,c,d,e,f}
•
live-in(
B
2)={a,c,d,e}
•
live-out(
B
2)={c,d,e,f}
• live-in(B
3)={a,c,d,f}
• live-out(B
3)={b,c,d,e,f}
calcular live-in
e live-out para
cada bloco básico
13
Grafo de interferência de registradores
(GIR)
Um
grafo de interferência de registradores
é um
grafo não-dirigido que resume a análise das
variáveis vivas da seguinte maneira:
Um nodo é uma variável/temporario que é um
candidato para alocação em registradores.
Um arco conecta nodos
v1
e
v2
se existe algum
comando no programa onde as variáveis
v1
e
v2
estão vivas simultaneamente. (variáveis
v1
e
v2
interferem uma a outra).
14
Grafo de interferência de
registradores : exemplo
a: s1 = ld(x) b: s2 = s1 + 4 c: s3 = s1 ∗∗∗∗ 8 d: s4 = s1 - 4 e: s5 = s1/2 f: s6 = s2 * s3 g: s7 = s4 - s5 h: s8 = s6 * s7 s7 s6 s5 s4 s3 s2 s1 s1 s2 s3 s4 s5 s7 s6 15Alocação de Registradores
por coloração de Grafos
Background: um grafo é
k-colorível
se cada
node pode ser atribuído uma entre
k
cores de
maneira que nenhum nodo adjacente tenha a
mesma cor.
Ideia básica: um k-coloraçãodo GIR pode ser mapeada diretamente para uma alocação legal de registradores, mapeando cada cor a um registrador distinto.
A propriedade de coloração garante que nenhum par de registradores alocado para variáveis adjacentes interferem entre elas se tiverem cores diferentes.
16
A ideia básica da Alocação de
Registradores por coloração é
1. construir o grafo de interferencia de
registrador,
2. Achar uma
k-coloração
para ele.
Alocação de Registradores
por coloração de Grafos
17
Complexidade do problema da
coloração
o problema de determinar se um
grafo não-dirigido é
k-colorível
tem
complexidade NP-hard para
k
≥ 3.
Também é dificil achar boas
aproximações para o problema.
18
Questão: O que fazer se um GIR não for
k-colorível
? Ou se o compilador não
puder achar uma
k-coloração
de
maneira eficiente?
Alocação de Registradores
Resposta: selecionar variáveis menos lucrativas para
“spilling” (i.e. não atribuí-las a registradores) e
remove-la do GIR até que o grafo seja
k-colorível
.
19
Lucratividade de uso do registrador
.
l
variave
para
usado
for
r
registrado
um
se
,
basico
bloco
no
ns
instructio
store
and
load
instruções
de
termos
em
os
economizad
r
processado
do
ciclos
de
estimado
numero
:
,
basico
bloco
um
de
execucao
de
estiamada
frequencia
:
:
é
r
registrado
em
variable
uma
usar
de
ade
lucrativid
A
v
i
, i)
savings (v
i
freq(i)
, i)
savings(v
freq(i)
ity(v)
profitabil
v
i∑
×
=
20Solução heurística para coloração
Remover nodox e todos arcos associados
observação:
grafoG grafoG’
G
é
k-colorível
se
G’
é
k-colorível
.
Dado
G
um grafo não-dirigido
Seja
x
um nodo de
G
tal que
degree(x) < k
.
21Algorithm de 2-fases
Construir
GI
Simplificar
Selecionar
e
“Spill”
Forward pass
Reverse pass
22 /* neighbor(v) contains a list of
o neighbors of v. */ /* Build Pass */
BuildG, o GIR;
/* Forward pass */
Initialize an empty stack;
repeat
whileGhas a node vsuch that |neighbors(v)| < kdo /* Simplify Step */
Push (v, neighbors(v), no-spill) Delete ve its edges from G end while
if Gis non-empty on /* Spill Step */
Choose “least profitable” node v as a potential spill node; Push (v, neighbors(v), may-spill) Deletevand its edges from G end if
untilGis an empty graph;
Algoritmo heurístico otimista
23 /* Reverse Pass */
whilestack is non-empty do
Pop (v, neighbors(v), tag) N:= set of nodes in neighbors(v);
if (tag= no-spill) on /* Select Step */
Select register Rfor vsuch that Ris not assigned to nodes inN; Insert vas a new node in G; Insert edges in Gfrom v
to each node in N;
else /* tag = may-spill */
if vcan be assigned a register R such thatRis not assigned to nodes in Non
/* Optimism paid off: need not spill */
Assign register Rto v; Insertvas a new node in G; Insert edges in Gfrom v
to each node in N;
else
/* Need to spill v */
Mark vas a node that needs spill
end if end if end while
Algoritmo heurístico otimista
24
Alguns pontos
Esta algoritmo de Alocação de
Registradores, basedo em coloração de
grafos, é ao mesmo tempo eficiente
(linear time) e efetivo (good assignment).
25
Extensões
Coalescing (união)
Divisão do Intervalo de Vida
26
Coalescing
Em uma sequencia de código intermediário com copy
comand, assumir registradores estão alocados para
ambas variáveis
x
e
y
. (no GIR estes são chamados
nodos de move-related
x := …
. . .
y := x
. . .
… := y
Oportunidade para mais otimização:
eliminar o copy comand se
x
e
y
atribuidos ao mesmo registrador.
Esta restrição, na qual
x
e
y
são atribuídas ao
mesmo registrador pode be modelada por
coalescing (união) dos nodos
x
e
y
no GIR, i.e.,
tratando-as como se fossem a mesma variável.
27
Simplificar
Construir
IG
Selecionar
e
“Spill”
Coalesce
Uma Extensão com Coalesce
28
Alocação de Registradores com
Coalescing
2. Simplificar:
um por vez, remover
non-move-related
nodos com baixo degree (<
k
) de
G
. O nodo
removido é empilhado.
1. Construir:
o GIR
G
e categorizar nodos como
move-related
ou
non-move-related.
3. Coalesce:
coalesce (unir) moderadamente
G
: somente
nodos
a
e
b
se o nodo resultante
a-b
tem
menos que
k
vizinhos.
4. Freeze:
se nem coalesce nem simplificar funcionar,
fazer um freeze dos nodos
move-related
de
baixo degree, tornando
non-move-related
e
disponibilizando para simplifação.
(Appel, pp. 240)
29
Alocação de Registradores com
Coalescing
5. Spill:
se não existirem nodos de baixo degree, selecionar
nodo para potencial
“spilling”.
6. Selecionar:
pop cada elemento do stack, atribuindo cores
(re)build
simplify
coalesce
freeze
select
potential
spill
actual
spill
(Appel, pp. 240) 30exemplo:
Passo 1: calcular Intervalos de Vidas
live-in: k j g := mem[j+12] h := k -1 f := g + h e := mem[j+8] m := mem[j+16] b := mem[f] c := e + 8 d := c j := b k := m + 4 live-out: d k j m e f h g k j b c d
31
exemplo:
Passo 2: Simplificar (K=4)
b m k j g h d c e f (Appel, pp. 237) stack 32exemplo:
Passo 2: Simplificar (K=4)
b m k j g h d c e f (Appel, pp. 237) (h,no-spill) stack 33exemplo:
Passo 2: Simplificar (K=4)
b m k j g d c e f (Appel, pp. 237) (g, no-spill) (h, no-spill) stack 34exemplo:
Passo 2: Simplificar (K=4)
b m k j d c e f (Appel, pp. 237) (k, no-spill) (g, no-spill) (h, no-spill) stack 35exemplo:
Passo 2: Simplificar (K=4)
b m j d c e f (f, no-spill) (k, no-spill) (g, no-spill) (h, no-spill) stack 36exemplo:
Passo 2: Simplificar (K=4)
b m j d c e (e, no-spill) (f, no-spill) (k, no-spill) (g, no-spill) (h, no-spill) stack37
exemplo:
Passo 2: Simplificar (K=4)
b m j d c (Appel, pp. 237) (m, no-spill) (e, no-spill) (f, no-spill) (k, no-spill) (g, no-spill) (h, no-spill) stack 38exemplo:
Passo 3: Coalesce (K=4)
b j d c (Appel, pp. 237) (m, no-spill) (e, no-spill) (f, no-spill) (k, no-spill) (g, no-spill) (h, no-spill) stackNão podemos simplificar? Não, nodos move-related.
39
exemplo:
Passo 3: Coalesce (K=4)
b j d c (Appel, pp. 237) (m, no-spill) (e, no-spill) (f, no-spill) (k, no-spill) (g, no-spill) (h, no-spill) stack 40exemplo:
Passo 3: Simplificar (K=4)
b j c-d (Appel, pp. 237) (c-d, no-spill) (m, no-spill) (e, no-spill) (f, no-spill) (k, no-spill) (g, no-spill) (h, no-spill) stack 41exemplo:
Passo 3: Coalesce (K=4)
b j (Appel, pp. 237) (c-d, no-spill) (m, no-spill) (e, no-spill) (f, no-spill) (k, no-spill) (g, no-spill) (h, no-spill) stack 42exemplo:
Passo 3: Simplify (K=4)
b-j (Appel, pp. 237) (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) stack43
exemplo:
Passo 6: Selecionar (K=4)
b m k j g h d c e f (Appel, pp. 237) (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) stack R1 R2 R3 R4 44exemplo:
Passo 6: Selecionar (K=4)
b m k j g h d c e f (Appel, pp. 237) (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) stack R1 R2 R3 R4 45exemplo:
Passo 6: Selecionar (K=4)
b m k j g h d c e f (Appel, pp. 237) (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) stack R1 R2 R3 R4 46exemplo:
Passo 6: Selecionar (K=4)
b m k j g h d c e f (Appel, pp. 237) (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) stack R1 R2 R3 R4 47exemplo:
Passo 6: Selecionar (K=4)
b m k j g h d c e f (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) stack R1 R2 R3 R4 48exemplo:
Passo 6: Selecionar (K=4)
b m k j g h d c e f (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) stack R1 R2 R3 R449
exemplo:
Passo 6: Selecionar (K=4)
b m k j g h d c e f (Appel, pp. 237) (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) stack R1 R2 R3 R4 50exemplo:
Passo 6: Selecionar (K=4)
b m k j g h d c e f (Appel, pp. 237) (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) stack R1 R2 R3 R4 51Pergunta
Seria possível alocar o exemplo
anterior com 3 registradores?
52
exemplo:
Passo 2: Simplificar (K=3)
b m k j g h d c e f (Appel, pp. 237) (h,no-spill) stack 53exemplo:
Passo 2: Simplificar (K=3)
b m k j g d c e f (Appel, pp. 237) (g, no-spill) (h, no-spill) stack 54exemplo:
Passo 5: Freeze (K=3)
b m k j d c e f (Appel, pp. 237) (g, no-spill) (h, no-spill) stackCoalescing iria piorar.
podemos postergar a
55
exemplo:
Passo 3: Simplify (K=3)
b m k j d c e f (Appel, pp. 237) (c, no-spill) (g, no-spill) (h, no-spill) stack 56exemplo:
Passo 6: Spill (K=3)
b m k j d e f (Appel, pp. 237) (e, may-spill) (c, no-spill) (g, no-spill) (h, no-spill) stackNem coalescing nem
freezing ajudam.
Neste ponto devemos
usar lucratividade para
escolher nodo may-spill.
57
exemplo:
Passo 3: Simplify (K=3)
b m k j d f (Appel, pp. 237) (f, no-spill) (e, may-spill) (c, no-spill) (g, no-spill) (h, no-spill) stack 58exemplo:
Passo 3: Simplify (K=3)
b m k j d (Appel, pp. 237) (m, no-spill) (f, no-spill) (e, may-spill) (c, no-spill) (g, no-spill) (h, no-spill) stack 59exemplo:
Passo 3: Coalesce (K=3)
b k j d (m, no-spill) (f, no-spill) (e, may-spill) (c, no-spill) (g, no-spill) (h, no-spill) stack 60exemplo:
Passo 3: Coalesce (K=3)
k j-b d (d, no-spill) (m, no-spill) (f, no-spill) (e, may-spill) (c, no-spill) (g, no-spill) (h, no-spill) stack61
exemplo:
Passo 3: Coalesce (K=3)
k j-b (Appel, pp. 237) (k, no-spill) (d, no-spill) (m, no-spill) (f, no-spill) (e, may-spill) (c, no-spill) (g, no-spill) (h, no-spill) stack 62exemplo:
Passo 3: Coalesce (K=3)
j-b (Appel, pp. 237) (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) stack 63exemplo:
Passo 6: Selecionar (K=3)
b m k j g h d c e f (Appel, pp. 237) stack R1 R2 R3 (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) 64exemplo:
Passo 6: Selecionar (K=3)
b m k j g h d c e f (Appel, pp. 237) stack R1 R2 R3 (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) 65exemplo:
Passo 6: Selecionar (K=3)
b m k j g h d c e f (Appel, pp. 237) stack R1 R2 R3 (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) 66exemplo:
Passo 6: Selecionar (K=3)
b m k j g h d c e f (Appel, pp. 237) stack R1 R2 R3 (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)67
exemplo:
Passo 6: Selecionar (K=3)
b m k j g h d c e f (Appel, pp. 237) stack R1 R2 R3 (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) 68exemplo:
Passo 6: Selecionar (K=3)
b m k j g h d c e f (Appel, pp. 237) stack R1 R2 R3 (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) 69exemplo:
Passo 6: Selecionar (K=3)
b m k j g h d c e f (Appel, pp. 237) stack R1 R2 R3 (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) 70exemplo:
Passo 6: Selecionar (K=3)
b m k j g h d c e f (Appel, pp. 237) stack R1 R2 R3 (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) 71exemplo:
Passo 6: Selecionar (K=3)
b m k j g h d c e f stack R1 R2 R3 (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) 72Divisão do Intervalo de Vida
o algoritmo básico de coloração não
considera casos nos quais uma variável pode
ser atribuida a um registrador em parte de
seu Intervalo de Vida.
uma variável pode ter seu intervalo dividido,
criando-se duas novas variáveis, uma delas pode criando-ser lucrativa
se atribuida a um registrador enquanto a outra não.
73