Académique Documents
Professionnel Documents
Culture Documents
23 novembre 2011
Rapidité d’exécution
Sécurité
Taille du code
Consommation d’énergie
Remarques:
Ces critères peuvent être contradictoires entre eux.
Trouver un programme compilé optimal est un problème indécidable.
On se contente d’heuristiques.
Des méthodes dynamiques d’optimisation permettent de choisir les
options de compilation en fonction du comportement du programme sur
des données bien choisies.
Dans ce cours
Produire du code MIPS qui utilise intelligemment les registres.
On considère un sous-ensemble de C
entiers
pointeurs sur des structures
commande print pour les entiers
Exemple
int fact ( int x)
{ i f ( x <=1) r e t u r n 1 ; r e t u r n x ∗ f a c t ( x − 1 ) ; }
E ::= n S ::= E;
| L | if (E) S
| L=E | if (E) S else S
| E op E | - E | ! E | while (E) S
| x(E, . . . , E) | return E;
| malloc(sizeof(struct x)) | print(E);
L ::= x | B
| E->x B ::= { V ...V S...S }
op → == | != | < | <= | > | >= V ::= T x, . . . , x;
| && | || | + | - | * | / T ::= int | struct x *
D ::= V
| T x(T x, . . . , T x) B P ::= D...D
| struct x {V . . . V };
type i n s t r =
| Skip | Expr of expr
| I f of expr ∗ i n s t r ∗ i n s t r
| While of expr ∗ i n s t r
| Block of ( d e c l _ v a r l i s t ∗ i n s t r list )
| Return of expr
| P r i n t of expr
and d e c l _ v a r = s t r i n g ∗ t y p
Une fonction a un nom, des paramètres, des variables locales et une suite
d’instructions.
type d e c l _ f u n =
{ name : s t r i n g ; params : d e c l _ v a r l i s t ; r e t u r n : t y p ;
l o c a l s : d e c l _ v a r l i s t ; body : i n s t r l i s t }
Un programme contient des variables globales et des fonctions.
type program = { g l o b s : d e c l _ v a r l i s t ; f u n s : d e c l _ f u n l i s t }
not(e1 < e2 ) = e1 ≥ e2
Attention
Certaines transformations arithmétiques ne sont correctes qu’en
l’absence d’effets de bord.
0×e =0
Les calculs sur les flottants ne satisfont pas non plus les règles usuelles
(associativité . . . )
e+0 −→ e
0+e −→ e
e−0 −→ e
e+n −→ Addi(n) e
e−n −→ Addi(−n) e
n+e −→ Addi(n) e
n1 op n2 −→ n n résultat du calcul
Propriétés attendues
Préservation de la sémantique:
Attention aux effets de bord si l’ordre d’exécution des expressions est
modifié.
Terminaison (trouver un ordre qui décroit).
Confluence (une seule forme simplifiée, l’ordre des simplifications ne
joue pas)
l e t rec t r a n s l a t e = function
Binop ( Add , e1 , e2 ) −> l e t e1 ’ = t r a n s l a t e e1
and e2 ’ = t r a n s l a t e e2 i n
mkadd e1 ’ e2 ’
| ...
l e t mkadd e1 e2 =
match e1 , e2 with
Cte ( 0 ) , e | e , Cte ( 0 ) −> e
| Cte ( n1 ) , Cte ( n2 ) −> Cte ( n1+n2 )
| Cte ( n1 ) , Unop ( Addi ( n2 ) , e ) | Unop ( Addi ( n2 ) , e ) , Cte ( n1 ) |
−> mkadd ( Cte ( n1+n2 ) ) e
| Cte ( n ) , e | e , Cte ( n ) when i n t 1 6 n
−> Unop ( Addi ( n ) , e )
| Unop ( Addi ( n1 ) , e1 ) , Unop ( Addi ( n2 ) , e2 ) when ( n1+n2 =0)
−> mkadd e1 e2
| Unop ( Addi ( n1 ) , e1 ) , Unop ( Addi ( n2 ) , e2 ) when ( i n t 1 6 n )
−> Unop ( Addi ( n1+n2 ) , mkadd e1 e2 )
| Unop ( Addi ( n ) , e1 ) , e2 | e1 , Unop ( Addi ( n ) , e2 )
−> Unop ( Addi ( n ) , mkadd e1 e2 )
| _ −> Binop ( Add , e1 , e2 )
type i n s t r =
| Econst of reg ∗ i n t ∗ l a b e l
| Eunop of reg ∗ unop ∗ reg ∗ l a b e l
| Ebinop of reg ∗ binop ∗ reg ∗ reg ∗ l a b e l
| EGaccess of reg ∗ s t r i n g ∗ l a b e l
| EGassign of reg ∗ s t r i n g ∗ l a b e l
| Eload of reg ∗ reg ∗ i n t ∗ l a b e l
| Estore of reg ∗ reg ∗ i n t ∗ l a b e l
| Emove of reg ∗ reg ∗ l a b e l
| Emalloc of reg ∗ i n t ∗ l a b e l
| Eprint of reg ∗ l a b e l
| Eubranch of ubranch ∗ reg ∗ l a b e l ∗ l a b e l
| Ebbranch of bbranch ∗ reg ∗ reg ∗ l a b e l ∗ l a b e l
| Ecall of reg ∗ s t r i n g ∗ reg l i s t ∗ l a b e l
| Egoto of label
Le graphe est représenté comme une map des étiquettes dans les
instructions.
Le graphe est construit en ajoutant les instructions en général associées
à une nouvelle étiquette.
↓L
r1 ← e1
↓L ↓ l2
r ← e1 + e2 ≡ r2 ← e2
↓l ↓ l1
addi r r1 r2
↓l
Expressions simples
l e t rec r t l _ e x p r reg e l = match e with
| Cst ( n ) −> a d d _ i n s t r ( Econst ( reg , n , l ) )
| Unop ( op , e ) −>
l e t reg1 = R e g i s t e r . f r e s h ( ) i n
l e t l 1 = a d d _ i n s t r ( Eunop ( reg , op , reg1 , l ) ) i n
r t l _ e x p r reg1 e l 1
| Binop ( op , e1 , e2 ) −>
l e t reg1 = R e g i s t e r . f r e s h ( )
and reg2 = R e g i s t e r . f r e s h ( ) i n
l e t l 2 = a d d _ i n s t r ( Ebinop ( reg , op , reg1 , reg2 , l ) ) i n
l e t l 1 = r t l _ e x p r reg2 e2 l 2 i n
r t l _ e x p r reg1 e1 l 1
| M a l l o c ( n ) −> a d d _ i n s t r ( Emalloc ( reg , n , l ) )
...
Instructions élémentaires
l e t rec r t l _ i n s t r r r e t u r n i l e x i t l a b = match i with
Skip −> l a b
| Return e −> r t l _ e x p r r r e t u r n e l e x i t
| Expr e −> l e t reg = R e g i s t e r . f r e s h ( ) i n
r t l _ e x p r reg e l a b
| P r i n t e −>
l e t reg = R e g i s t e r . f r e s h ( ) i n
l e t l a b 1 = a d d _ i n s t r ( E p r i n t ( reg , l a b ) ) i n
r t l _ e x p r reg e l a b 1
| Block ( _ , l i ) −>
List . fold_right
( fun i l −> r t l _ i n s t r r r e t u r n i l e x i t l )
l i lab
...
↓L
e?
ltrue . & lfalse
i1 i2
& .
lab
entry
e?
lbody
i lab
l
goto
type d e c l _ f u n =
{ name : s t r i n g ;
params : r e g i s t e r l i s t ;
return : register ;
entry : label ; e x i t : label ;
body : graph
}
le t r t l _ f u n df =
l e t r r e t u r n = Register . fresh ( ) in
l e t l e x i t = Label . f r e s h ( ) i n
clear_graph ( ) ;
let lentry = List . fold_right
( fun i l −> r t l _ i n s t r r r e t u r n i l e x i t l )
d f . Ast . body l e x i t
i n { name= d f . Ast . name ;
params= L i s t . map ( fun ( s , _ ) −> R e g i s t e r . v a r s )
d f . Ast . params ;
return=rreturn ;
entry= lentry ;
exit=lexit ;
body= ! graph
}
Instruction analogues
type i n s t r =
| Econst of reg ∗ i n t ∗ l a b e l
| Eunop of reg ∗ unop ∗ reg ∗ l a b e l
| Ebinop of reg ∗ binop ∗ reg ∗ reg ∗ l a b e l
| EGassign of reg ∗ s t r i n g ∗ l a b e l
| EGaccess of reg ∗ s t r i n g ∗ l a b e l
| Eload of reg ∗ reg ∗ i n t ∗ l a b e l
| E s t o r e of reg ∗ reg ∗ i n t ∗ l a b e l
| Emove of reg ∗ reg ∗ l a b e l
| Eubranch of ubranch ∗ reg ∗ l a b e l ∗ l a b e l
| Ebbranch of bbranch ∗ reg ∗ reg ∗ l a b e l ∗ l a b e l
| Egoto of l a b e l
...
Nouvelles Instructions
type i n s t r =
...
| E c a l l of s t r i n g ∗ i n t ∗ l a b e l
| E a l l o c _ f r a m e of l a b e l
| Edel_frame of l a b e l
| Ereturn
| Eget_param of reg ∗ i n t ∗ l a b e l
| Eset_param of reg ∗ i n t ∗ l a b e l
| E s y s c a l l of l a b e l
$a0 ← n
$v 0 ← 9
syscall
r ← $v 0
l e t e r t l _ i n s t r = function
...
| R t l . Emalloc ( r , n , l ) −>
l e t l a b 1 = a d d _ i n s t r ( Emove ( r , v0 , l ) ) i n
l e t lab2 = add_instr ( Esyscall ( lab1 ) ) in
l e t l a b 3 = a d d _ i n s t r ( Econst ( v0 , 9 , l a b 2 ) ) i n
( Econst ( a0 , n , l a b 3 ) )
l e t e r t l _ i n s t r = function
...
| R t l . E p r i n t ( r , l )−>
l e t lab1 = add_instr ( Esyscall l ) in
l e t lab2 = add_instr ( Econst ( v0 , 1 1 , l a b 1 ) ) i n
l e t lab3 = add_instr ( Econst ( a0 , 1 0 , l a b 2 ) ) i n
l e t lab4 = add_instr ( Esyscall lab3 ) in
l e t lab5 = add_instr ( Econst ( v0 , 1 , l a b 4 ) ) i n
( Emove ( a0 , r , l a b 5 ) )
r ← call(f , lr )
On place n (n ≤ 4) paramètres dans les registres ($a0,$a1,. . . )
$a0 ←r1
$a1 ←r2
...
On place si nécessaire les autres paramètres sur la pile
sw r5 -4($sp)
sw r6 -8($sp)
...
L’allocation du tableau d’activation sera faite en une fois par l’appelé pour
les paramètres + les données locales
On fait l’appel à la fonction call(f , n)
On affecte à $r le résultat qui est calculé dans $v 0 : r ← $v 0
l e t e r t l _ i n s t r = function
| R t l . E c a l l ( r , f , r l , l ) −>
l e t ass , r l s = assoc_formals r l i n
l e t n = L i s t . l e n g t h ass i n
l e t l a b 1 = a d d _ i n s t r ( Emove ( r , v0 , l ) ) i n
l e t lab2 = add_instr ( E c a l l ( f , n , lab1 ) ) in
l e t ofs = ref 0 in
l e t labp = L i s t . f o l d _ l e f t
( fun l a b r i −> o f s : = ! o f s − wsize ;
a d d _ i n s t r ( Eset_param ( r i , ! ofs , l a b ) ) )
lab2 r l s
in
l e t laba = L i s t . f o l d _ r i g h t
( fun ( r i , r d ) l a b −> a d d _ i n s t r ( Emove ( rd , r i , l a b ) ) )
ass l a b p
i n ( Egoto ( l a b a ) )
let e r t l _ i n s t r = function
| R t l . Econst ( r , n , l ) −> Econst ( r , n , l )
| R t l . Eunop ( r1 , op , r2 , l ) −> Eunop ( r1 , op , r2 , l )
| R t l . Ebinop ( r1 , op , r2 , r3 , l ) −> Ebinop ( r1 , op , r2 , r3 , l )
| R t l . EGassign ( r , x , l ) −> EGassign ( r , x , l )
...
let ertl_graph g =
Label .M. map
( fun l a b i −> a d d _ l a b _ i n s t r l a b ( e r t l _ i n s t r i ) )
g
let f u n _ e n t r y savers f o r m a l s e n t r y =
let ass , r l s = assoc_formals f o r m a l s i n
let ofs = ref 0 in
let labp = L i s t . f o l d _ l e f t
( fun l a b r i −> o f s : = ! o f s − wsize ;
a d d _ i n s t r ( Eget_param ( r i , ! ofs , l a b ) ) )
entry r l s
in
l e t laba = L i s t . f o l d _ r i g h t
( fun ( r i , r d ) l −> a d d _ i n s t r ( Emove ( r i , rd , l ) ) )
ass l a b p
in
l e t labs = L i s t . f o l d _ r i g h t
( fun ( r i , r d ) l −> a d d _ i n s t r ( Emove ( r i , rd , l ) ) )
savers l a b a
in add_instr ( Ealloc_frame labs )
l e t f u n _ e x i t savers r e t r l e x i t =
l e t l a b 1 = a d d _ i n s t r ( Edel_frame ( a d d _ i n s t r E r e t u r n ) ) i n
l e t labs = L i s t . f o l d _ r i g h t
( fun ( r i , r d ) l a b −> a d d _ i n s t r ( Emove ( rd , r i , l a b ) ) )
savers l a b 1
in
l e t l a b e = a d d _ i n s t r ( Emove ( v0 , r e t r , l a b s ) ) i n
a d d _ l a b _ i n s t r l e x i t ( Egoto l a b e )
type d e c l _ f u n =
{ name : s t r i n g ; params : i n t ; e n t r y : l a b e l ; body : graph }
l e t e r t l _ f u n { R t l . name= i d ; R t l . params= l r ; R t l . r e t u r n = r e t ;
R t l . e n t r y = l e n t r y ; R t l . e x i t = l e x i t ; R t l . body=g } =
clear_graph ( ) ; ertl_graph g ;
l e t np = min ( L i s t . l e n g t h l r ) R e g i s t e r . nparams i n
l e t savers = L i s t . map ( fun r −> R e g i s t e r . f r e s h ( ) , r )
( ra : : callee_saved )
in
l e t newentry = f u n _ e n t r y savers l r l e n t r y i n
f u n _ e x i t savers r e t l e x i t ;
{ name= i d ; params=np ; e n t r y =newentry ; body = ! graph }
Définition
Un registre est vivant sur un arc du graphe de flot de contrôle si sa valeur
est utilisée avant d’être redéfinie.
Calcul
Calcul d’une approximation : une variable pourra être déclarée vivante
alors qu’elle n’est pas accédée dans les exécutions.
Localement pour chaque instruction, on connait ce qui est défini et ce qui
est utilisé
Approche en avant :
la sémantique de chaque instruction permet de définir out(i) en fonction de
in(i) (fonction de transfert)
le flot de contrôle permet de définir in(i) en fonction de out(j) pour toutes les
instructions j telles qu’il y a un arc de j à i.
Approche en arrière :
la sémantique de chaque instruction permet de définir in(i) en fonction de
out(i) (fonction de transfert)
le flot de contrôle permet de définir out(i) en fonction de in(j) pour toutes les
instructions j telles qu’il y a un arc de i à j.
Remarques
Une fonction arbitraire peut avoir 0 ou plusieurs points fixes
Typiquement on aura X = X1 × · · · × Xn lorsque l’on a n inconnues, par
exemple les informations in(i) et out(i) pour chaque point de
programme i.
Exemples
X est l’ensemble des parties d’un ensemble A avec l’ordre inclusion.
Les booléens avec false ≤ true
Ensemble D avec deux éléments ⊥ et > et l’ordre ⊥ ≤ d ≤ >.
Théorème Toute fonction F monotone sur X admet un plus petit point fixe.
i=m-1
j=n
a = u1
L1: i=i+1
j=j-1
if i < j goto L2
a = u2
L2: i = u3
if i < j goto L1
B1
i1 :i=m-1
j1 :j=n
a1 :a=u1 in(B1 ) =∅ ∅ ∅
out(B1 )=in(B1 )\{i, j, a}∪{i1 , j1 , a1 } i1 , j1 , a1 i1 , j1 , a1
B2
i2 :i=i+1 in(B2 ) =out(B1 ) ∪ out(B4 ) i1 , j1 , a1 i1 , i3 , j1 , j2 , a1 , a2
j2 :j=j-1 out(B2 )=in(B2 )\{i, j} ∪ {i2 , j2 } i2 , j2 , a1 i2 , j2 , a1 , a2
if i < j goto B4 in(B3 ) =out(B2 ) i2 , j2 , a1 i2 , j2 , a1 , a2
out(B3 )=in(B3 )\{a} ∪ {a2 } i2 , j2 , a2 i2 , j2 , a2
B3
in(B4 ) =out(B3 ) ∪ out(B2 ) i2 , j2 , a1 , a2 i2 , j2 , a1 , a2
a2 :a=u2
out(B4 )=in(B4 )\{i} ∪ {i3 } i3 , j2 , a1 , a2 i3 , j2 , a1 , a2
B4
i3 :i=u3
if i < j goto B2
B1
i=m-1
j=n
a=i*j in(B1 ) =out(B1 )\{i, j, a}∪{m, n} m, n m, n
out(B1 )=in(B2 ) a, i, j a, i, j
B2
i=i+1 in(B2 ) =out(B2 )\{i, j} ∪ {i, j} a, i, j a, i, j
j=j-1 out(B2 )=in(B3 ) ∪ in(B4 ) a, i, j a, i, j
if i < j goto B4 in(B3 ) =out(B3 )\{a} ∪ {j} i, j i, j
out(B3 )=in(B4 ) a, i a, i, j
B3
in(B4 ) =out(B4 )\{i} ∪ {i, a} a, i a, i, j
a=j*j
out(B4 )=in(B2 ) ∪ in(fin) a a, i, j
B4
i=2*i
if i < a goto B2