Scaricare la presentazione
La presentazione è in caricamento. Aspetta per favore
PubblicatoGiorgia Pellegrini Modificato 11 anni fa
1
Dataflow Analysis
2
Tino CortesiTecniche di Analisi di Programmi 2 Dataflow Analysis Il punto di partenza per una dataflow analysis è una rappresentazione del grafo di controllo del programma I nodi di questo grafo possono rappresentare uno o più comandi del programma, e sono in corrispondenza a punti del programma La specifica dellanalisi è data mediante un insieme di equazioni che legano linformazione che si sta analizzando ai punti del programma (ovvero ai nodi del grafo)
3
Tino CortesiTecniche di Analisi di Programmi 3 Quando non è disponibile il grafo di controllo del programma, è necessario premettere alla dataflow analysis una control flow analysis. Linformazione può essere propagata in avanti (forward analysis), come nel caso della parity analysis, oppure allindietro (backward analysis)
4
Tino CortesiTecniche di Analisi di Programmi 4 Control flow graph Ogni istruzione del programma corrisponde ad un nodo del grafo Se il comando a può essere seguito dal comando b, allora nel Control Flow Graph deve esserci un arco dal parte dal nodo che corrisponde ad a ed arriva al nodo che corrisponde a b
5
Tino CortesiTecniche di Analisi di Programmi 5 Esempio [ input n; ] 1 [ m:= 1; ] 2 [ while n>1 do ] 3 [ m:= m * n; ] 4 [ n:= n - 1; ] 5 [ output m; ] 6 input n; m:= 1; n>1; m:= m*n; n:= n-1; output m; 1 2 3 4 5 6
6
Liveness Analysis
7
Tino CortesiTecniche di Analisi di Programmi 7 Liveness Analysis Una delle fasi principali della compilazione è la traduzione del programma in un linguaggio intermedio (IR) con un numero illimitato di temporanei. Questo programma dovrà girare su una macchina con un numero limitato di registri. Due temporanei a e b potranno utilizzare lo stesso registro se a e b non sono mai in uso contemporaneamente Il compilatore ha bisogno di analizzare il programma IR per determinare quali temporanei sono in uso contemporaneamente Diciamo che una variabile è viva (live) se contiene un valore che sarà utilizzato in futuro.
8
Tino CortesiTecniche di Analisi di Programmi 8 a:= 0; b:= a+1; 1 2 c:= c+b; 3 a:= b*2; 4 a<N; 5 return c; 6 a = 0; do{ b= a+1; c+=b; a=b*2; } while (a<N); return c; Esempio
9
Tino CortesiTecniche di Analisi di Programmi 9 Una variabile è live se contiene un valore che sarà utilizzato in futuro. Lanalisi è quindi dal futuro al passato (backward). La variabile b è usata nel comando 4: è live nellarco 3 4 Il comando 3 non assegna nulla a b, quindi b è live anche nellarco 2 3 Il comando 2 assegna un valore a b. Questo significa che il valore di b nellarco 1 2 non è utilizzato da nessuno in futuro Quindi il live range di b è: {2 3, 3 4} a:= 0; b:= a+1; 1 2 c:= c+b; 3 a:= b*2; 4 a<N; 5 return c; 6
10
Tino CortesiTecniche di Analisi di Programmi 10 a è live negli archi 4 5 e 5 2 La variabile a è live nellarco 1 2 a non è live negli archi 2 3 4 Anche se nel nodo 3 la variabile a ha un valore ben definito, questo non sarà più utilizzato finché ad a non sarà assegnato un nuovo valore a:= 0; b:= a+1; 1 2 c:= c+b; 3 a:= b*2; 4 a<N; 5 return c; 6
11
Tino CortesiTecniche di Analisi di Programmi 11 La variabile c è live sin dallinizio di questo programma: potrebbe essere ad esempio un parametro formale c è live in tutti gli archi lanalisi di liveness ci dice anche che se c è una variabile locale, c viene usata senza essere inizializzata (questo può essere utilizzato per generare un messagio di warning) a:= 0; b:= a+1; 1 2 c:= c+b; 3 a:= b*2; 4 a<N; 5 return c; 6
12
Tino CortesiTecniche di Analisi di Programmi 12 Sono sufficienti 2 registri: le variabili a e b non sono mai vive contemporaneamente a:= 0; b:= a+1; 1 2 c:= c+b; 3 a:= b*2; 4 a<N; 5 return c; 6 6 a:= 0; b:= a+1; 1 2 c:= c+b; 3 a:= b*2; 4 a<N; 5 return c;
13
Tino CortesiTecniche di Analisi di Programmi 13 Notazione Un grafo di flusso ha archi uscenti (out- edges), che portano a nodi successori, ed archi entranti (in-edges) che provengono da nodi predecessori. pred[n] e succ[n] denotano, rispettivamente, i nodi predecessori e successori del nodo n. Ad esempio, in questo grafo di flusso: gli out-edges del nodo 5 sono 5 6 e 5 2. gli in-edges del nodo 2 sono 5 2 e 1 2. pred[2]={1,5} a:= 0; b:= a+1; 1 2 c:= c+b; 3 a:= b*2; 4 a<N; 5 return c; 6
14
Tino CortesiTecniche di Analisi di Programmi 14 Notazione Un assegnamento ad una variabile definisce tale variabile Loccorrenza di una variabile nellespressione a destra delloperatore di assegnamento usa tale variabile def[n] è linsieme di variabili che sono definite nel nodo n use[n] è linsieme delle variabili che sono usate nel nodo n Ad esempio, in questo grafo di flusso: def[3]={c} use[3]={b, c} a:= 0; b:= a+1; 1 2 c:= c+b; 3 a:= b*2; 4 a<N; 5 return c; 6
15
Tino CortesiTecniche di Analisi di Programmi 15 Formalizzazione Una variabile è live su un arco se esiste un cammino orientato da tale arco ad un use di quella variabile che non attraversa nessun altro def di quella stessa variabile. Una variabile è live-in in un nodo se è live su ognuno dei suoi in-edges. Una variabile è live-out in un nodo se è live su almeno uno dei suoi out-edges. Ad esempio, in questo grafo di flusso: a è live negli archi 1 2, 4 5 e 5 2 a è live-in nel nodo 2, b non lo è. c è live-out nel nodo 5 a:= 0; b:= a+1; 1 2 c:= c+b; 3 a:= b*2; 4 a<N; 5 return c; 6
16
Tino CortesiTecniche di Analisi di Programmi 16 Calcolare la Liveness Linformazione di liveness (live-in e live-out) si può calcolare nel modo seguente: 1. Se una variabile è in use[n], allora è live-in nel nodo n. Ovvero, se un comando usa una variabile, tale variabile è viva allentrata di quel comando 2. Se una variabile è live-in nel nodo n, allora è live-out per tutti i nodi in pred[n] 3. Se una variabile è live-out nel nodo n, e non appartiene a def[n], allora la variabile è anche live-in nel nodo n. Ovvero, se un comando ha bisogno del valore di a alla fine del comando n, e n non fornisce quel valore, allora il valore di a è necessario anche allentrata di n
17
Tino CortesiTecniche di Analisi di Programmi 17 Dataflow Equations Se indichiamo con in[n] linsieme delle variabili che sono live-in nel nodo n out[n] linsieme delle variabili che sono live-out nel nodo n possiamo esprimere le regole precedenti con due equazioni: 1. in[n] = use[n] U (out[n] - def[n]) 2. out[n] = U { in[m] | m succ[n]}
18
Tino CortesiTecniche di Analisi di Programmi 18 gen LV (p)= use[p] kill LV (p) = def[n] se p è un punto finale LV exit (p)= U { LV entry (q) | q segue p} LV entry (p)= ( LV exit ( p ) \ kill LV (p) ) U gen LV (p) Liveness Analysis (una formalizzazione alternativa)
19
Tino CortesiTecniche di Analisi di Programmi 19 Algoritmo Per ottenere una soluzione alle due equazioni precedenti si può usare il seguente algoritmo: for each n in[n]:={}; out[n]:={} repeat for each n in[n]:=in[n]; out[n]:=out[n] in[n] := use[n] U (out[n] - def[n]) out[n]:= U { in[m] | m succ[n]} until ( per ogni n: in[n]=in[n] && out[n]=out[n])
20
Tino CortesiTecniche di Analisi di Programmi 20 123 usedefinoutinoutinout 1aaa 2abaab ca cb c 3 c b b 4babbaba 5aaaaa c 6cccc for each n in[n]:={}; out[n]:={} repeat for each n in[n]:=in[n]; out[n]:=out[n] in[n] := use[n] U (out[n] - def[n]) out[n]:= U { in[m] | m succ[n]} until ( per ogni n: in[n]=in[n] && out[n]=out[n]) a:= 0; b:= a+1; 1 2 c:= c+b; 3 a:= b*2; 4 a<N; 5 return c; 6
21
Tino CortesiTecniche di Analisi di Programmi 21 345 usedefinoutinoutinout 1aaa cc 2ab b ca cb ca cb c 3 c b b b 4bababa cb ca c 5a 6cccc for each n in[n]:={}; out[n]:={} repeat for each n in[n]:=in[n]; out[n]:=out[n] in[n] := use[n] U (out[n] - def[n]) out[n]:= U { in[m] | m succ[n]} until ( per ogni n: in[n]=in[n] && out[n]=out[n]) a:= 0; b:= a+1; 1 2 c:= c+b; 3 a:= b*2; 4 a<N; 5 return c; 6
22
Tino CortesiTecniche di Analisi di Programmi 22 567 usedefinoutinoutinout 1aca cc c 2ab b ca cb ca cb c 3 c b 4ba a cb ca cb ca c 5a 6cccc for each n in[n]:={}; out[n]:={} repeat for each n in[n]:=in[n]; out[n]:=out[n] in[n] := use[n] U (out[n] - def[n]) out[n]:= U { in[m] | m succ[n]} until ( per ogni n: in[n]=in[n] && out[n]=out[n]) a:= 0; b:= a+1; 1 2 c:= c+b; 3 a:= b*2; 4 a<N; 5 return c; 6
23
Tino CortesiTecniche di Analisi di Programmi 23 Nellesecuzione precedente, bisogna aspettare la prossima iterazione per utilizzare la nuova informazione calcolata sugli in e out. Riordinando in modo opportuno i nodi si ottiene... 123 usedefinoutinoutinout 6cccc 5aca c 4ba b ca cb ca cb c 3 c 2ab a cb ca cb ca c 1a c c c
24
Tino CortesiTecniche di Analisi di Programmi 24 Backward Analysis Dallesempio è chiaro come la Liveness Analysis sia unanalisi di tipo backward: linformazione si propaga dai nodi terminali del grafo al nodo iniziale.
25
Tino CortesiTecniche di Analisi di Programmi 25 Rappresentare insiemi Ci sono due modi per rappresentare efficientemente insiemi di variabili: array di bits se ci sono N variabili nel programma, ogni insieme può essere rappresentato con N bits calcolare lunione di due insiemi equivale alla or dei bits corrispondenti ad ogni posizione efficiente se gli insiemi sono densi liste ordinate un insieme può essere rappresentato come la lista dei suoi elementi, ordinati utilizzando una qualsiasi chiave totalmente ordinata (ad es. il nome della variabile) lunione di due insiemi è il merge delle due liste, eliminando i duplicati efficiente se gli insiemi sono sparsi
26
Tino CortesiTecniche di Analisi di Programmi 26 Time-Complexity Diciamo che un programma ha dimensione N se ha al più N nodi nel grafo di flusso ed ha al più N variabili. Ogni insieme live-in (o live-out) ha al più N elementi Ogni operazione di unione per calcolare live-in e live-out ha complessità O(N) Il ciclo for calcola un numero costante di operazioni di unione per ogni nodo del grafo. Ci sono O(N) nodi. Quindi il ciclo for ha complessità O(N 2 ) for each n in[n]:={}; out[n]:={} repeat for each n in[n]:=in[n]; out[n]:=out[n] in[n] := use[n] U (out[n] - def[n]) out[n]:= U { in[m] | m succ[n]} until ( per ogni n: in[n]=in[n] && out[n]=out[n])
27
Tino CortesiTecniche di Analisi di Programmi 27 Time Complexity Ogni iterazione del ciclo repeat può solo accrescere gli insiemi live-in e live-out (cè monotonia), e gli insiemi non possono crescere indefinitamente: al più ogni insieme contiene tutte le variabili. Quindi ci possono essere al più 2N 2 iterazioni Quindi la complessità dellalgoritmo è al peggio O(N 4 ). Ordinando opportunamente i nodi del grafo, si riduce il numero di iterazioni del ciclo repeat a 2 o 3. Inoltre gli insiemi live-in e live-out sono solitamente sparsi. In pratica, la complessità media varia da O(N) a O(N 2 ). for each n in[n]:={}; out[n]:={} repeat for each n in[n]:=in[n]; out[n]:=out[n] in[n] := use[n] U (out[n] - def[n]) out[n]:= U { in[m] | m succ[n]} until ( per ogni n: in[n]=in[n] && out[n]=out[n])
28
Tino CortesiTecniche di Analisi di Programmi 28 Approssimazione Conservativa 1. in[n] = use[n] U (out[n] - def[n]) 2. out[n] = U { in[m] | m succ[n]} Se d è unaltra variabile non usata in questo frammento di codice, sia X che Y della seguente tabella sono soluzioni delle due equazioni, mentre Z non lo è. XYZ usedefinoutinoutinout 1aca ccdacdca c 2ab b cacdbcda cb 3b cc bcd bb 4bab ca cbcdacdba c 5a acd a c 6cccc
29
Tino CortesiTecniche di Analisi di Programmi 29 Approssimazione Conservativa Come si legge allora la risposta dellanalisi? d è live oppure no? Se la variabile a sarà effettivamente utilizzata in qualche esecuzione del programma quando questa raggiunge il nodo n, allora siamo sicuri che a è nellinsieme live-out del nodo n in tutte le soluzioni del sistema di equazioni. Ma il viceversa non è vero: possiamo calcolare che d è nellinsieme live-out del nodo n, ma ciò non significa che necessariamente il suo valore sarà usato in qualche esecuzione del programma. Approssimazione conservativa nel caso di liveness significa che si può erroneamente derivare che una variabile sia live, ma non si deve mai derivare erroneamente che una variabile sia morta.
30
Tino CortesiTecniche di Analisi di Programmi 30 Soluzione Minima Abbiamo visto che il sistema di equazioni 1. in[n] = use[n] U (out[n] - def[n]) 2. out[n] = U { in[m] | m succ[n]} può avere più di una soluzione (X e Y, ad esempio). Nel nostro caso, X è la soluzione minima, ovvero, ogni soluzione Y è tale che per ogni n: in X [n] in Y [n] Si può dimostrare che lalgoritmo che abbiamo utilizzato calcola sempre la soluzione minima di questo sistema di equazioni.
31
Tino CortesiTecniche di Analisi di Programmi 31 Uso dellanalisi Linformazione di liveness è utilizzata per diversi tipi di ottimizzazioni nei compilatori Dead code elimination ad es. rimozione di un comando che assegna un valore ad una variabile che non viene utilizzata prima di essere riassegnata Code motion ad es. spostamento di un comando che assegna variabili che non vengono utilizzate in una porzione di codice Register Allocation una condizione necessaria perché due variabili a e b possano essere allocate sullo stesso registro è che in nessun punto del programma a e b siano entrambe live
32
Tino CortesiTecniche di Analisi di Programmi 32 Grafo di interferenza Una condizione che impedisce a due variabili a e b di essere allocate sullo stesso registro viene chiamata anche interferenza Ad esempio, se le due variabili sono entrambe live nello stesso nodo del grafo di flusso Ad esempio, se a viene generata da unistruzione che non può accedere al registro r, a ed r interferiscono. Linformazione sullinterferenza di variabili può essere espressa con una matrice, o con un grafo non orientato. Nel nostro esempio: abc ax bx cxx a c b
33
Tino CortesiTecniche di Analisi di Programmi 33 Esercizio Analizzare il flusso del seguente programma: disegnare il grafo di controllo calcolare live-in e live-out di ogni comando costruire il grafo di interferenza 1. m:=0 2. v:=0 3. if (v>=n) goto 15 4. r:=v 5. s:=0 6. if (r<n) goto 9 7. v:= v+1 8. goto 3 9. x:=M[r] 10. s:=s+x 11. if (s<=m) goto 13 12. m:= s 13. r:= r+1 14. goto 6 15. return m
34
Tino CortesiTecniche di Analisi di Programmi 34 Esercizio Verificare, usando la liveness analysis, che è corretto rimuovere il comando y:=1 dal secondo dei seguenti programmi, ma non dal primo y = 1; while (x <= 10) { x = x + 1; y = x; } print(y); y = 1; repeat { x = x + 1; y = x; } until (x > 10); print(y);
35
Tino CortesiTecniche di Analisi di Programmi 35 Esercizio Modificare la live variables analysis per realizzare la faint variables analysis. Una variable è faint (pallida) se è dead o se è solo utilizzata per calcolare variabili che sono faint; in caso contrario è fortemente live. Ad esempio, si consideri il frammento di codice x:=1; y:=3; x:= x-1; y:=2*y; x:= 2; con lassunzione che poi x sia dead. La variabile x è faint dopo il primo, il terzo ed il quinto assegnamento La variabile x è dead dopo il terzo ed il quinto La variabile x è live dopo il primo assegnamento.
36
Tino CortesiTecniche di Analisi di Programmi 36 Esempio a:= 0; b:= a+1; 1 2 c:= c+b; 3 a:= b*2; 4 a<N; 5 return c; 7 d:= b*e; 6 usedefLV in LV out DV in DV out FA in FA out 1aceaceabdbd 2abacebcebdad 3bccbce ad 4babceabceadd 5aabce dd 6bedabceacedbd 7ccabdeabcde
37
Tino CortesiTecniche di Analisi di Programmi 37 Esercizio La copy-propagation analysis determina per ogni punto del programma n se esiste un cammino da un comando di copia, ovvero da un assegnamento del tipo x := y, fino al nodo n, nel quale non ci siano altri assegnamenti alla variabile y. Dare una specifica formale a tale analisi dataflow
38
Tino CortesiTecniche di Analisi di Programmi 38 Esercizio La dominator analysis determina per ogni comando di assegnamento da quali altri assegnamenti esso è dominato. Un assegnamento è dominato da unaltro assegnamento se ogni possibile esecuzione del primo è sempre preceduta da unesecuzione del secondo. Dare una specifica formale a tale analisi dataflow
Presentazioni simili
© 2024 SlidePlayer.it Inc.
All rights reserved.