VO Compilerbau Roderick Bloem, Institut [email protected] fuer Code-Optimierung Softwaretechnologie 2002, F. Wotawa VO Compilerbau Univ.Prof. Dr. Franz Wotawa IICM – Softwaretechnologie [email protected] 1 Ziele/Aufgaben 2002, F. Wotawa 2 Kriterien für Code-Transformation • “Optimierung” des generierten (Zwischen-)Codes (schneller, kleiner) • Tradeoff zwischen Aufwand und Nutzen der Optimierung Most payoff for the least effort • Das Verhalten des Programms muß erhalten bleiben. • Im Durchschnitt muß das transformierte Programm schneller (kleiner) sein. • Die Analyse muß den Aufwand wert sein. D.h. eine Programmanalyse, die zu besseren Transformationen führt aber sehr sehr viel Zeit benötigt, ist unter Umständen keine Option. • Fokus: Zielmaschenunabhängige Code-Optimierung • Optimierung unabhängig von den Input-Werten! • Ziel: Im Durchschnitt bessere Resultate • Techniken: Daten- und Kontrollflußanalyse 2002, F. Wotawa 3 2002, F. Wotawa 4 Verbesserung der Performanz Organisation Compileroptimierung • Dramatische Verbesserungen des Laufzeitverhaltens (von Stunden zu wenigen Sekunden) können nur durch die Verbesserung des Programms auf allen Ebenen erfolgen: • Organisation: front end code optimizer code generator – Verbesserung der Algorithmen und Datenstrukturen (z.B. Insert Sort ersetzen durch Quicksort (N log N anstelle von N 2 )) – Code-Transformationen control-flow analysis – Verwendung von Register und schnelleren (Maschinensprache-) Instruktionen, bzw. Peephole-Transformationen source code front end user can profile program change algorithm transform loops intermediate code compiler can improve loops, procedure calls address calculations 2002, F. Wotawa transformations • Vorteile: code generator target code – Operationen für high-level Konstrukte sind im Zwischencode explizit verfügbar und können somit optimiert werden. compiler can use registers select instructions do peephole transformations – Der Zwischencode ist von der Zielmaschine (relativ) unabhängig. Optimierungen sind für vielen Maschinen (ohne Änderungen) möglich. 5 Beispiel–Quicksort 6 2002, F. Wotawa Three-Address Code – Quicksort void quicksort(int m,int n) { int i,j; int v,x; if (n<=m) return; /* fragment begins here */ i = m-1; j =n; v = a[n]; while (1) { do i = i+1; while (a[i]<v); do j = j-1; while (a[j]>v); if (i>=j) break; x = a[i]; a[i] = a[j]; a[j] = x; } /* fragments ends here */ quicksort(m,j); qicksort(i+1,n); } 2002, F. Wotawa data-flow analysis (1) (2) (3) (4) (5) (6) (7) (8) (9) (10) (11) (12) (13) (14) (15) 7 2002, F. Wotawa i := m-1 j := n t1 := 4*n v := a[t1] i := i+1 t2 := 4*i t3 := a[t2] if t3 < v goto (5) j := j-1 t4 := 4*j t5 := a[t4] if t5 > v goto (9) if i >= j goto (23) t6 := 4 *i x := a[t6] (16) (17) (18) (19) (20) (21) (22) (23) (24) (25) (26) (27) (28) (29) (30) t7 := 4*i t8 := 4*j t9 := a[t8] a[t7] := t9 t10 := 4*j a[10] := x goto (5) t11 := 4 *i x := a[t11] t12 := 4 *j t13 := 4*n t14 := a[t13] a[t12] := t14 t15 := 4*n a[t15] := x 8 Flow Graph – Quicksort Möglichkeiten der Optimierung • Common Subexpression: Eine Expression E, die schon vorher berechnet wurde und deren Werte in der Zwischenzeit nicht verändert wurden. Die Mehrfachberechnung von Ausdrücken kann vermieden werden. Beispiel: Block B5. Aus t8 := 4*j; t9:= a[t8]; a[t8] := x; wird t9 := a[t4]; a[t4] := x; B1 i := m-1 j := n t1 := 4*n v := a[t1] B2 i := i+1 t2 := 4*i t3 := a[t2] if t3 < v goto B2 B3 • Copy Propagation: Einführung von Copy-Statements um gleiche Ausdrücke vereinfachen zu können. j := j-1 t4 := 4*j t5 := a[t4] if t5 > v goto B3 t a := d + e a b := d + e wird zu:b c := d + e c B4 if i >= j goto B6 B5 B6 t6 := 4*i t11 := 4*i x := a[t6] x := a[t11] t7 := 4*i t12 := 4*i t8 := 4*j t13 := 4 *n t9 := a[t8] t14 := a[t13] a[t7] := t9 a[t12] := t14 t10 := 4*j t15 := 4*n a[t10] := x a[t15] := x := := := := d + e t t t goto B2 2002, F. Wotawa 9 Dead-Code Elimination 2002, F. Wotawa 10 Loop Optimization • Eine Variable lebt an einer bestimmten Stelle im Code, wenn ihr Wert danach verwendet werden kann bzw. verwendet wird. • Code wird als DEAD bezeichnet, wenn die berechneten Werte nicht verwendet werden. Dieser Code kann ignoriert werden. • Beispiel: • Code Motion: Verschieben von Code in einen Bereich außerhalb der Schleife. while (i <= limit-2) ... wird ersetzt durch t = limit-2; while (i <= t) .... • Induction Variable Elimination: Entfernung von manchen Induction-Variables durch die Verwendung von anderen Variablen. debug := false ... if (debug) print ... • Reduction in Strength: Ersetzung von teuren Operatoren durch billigere (z.B. Multiplikation durch Addition) Schlagwort: Constant Folding • Copy-Statements können oft entfernt werden, da die Variablen nicht weiter verwendet werden. 2002, F. Wotawa 11 2002, F. Wotawa 12 Tranformiertes Quicksort-Programm Optimization of Basic Blocks • Repräsentiere Basic Block als Directed Acyclic Graph (DAG) B1 • Verwende Graph zur Optimierung i := m-1 j := n t1 := 4*n + v := a[t1] c t2 := 4*i t4 := 4*j B2 a b – Common Subexpression Elimination: c d t2 := t2+4 t3 := a[t2] if t3 < v goto B2 B3 := := := := b a b a + + - c d c d - + a b, d d0 t4 := t4-4 t5 := a[t4] if t5 > v goto B3 c0 DAG: b0 – Dead-Code Eliminiation: Entferne jeden Wurzelknoten aus dem DAG der Variablen hat, die nicht mehr benötigt werden (DEAD variables). B4 if i >= j goto B6 B5 a[t2] := t5 B6 t14 := a[t1] a[t4] := t3 a[t2] := t14 goto B2 a[t1] := t3 13 2002, F. Wotawa Basic Block Optimierung (2) Suche nach Loops • Dominator: Der Knoten d eines Flow Graph dominiert den Knoten n, wenn jeder Pfad vom initialen Knoten zu n durch den Knoten d geht. • Algebraische Äquivalenzen x+0=0+x=x x−0=x x∗1=1∗x=x • Repräsentation aller Dominators durch Dominator Tree. x/1 = x • Reduction in Strength • Feststellung der Loops: x ∗ ∗2 = x ∗ x – Jeder Knoten muß einen einzelnen Eingangsknoten haben (Header). Dieser Entry dominiert alle anderen Knoten des Loops. 2.0 ∗ x = x + x x/2 = x ∗ 0.5 • Constant Folding: Evaluierung von Ausdrücken, die konstant bleiben. Die berechneten Werte werden anstelle der Konstanten verwendet. • Weiter algebraische Transformationen: Assoziativ- u. Kommutativgesetz anwenden, Relationenoperatoren (<,>,..) durch Subtraktion und Tests ersetzen,.. 2002, F. Wotawa 14 2002, F. Wotawa 15 – Es gibt mindestens einen Weg um den Loop zu iterieren. Suche nach Kanten im Flow Graph a → b wo a den Knoten b (Tail) dominiert. Eine solche Kante ist ein Back Edge. 2002, F. Wotawa 16 Natural Loop Berechnung der Dominators Input. A flow graph G with set of nodes N , set of edges E and initial node n0 . Output. The relation dom. 1. D(n0 ) := {n0 } • Gegeben: ein Back Edge n → d. • Der Natural Loop besteht aus d und allen Knoten, die n erreichen ohne durch d zu gehen. d ist der Header. • Algorithmus: procedure insert(m) if m is not in loop then begin loop := loop ∪ {m} push m onto stack end procedure main(n → d) stack := empty loop := {d} insert(n) while stack is not empty do begin pop m, the first element of the stack, off stack for each predecesor p of m do insert(p) end 2. for n ∈ N − {n0 } do D(n) := N ; 3. while changes to any D(n) occure do (a) for n ∈ N − {n0 } do i. D(n) := {n} ∪ ∩p a predecessor n D(p) d is in D(n) iff d dom n. • Inner Loops: Loop, der keine anderen Loop enthält. 2002, F. Wotawa 17 18 2002, F. Wotawa • Definition: Ein Flow Graph ist reducible dann und nur dann, wenn seine Kanten in 2 nicht überschneidente Teile partitioniert werden können und die 2 folgenden Properties gelten: Reducible Flow Graphs 1. Die Vorwärtsknoten des Graphen bilden einen azyklischen Graphen wo jeder Knoten vom Initialknoten erreicht werden kann. 2. Alle Back Edges sind Kanten wo deren Heads deren Tails dominieren. • Beispiel: Der folgende Graph ist nicht reducible. 1 2 2002, F. Wotawa 19 2002, F. Wotawa 3 20