Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern...

106
orlesung, Wintersemester 2009/10 M. Schölzel Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller

Transcript of Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern...

Page 1: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

1

Vorlesung, Wintersemester 2009/10 M. Schölzel

Optimierungstechniken in modernen Compilern

Optimierungstechniken für DSPs und Mikrocontroller

Page 2: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

2Optimierungstechniken in modernen Compilern Grundlagen

Eigenschaften von DSP-Architekturen

Irregulärer Datenpfad: Spezialregister Abhängig von der verwendeten Operation wird ein bestimmtes Register benötigt. Eingeschränkte Form von ILP vorhanden Instruktionsformat erzeugt zusätzliche Einschränkungen Pipeline ist eventuell vorhanden

X-Speicher Y-Speicher

ax ay af mx my mf

ALU

+/-

ALU

ar mr

Page 3: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

3Optimierungstechniken in modernen Compilern Grundlagen

Drei Phasen bei Zielcodeerzeugung

Codeauswahl (CS): Finden einer Abbildung der Zwischencodebefehle auf die

Maschinenbefehle der Zielarchitektur. Registerallokation (RA):

Finden geeigneter Speicherklassen für die Variablen des Zwischencodes.

Ablaufplanung und Bindung (SC): Finden einer geeigneten Ausführungsreihenfolge der Operationen

und einer geeigneten Ausführungseinheit für jede Operation.

Page 4: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

4Optimierungstechniken in modernen Compilern Grundlagen

Problem der Reihenfolge

RA vor SC: RA erzeugt zusätzliche Abhängigkeiten durch die genutzten Register.

SC vor RA: Hoher Registerdruck kann entstehen. Evtl. erforderlicher Spill-Code muss erneut geplant werden:

Ablaufplanung besteht deshalb aus Prepass und Postpass. CS vor SC:

Schlecht parallelisierbarer Code kann entstehen. SC vor CS:

Nicht alle durch die Architektur vorgegebenen Einschränkungen können bei der Parallelisierung beachtet werden. Konsequenz: Code ist schlecht parallelisiert; Ressourcen bleiben ungenutzt.

RA vor CS: Durch Registerzuordnung können gewisse Zieloperationen nicht mehr

genutzt werden, weil sich die Werte in den falschen Registern befinden.

CS vor RA: Einschränkung der Registerallokation, weil Ergebnisse in ganz

bestimmte Register geschrieben werden. Konsequenz kann hoher Registerdruck sein.

Page 5: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

5

Vorlesung, Wintersemester 2009/10 M. Schölzel

Optimierungstechniken für DSPs und Mikrocontroller

Ablaufplanung

Page 6: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

6Optimierungstechniken in modernen Compilern Grundlagen

Klassifizierung von Planungsalgorithmen

Lokal – Planung der Operationen innerhalb eines Basisblocks:

Ressourcenbeschränkt: List-Scheduling Zeitbeschränkt: ASAP, ALAP, Force-Directed-Scheduling

Global – Planung der Operationen über Basisblockgrenzen hinaus:

Azyklisch – Planung der Operationen in schleifenfreiem Code:• Strukturorientiert: Region-based-scheduling, percolation-

scheduling, global-scheduling• Profilorientiert: Trace-Schedling, Superblock-Scheduling,

Hyperblock-Schedling Zyklisch – Planung der Operationen in Schleifen:

• Loop-Unrolling• Modulo-Scheduling

Page 7: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

7Optimierungstechniken in modernen Compilern Grundlagen

Lokale Ablaufplanung

Gegeben ist sequentieller Code für einen Basisblock - z.B. DAG - mit abgeschlossener Registerallokation.

Ziel: Festlegen eines Ausführungszeitpunktes (v) für jede Operation v, so dass keine Datenabhängigkeiten verletzt werden unter Berücksichtigung einer der folgenden zwei grundsätzlichen Nebenbedingungen:

Ressourcenbeschränktes Scheduling (z.B. List-Scheduling): • Gegeben ist eine Menge von Ressourcen.• Schedule darf zu keinem Zeitpunkt mehr Ressourcen erfordern als

vorhanden sind.• Optimierungsziel: Minimierung der Schedulelänge.

Zeitbeschränktes Scheduling (z.B: ASAP, ALAP, Force-Directed-Scheduling):

• Gegeben ist eine Schedulelänge.• Schedule darf die gegebene Schedulelänge nicht überschreiten.• Optimierungsziel: Minimierung des Ressourcenbedarfs.

Page 8: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

8Optimierungstechniken in modernen Compilern Grundlagen

Modellierung der Abhängigkeiten in einem Basisblock durch einen DAG

Totale Ordnung einer Anweisungsfolge im 3-Adress-Code wird zu einer partiellen Ordnung abgeschwächt.

G = (N, E, A, ord, label) sei ein gerichteter azyklischer Graph (DAG):

Knoten repräsentieren Operationen in den 3-Adress-Code-Anweisungen.

Kanten in E repräsentieren durch skalare Variablen entstehenden Flussabhängigkeiten.

Kanten in A repräsentieren durch Speicherzugriffe entstehende Datenabhängigkeiten.

ord : E modelliert die Reihenfolge der eingehenden Kanten (Operanden) eines Knotens. Bei ord(e) < ord(e') ist e linker und e' rechter Operand.

label : N {const k, store, load, write a, read a, | k , a +, ist Operation im 3-Adress-Code} ist eine Beschriftung der Knoten mit Operationen.

Page 9: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

9Optimierungstechniken in modernen Compilern Grundlagen

Konstruktion eines DAGs zu einem Basisblock

Eingabe: Basisblock als Folge von 3-Adress-Code-Anweisungen ir0,…,irn Ausgabe: DAG (N, E, A, ord, label) Algorithmus:

Hilfsfunktionen:

N := , E := , A := , ord := , label := S := // Enthält für die aktuelle Situation bei der Übersetzung für jede Variable // des Zwischencodes u.a. den Knoten im DAG, der ihren Wert berechnetfor i = 0 to n do switch(iri) case "x := y z": TranslateBinStmt(iri); break; case "x := y : TranslateUnaStmt(iri); break; case "x := y" : TranslateCopy(iri); break; case "@x := y" : TranslateStore(iri); break; case "x := @y" : TranslateLoad(iri); break; endodFür jedes (a,n,W) S mit a ist Programmvariable erzeuge Knoten m mit label(m) = write a, N := N {m}, E := E {(n,m)}, A := A {(h,m) | label(h) = read a oder label(h) = load oder label(h) = store}

findVar(var) if (var,n,x) S then return n else return 0 fi

findLabel(label,l,r) if n N mit Beschriftung label und ((l,n) E oder l = 0) und ((r,n) E oder r = 0) then return n else return 0 fi

Page 10: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

10Optimierungstechniken in modernen Compilern Grundlagen

Übersetzung von Kopieranweisungen

TranslateCopy(x := y) if findVar(y) = 0 then Erzeuge Knoten n mit label(n) = read y // passiert nur, wenn y Programmvariable N := N {n} S := S {(y,n,R)} fi l := findVar(y) S := S – {(x,n,k) | n N und k {R,W}) S := S {(x,l,W)}

TranslateConst(x := k) if findLabel(const k,0,0) = 0 then Erzeuge Knoten n mit label(n) = const k N := N {n} fi n := findLabel(const k,0,0) S := S {(x,n,W)}

Page 11: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

11Optimierungstechniken in modernen Compilern Grundlagen

Übersetzung binärer und unärer Operationen

TranslateBinStmt(x := y z) l := findVar(y) r := findVar(z) if n N mit label(n) = und (l,n) E und (r,n) E und not (ord(r,n) < ord(l,n)) then m := n else Erzeuge einen Knoten m mit Beschriftung N := N {m} E := E {(l,m),(r,m)} ord((l,m)) := 0; ord((r,m)) := 0, falls kommutativ, sonst ord((r,m)) := 1 fi S := S – {(x,n,k) | n N und k {R,W}) S := S {(x,m,W)}

TranslateUnaStmt(x := y) l := findVar(y) // immer erfolgreich if findLabel(, l) then m := findLabel(, l) else Erzeuge neuen Knoten m mit label(m) = N := N {m} E := E {(l,m)} fi S := S – {(x,n,k) | n N und k {R,W}) S := S {(x,m,W)}

Page 12: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

12Optimierungstechniken in modernen Compilern Grundlagen

Übersetzung von Speicherzugriffen

TranslateStore(@x := y) l := findVar(x) r := findVar(y) Erzeuge neuen Knoten n mit label(n)=store N := N {n} E := E {(l,n),(r,n)}; ord((l,n)):=0; ord((r,n)):=1; A := A {(k,n) | k N und label(k)=store oder label(k)=load oder label(k) = read a oder label(k) = write a}

TranslateLoad(x := @y) l := findVar(y) Erzeuge neuen Knoten n mit label(n)=load N := N {n} E := E {(l,n)} S := S – {(x,n,k) | n N und k {R,W}) S := S {(x,n,W)} A := A {(k,n) | k N und label(k) = store oder label(k) = write a}

Page 13: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

13Optimierungstechniken in modernen Compilern Grundlagen

Beispiel

Beispiel: a[i] = b[i] + a[j]

t0 := it1 := 4t2 := t1 * t0t3 := &bt4 := t3 + t2t5 := @t4t6 := jt7 := 4t8 := t7 * t6t9 := &at10 := t9 + t8t11 := @t10t12 := t5 + t11t13 := it14 := 4t15 := t14 * t13t16 := &at17 := t16 + t15@t17 := t12

1read i

2const 4

3

(t0,1,W)

S

(t1,2,W)(t2,3,W)

*4

const &b(t3,4,W)

5+

(t4,5,W)

6 load

(t5,6,W)

7read j

(i,1,R)

(t6,7,W)(j,7,R)

(t7,2,W)

8*

(t8,8,W)

9const &a

(t9,9,W)

10+

(t10,10,W)11 load

(t11,11,W)

12+ (t12,12,W)

(t13,1,W)(t14,2,W)(t15,3,W)(t16,9,W)

13+

(t17,13,W)14 store

Page 14: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

14Optimierungstechniken in modernen Compilern Grundlagen

ASAP/ALAP

ASAP (As Soon As Possible) und ALAP (As Late As Possible) liefern keine besonders guten Ergebnisse.

Einsatz eher in der High-Level-Synthese. Können beim ressourcenbeschränkten List-Scheduling

aber zum steuern der Heuristik verwendet werden:0, falls { |( , ) }

( )max{ ( ) ( ) |( , ) }, sonst.

w w v Easap v

asapw delay w w v E

ì Î = Æïïï= íï + Îïïî

max{ ( ) | }, falls { |( , ) }( )

min{ ( ) ( ) |( , ) }, sonst.

asap v v V w v w Ealap v

alapw delay v v w E

ì Î Î = Æïïï= íï - Îïïî

Page 15: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

15Optimierungstechniken in modernen Compilern Grundlagen

Ressourcenmodellierung durch Reservierungstabellen

Reservierungstabelle Tv für jede Operationsart v: Tv R {0,...,l}, wobei R die Menge aller Ressourcen ist. (r,t) Tv bedeutet, dass die Ressource r genau t Takte nach dem

Starten der Operation v benötigt wird. Zu einer Operationsart kann eine Menge von Reservierungstabellen v

(R {0,...,l}) gehören, die eine Ausführung der Operation auf verschiedenen Ressourcen beschreiben.

Globale Reservierungstabelle TG R {0,...,m}, wobei m die maximale Länge des Ablaufplans ist.

Eine Operation der Art v kann zum Zeitpunkt p gestartet werden, falls:

eine Reservierungstabelle Tv v existiert und für alle (r,t) Tv gilt: (r,p+t) TG.

Zu jeder Operationsart v ist durch die Funktion delay(v) festgelegt, wie viele Takte nach dem Starten einer Operation der Art v eine datenabhängige Operation gestartet werden kann.

Page 16: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

16Optimierungstechniken in modernen Compilern Grundlagen

Maschinenmodell für ressourcenbeschränkte Ablaufplanung

Modellierung der Reservierungstabellen: R = {ALU1, ALU2, ALU3, FPU, MMU}. ALU = {{(ALU1,0)}, {(ALU2,0)}, {(ALU3,0)}} delay(ALU) = 1 MUL = {{(ALU1,0), (ALU1,1)}} delay(MUL) = 2 FPU = {{(FPU,0),(FPU,1),(FPU,2)}} delay(FPU) = 3 MMU = {{(MMU,0),(MMU,1)}} delay(MMU) = 2

Registerbank

ALU Speicher

FE/DE

DE/EX

EX/MEM

Ste

ue

rwe

rk

MMUALU

Speicher

Schematischer Aufbau des zugehörigen VLIW Prozessors:

FPUALU

Page 17: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

17Optimierungstechniken in modernen Compilern Grundlagen

Ablaufplan

Gegeben ist ein DAG G = (N, E, A, ord, label), dessen Knotenbeschriftung Operationsarten sind.

A kann auch Datenabhängigkeiten modellieren, die z.B. durch eine abgeschlossene Registerallokation entstehen.

Ein Ablaufplan : N legt für jede Operation einen Startzeitpunkt fest. Der Ablaufplan ist gültig, wenn:

Für alle v N: (v) 0 und Aus (u,v) E A folgt: (v) (u) + delay(label(u)) Es darf keine Ressourcenkonflikte zwischen den Operationen geben.

Länge eines Schedules : length() = max{(v) + delay(label(v)) | v N}

Finden eines Schedules minimaler Länge ist NP-vollständig. List-Scheduling ist eine Heuristik, die in der Praxis sehr gute

Ergebnisse liefert.

Page 18: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

18Optimierungstechniken in modernen Compilern Grundlagen

List-Scheduling-AlgorithmusEingabe: DAG (N, E, A, ord, label) und delayAusgabe: Schedule

maxDelay := max{delay(t) | t };i = 0;ready(0) = {u | vN: (v,u) (EA)};ready(k) = für alle 1 k maxDelay;scheduled = ;

while (scheduled N) do while ein Knoten von aus ready(0) ohne Ressourcenkonflikt zum Zeitpunkt i gestartet werden do Wähle einen Knoten v ready(0) der ohne Konflikt zum Zeitpunkt i starten kann (v) := i; scheduled := scheduled {v}; for each u (N – ready(0) – ... – ready(maxDelay) - scheduled) do if((v,u) (EA) and w N: (w,u) (EA) w scheduled) then ready(delay(v)) := ready(delay(v)) {u} fi od od i = i + 1; for k = 0 to maxDelay-1 do ready(k) := ready(k+1) od; ready(maxDelay) := od

Page 19: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

19Optimierungstechniken in modernen Compilern Grundlagen

Beispiel

Modellierung der Reservierungstabellen: R = {ALU1, ALU2, ALU3, FPU, MMU}. ALU = {{(ALU1,0)}, {(ALU2,0)}, {(ALU3,0)}} delay(ALU) = 1 MUL = {{(ALU1,0), (ALU1,1)}} delay(MUL) = 2 FPU = {{(FPU,0),(FPU,1),(FPU,2)}} delay(FPU) = 3 MMU = {{(MMU,0),(MMU,1)}} delay(MMU) = 2

ALU MUL

ALU

ALU

MUL

ALU

0 1 2

3

4

5

ALU1 ALU2 ALU3 FPU MMU

1 0 2

1

3

4

5

Globale Ressourcentabelle: Ready

0, 1, 2345

5

Page 20: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

20Optimierungstechniken in modernen Compilern Grundlagen

Globales Scheduling

Verschieben von Operationen aus einem Basisblock in einen anderen.

Neben Beachtung der Datenabhängigkeiten auch Beachtung der Steuerflussabhängigkeiten erforderlich:

Alle Operationen, die im ursprünglichen Programm ausgeführt werden, müssen auch im optimierten Programm ausgeführt werden.

Spekulativ ausgeführte Operationen im optimierten Programm, dürfen keine ungewollten Seiteneffekte verursachen.

Page 21: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

21Optimierungstechniken in modernen Compilern Grundlagen

Wiederholung Definitionen

Block x dominiert Block y (x dom y) genau dann im Steuerflussgraphen, wenn jeder Pfad vom Startknoten zum Block y durch Block x führt.

Block x postdominiert Block y (x pdom y) genau dann im Steuerflussgraphen, wenn jeder Pfad vom Block y zum Stoppknoten durch Block x führt.

Block x und Block y sind genau dann steuerflussäquivalent, wenn x dom y und y pdom x.

x

z

y

x dom y und x dom z.

z pdom x und z pdom y.

x und z sind steuerflussäquivalent.

Page 22: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

22Optimierungstechniken in modernen Compilern Grundlagen

Aufwärtsverschiebung von Operationen

Eine Operation u wird aus einem Basisblock s in einen Basisblock d verschoben und d ist Steuerflussvorfahre von s.

Voraussetzung: Es werden keine Datenabhängigkeiten verletzt. Die durch u definierte Variable ist in d nicht lebendig.

Unterscheidung folgender Fälle: s und d sind steuerflussäquivalent:

• Verschiebung ist unproblematisch. d dom s und s nicht pdom d:

• u kann ausgeführt werden, obwohl es nicht ausgeführt werden sollte (spekulkative Ausführung).

• Nur zulässig, wenn u keine Seiteneffekte verursacht.• Nur sinnvoll, wenn u in d "umsonst" ausgeführt werden kann.

d nicht dom s und s pdom d: • Auf allen Pfaden nach s muss an den Positionen, von denen aus d nicht mehr erreicht

werden kann eine Kopie der Operation u eingefügt werden (Korrekturcode). Dabei ist zu beachten:

– Die Operanden der Kopie von u müssen dieselben sein, wie im Block s.– Das Ergebnis von u darf keinen noch benötigten Wert überschreiben.– Das Ergebnis von u wird nicht überschrieben, bevor es den Block s erreicht.

• Einige Ausführungspfade im Programm können langsamer werden.• Nur sinnvoll, wenn die optimierten Pfade häufiger ausgeführt werden als die

verlangsamten Pfade.

Page 23: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

23Optimierungstechniken in modernen Compilern Grundlagen

Warum ändern sich Datenabhängigkeiten?

Code Motion kann Datenabhängigkeiten verändern: In dem Beispiel entsteht eine WAW-Abhängigkeit: x=1 kann nicht vor

x=2 verschoben werden. Außerdem ändert sich der Lebendigkeitsbereich von x: x=1 kann nach

der Transformation nicht in den Block mit x=2 verschoben werden.

...

...

x = 1x = 2

...x = 2

...

x = 1

Page 24: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

24Optimierungstechniken in modernen Compilern Grundlagen

Beispiel

load [R1] R6nopbeqz R6, B3

load [R2] R7nopstore R7 [R3]

load [R4] R8nopadd r8, r8 r8store R8 [R5]

load [R1] R6 || load [R4] R8load [R2] R7beqz R6, B3 || add r8, r8 r8

store R7 [R3]

store R8 [R5]

Ursprünglicher Steuerflussgraph Transformierter Steuerflussgraph

Architektureigenschaften:load hat Latenz von 2; jede andere Operation 1.Zwei Operationen können parallel ausgeführt werden.

Page 25: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

25Optimierungstechniken in modernen Compilern Grundlagen

Abwärtsverschiebung von Operationen

Eine Operation u wird aus einem Basisblock s in einen Basisblock d verschoben und d ist Steuerflussnachfahre von s.

Voraussetzung: Es werden keine Datenabhängigkeiten verletzt.

Unterscheidung folgender Fälle: s und d sind steuerflussäquivalent:

• Verschiebung ist unproblematisch. s nicht dom d und d pdom s:

• u kann ausgeführt werden, obwohl es nicht ausgeführt werden sollte (spekulkative Ausführung).

• Nur zulässig, wenn u keine Seiteneffekte verursacht.• Alternativ: Kopien der Blöcke von s nach d erstellen und nur in die Kopie von d die

Operation u verschieben. s dom d und d nicht pdom s:

• Auf allen Pfaden von s, muss an den Positionen, von denen aus d nicht mehr erreicht werden kann, eine Kopie der Operation u eingefügt werden (Korrekturcode). Dabei ist zu beachten:

– Die Operanden der Kopie von u müssen dieselben sein, wie im Block s.– Das Ergebnis von u darf keinen noch benötigten Wert überschreiben.

• Einige Ausführungspfade im Programm können langsamer werden.• Nur sinnvoll, wenn die optimierten Pfade häufiger ausgeführt werden als die

verlangsamten Pfade.

Page 26: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

26Optimierungstechniken in modernen Compilern Grundlagen

Beispiel

load [R1] R6 || load [R4] R8load [R2] R7beqz R6, B3 || add r8, r8 r8

store R7 [R3]

store R8 [R5]

load [R1] R6 || load [R4] R8load [R2] R7beqz R6, B3 || add r8, r8 r8

store R7 [R3] || store R8 [R5]store R8 [R5]

Anlegen einer Kopie und löschen des leeren Basisblocks.

Page 27: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

27Optimierungstechniken in modernen Compilern Grundlagen

Zusammenfassung Codeverschiebung

Verschiebung zwischen steuerflussäquivalenten Blöcken: Kein Korrekturcode und keine spekulative Ausführung von

Operationen. Aufwärts-/Abwärtsverschiebung von s nach d, wobei s

nicht pdom/dom d: Spekulative Ausführung von Operationen, die auf einigen Pfaden

überflüssigerweise ausgeführt werden. Aufwärts-/Abwärtsverschiebung von s nach d, wobei s

nicht dom/pdom d: Korrekturcode erforderlich. Ausführung auf einigen Pfaden kann

verlangsamt werden. Aufwärts-/Abwärtsverschiebung von s nach d, wobei s

nicht dom/pdom d und s nicht pdom/dom d: Kombination der letzten beiden Fälle mit allen Nachteilen.

Page 28: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

28Optimierungstechniken in modernen Compilern Grundlagen

Region-Based-Scheduling

Voraussetzung: Steuerflussgraph kann hierarchisch aus Regionen aufgebaut werden.

Region-Based-Scheduling unterstützt: Aufwärtsverschiebung von Operationen aus s in

einen steuerflussäquivalenten Basisblock d. Aufwärtsverschiebung von Operationen aus s um

eine Verzweigung zu dominierenden Vorgängerblöcken d; d.h. d dom s und s nicht pdom d.

In beiden Fällen ist kein Korrekturcode erforderlich.

Page 29: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

29Optimierungstechniken in modernen Compilern Grundlagen

Region

Eine Region in einem Steuerflussgraph (N,E) ist ein Subgraph (N',E') für den gilt:

N' N E' E Es existiert ein Knoten h N' mit N' dom(h) Falls von einem Knoten m ein Knoten n N' erreicht werden kann,

ohne dass auf diesem Pfad der Knoten h betreten wird, dann ist m N'.

E' ist die Menge aller Kanten zwischen den Knoten in N', die nicht h als Ziel haben.

Es ergibt sich eine Hierarchie von Regionen in einer Funktion:

die gesamte Funktion ist eine Region, jede Schleife in der Funktion bildet eine eigene Region.

Rücksprungkanten einer Schleife zu ihrem Kopf h werden ignoriert, wodurch der Steuerflussgraph azyklisch wird.

Page 30: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

30Optimierungstechniken in modernen Compilern Grundlagen

Beispiel Region

B1

B2

B3

B5

R2

R1

B7

B1

B2

B3

B5

B6

B4

B7

B1

R2

R3

B7

Page 31: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

31Optimierungstechniken in modernen Compilern Grundlagen

Scheduling-AlgorithmusEingabe: Steuerflussgraph und Liste der RegionenAusgabe: Schedule mit Zuordnung von Operationen zu Basisblöcken

for each Region R, wobei innere Regionen zuerst abgearbeitet werden do Berechne Datenabhängigkeiten zwischen den Operationen for each Basisblock B in R in topologischer Sortierung do // Steuerflussäquivalente Blöcke CE = {x | x R und x ist steuerflussäquivalent mit B} // dominierte Nachfolger DS = {x | x R und b CE: b dom x und bCE: (b,x) E} CB = CE DS t = 0 while nicht alle Operationen aus B sind verplant do CI = Operationen in CB, deren Vorgänger bereits verplant wurden for each u CI in Prioritätsreihenfolge do if u hat keine Ressourcenkonflikte then (u) = (t,B); Aktualisiere Ressourcenverwendung Aktualisiere Datenabhängigkeiten fi od t = t + 1; od odod

Page 32: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

32

Vorlesung, Wintersemester 2009/10 M. Schölzel

Optimierungstechniken für DSPs und Mikrocontroller

Registerallokation

Page 33: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

33Optimierungstechniken in modernen Compilern Grundlagen

Basisblocklokale Registerallokation

Ziel: Abbildung der temporären Variablen eines Zwischencodeprogramms auf eine beschränkte Anzahl von Prozessorregistern.

Klassifizierung der Registerallokation: Lokal: Auf den Basisblock beschränkt. Global: Für Funktionen oder das gesamte Programm.

Vorgehensweise bei der Registerallokation hängt stark von der Zielarchitektur ab:

Register-/Register-Architektur oder Register-/Speicher-Architektur,

2-Adress- oder 3-Adress-Architektur, Universeller Registersatz oder Spezialregistersatz, Flache oder tiefe Registerhierarchie.

Page 34: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

34Optimierungstechniken in modernen Compilern Grundlagen

Verwaltungsstrukturen für die Registerallokation

V ist die Menge aller Variablen im 3-Adress-Code. Registerdeskriptor rd : {0,…,RegNum – 1} (V {w,r}) speichert für jedes

Register die Menge der Variablen, deren Werte sich im Register befinden sowie deren Lese-/Schreibzustand.

Speicherdeskriptor: sd: V speichert für jede im Speicher abgelegte Variable die Speicheradresse (absolut für globale und relativ für lokale Variablen).

Belegungssituationen der Verwaltungsstrukturen: Für jede globale Variable a ist durch sd(a) immer ein Speicherplatz festgelegt. Bei Übersetzung einer Funktion f ist außerdem für jede lokale Variable a in f

durch sd(a) eine relative Adresse festgelegt. Für eine temporäre Variabel existiert

• kein Eintrag in rd oder sd,• nur ein Eintrag in rd oder• nur ein Eintrag in sd oder• ein Eintrag in rd und sd.

Für eine Programmvariable existiert • immer ein Eintrag in sd• möglicherweise auch ein Eintrag in rd; dann befindet sich der aktuelle Wert der

Variablen im Register.

Page 35: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

35Optimierungstechniken in modernen Compilern Grundlagen

Hilfsfunktionen

Hilfsfunktionen für eine Variable v: isLocal(v) = True gdw. der Speicherplatz für v im Stapel ist. addr(v) ist die Adresse des Speicherplatzes von v oder die relative

Adresse, die während des Aufbaus der Symboltabelle festgelegt wurde. getNextFreeLocalAddress(): Liefert die nächste freie relative Adresse

im Stapel getFreeReg(): liefert den Namen eines Registers, in das ein neuer

Wert geschrieben werden kann. getVarInReg(v): Erzeugt den erforderlichen Zielcode, um den Wert

der Variablen v in einem Register bereitzustellen. lockReg(r): Verhindert, dass der Inhalt des Registers r bei

folgenden Registeranforderungen ausgelagert wird. unlockReg(r): Klar setRegDeskr(r,x): Danach gilt (x,w) = rd(r) und für alle i: 1 i

RegNum und i r (x,w) rd(i) und (x,r) rd(i). delete(x,r): Danach gilt: (x,w) rd(r) und (x,r) rd(r). clear(): Löscht Einträge im Speicher- und Registerdeskriptor. saveRegs(): Sichert Register im Speicher, die aktualisierte Werte

von Programmvariablen enthalten.

Page 36: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

36Optimierungstechniken in modernen Compilern Grundlagen

Implementierung von getFreeReg

Eingabe: keineAusgabe: Name eines Registers, dessen Inhalt überschrieben werden kannAlgorithmus getFreeReg:Falls ein i existiert mit 1 i RegNum und rd(i) = dann return iFalls ein i existiert mit 1 i RegNum und für alle (v,x) rd(i) gilt x = r, dann rd(i) := , return iWähle ein s mit 1 s RegNum und s ist nicht gesperrtSpill(s)return s

Eingabe: Registernummer sAusgabe: Zielcode zum Auslagern des RegisterwertesAlgorithmus Spill:for each (v,w) rd(s) do if sd(v) undefiniert then addr = getNextFreeLocalAddr() outCode("mov s,[bp-addr]") sd(v) := addr else if v ist global then outCode("mov s,[sd(v)]") else outCode("mov s,[bp-sd(v)]") fi fiodrd(s) :=

Page 37: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

37Optimierungstechniken in modernen Compilern Grundlagen

Beispiel: getFreeReg

Aufruf: getFreeReg() mit Registerdeskriptor:

Aufruf: getFreeReg() mit Registerdeskriptor:

i rd(i)

(t0,w), (a,r)

(t2,w), (c,r)

0

1

2

(t15,w), (p,r)15…

i rd(i)

(t0,w), (t16,w)

(t1,w), (a,w)

(t2,w), (t18,w)

0

1

2

(t15,w), (t31,w)15…

Rückgabewert:

r1

Erzeugter Spillcode:mov r1,[bp-sd(t1)]mov r1,[sd(a)]

Neuer Registerdeskriptor:

Registerdeskriptor:

Rückgabewert:

r1

Erzeugter Spillcode:Keiner

Neuer Registerdeskriptor:

Registerdeskriptor: i rd(i)

(t0,w), (a,r)

(t2,w), (c,r)

0

1

2

(t15,w), (p,r)15…

i rd(i)

(t0,w), (t16,w)

(t2,w), (t18,w)

0

1

2

(t15,w), (t31,w)15…

Page 38: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

38Optimierungstechniken in modernen Compilern Grundlagen

Übersetzung binärer/unärer Anweisungen

Eingabe: 3-Adress-Code-Anweisung x := y zAusgabe: ZielcodeAlgorithmus:

l := getVarInReg(y); lockReg(l);r := getVarInReg(z); lockReg(r);if isTemp(y) then Delete(y,l); if isTemp(z) then Delete(z,r);t := getFreeReg(x);unlock(l); unlock(r);asmmnem := Assembleropertion für outCode("asmmnem l,r,t");setRegDeskr(t,x)

Eingabe: 3-Adress-Code-Anweisung x := yAusgabe: ZielcodeAlgorithmus:

r := getVarInReg(y); lookReg(r);if isTemp(y) then Delete(y,r);t := getFreeReg();unlook(r);asmmnem := Assembleropertion für outCode("asmmnem r,t");setRegDeskr(t,x)

Page 39: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

39Optimierungstechniken in modernen Compilern Grundlagen

Beispiel

Übersetzung von t20 := t1 + t16; Aufruf von getVarInReg(t1) und getVarInReg(t16):

Aufruf von getFreeReg()

i rd(i)

(t0,w), (a,w)

(t1,w), (b,w)

(t2,w), (c,w)

0

1

2

(t15,w), (p,w)15…

Rückgabewert:

r1 für t1r0 für t16

Erzeugter Spillcode:mov r0,[bp-sd(t0)]mov r0,[sd(a)]mov [bp-sd(t16)],r0

Neuer Registerdeskriptor:i rd(i)

(t16,r)

(t1,w), (b,w)

(t2,w), (c,w)

0

1

2

(t15,w), (p,w)15…

Registerdeskriptor:

locked locked

0

0

0

0

1

1

0

0

i rd(i)

(b,w)

(t2,w), (c,w)

0

1

2

(t15,w), (p,w)15…

locked

1

1

0

0

Registerdeskriptor:

Rückgabewert:

r0

Erzeugter Spillcode:Keiner

i rd(i)

(t20,w)

(b,w)

(t2,w), (c,w)

0

1

2

(t15,w), (p,w)15…

locked

0

0

0

0

Zielcode:add

r1,r0,r0

Neuer Registerdeskriptor:

Page 40: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

40Optimierungstechniken in modernen Compilern Grundlagen

Übersetzung von Labels und Sprunganweisungen

Eingabe: 3-Adress-Code-Anweisung label:Ausgabe: ZielcodeAlgorithmus:

SaveRegs();outCode("label:");Clear();

Eingabe: 3-Adress-Code-Anweisung goto labelAusgabe: ZielcodeAlgorithmus:

SaveRegs();outCode("jmp label");

Eingabe: 3-Adress-Code-Anweisung if x then goto lAusgabe: ZielcodeAlgorithmus:

t := getVarInReg(x);Delete(x,t)SaveRegs();outCode("BNZ t,l");

… a := t7label: t8 := a …

… a := t7 goto label10label9: …

… a := t7 if t8 then goto label20 b := t9 …

Aktualisieren der Werte im Speicher.

Einsprung von verschiedenen Position möglich; Belegung der

Register unklar.

Sprung zu einer Position an der der Registerdeskriptor

gelöscht wird; Aktualisieren der Wert eim Speicher

nötig.

Hier wird die Registerallokation

fortgesetzt.

Sprung zu einer Position an der der Registerdeskriptor

gelöscht wird; Aktualisieren der Wert eim Speicher

nötig.

Fortsetzung der Registeralloka-tion.

Belegung der Register für jede Programmausführung

fest. Kein Sichern erforderlich.

Page 41: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

41Optimierungstechniken in modernen Compilern Grundlagen

Offensichtliche Verbesserungen

Lade-/Speicheranweisungen an jedem Anfang/Ende eines Basisblocks sind erforderlich.

Konseqnenz: Globale Planung der Register erforderlich. CISC-Architekturen werden nur schlecht unterstützt, da

jede 3-Adress-Code-Anweisung nach einem festen Schema übersetzt wird.

Konsequenz: Zielcodeauswahl flexibler gestalten. Anordnung der Zielcodeoperationen ist nur vom

Quelltext und der Übersetzung des Syntaxbaums in 3-Adress-code abhängig

Konsequenz: Bessere Anordnung der Operationen finden, um Verwendung von Prozessorregistern zu minimieren.

Page 42: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

42Optimierungstechniken in modernen Compilern Grundlagen

Integrated Prepass Scheduling

Ausführung der Ablaufplanung vor der Registerallokation. Ablaufplanung mittel List-Scheduling nach zwei

Strategien: CSP: Ablaufplanung die bevorzugt Operationen plant, die keine

Konflikte in der Pipeline verursachen. CSR: Ablaufplanung, die bevorzugt Operationen plant, die den

Registerdruck verringern. Ablaufplanung protokolliert Anzahl der lebendigen Werte

während der Planung mit. Schwellwert minRegs, gibt an, ab wann bevorzugt

Operationen geplant werden, die den Registerdruck verringern:

Solange mehr als minReg Register vorhanden sind, wird mit CSP geplant.

Sobald Anzahl der freien Register unter den Schwellwert minRegs sinkt, wird CSR verwendet.

Page 43: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

43Optimierungstechniken in modernen Compilern Grundlagen

Motivation Globale Registerallokation

Problem der lokalen Registerallokation: Laden/Sichern der Werte von Programmvariablen am Anfang/Ende

von jedem Basisblock. Konsequenz: Überflüssige Lade-/Speicheroperationen.

Lösung: Globale Registerallokation für Programme in 3-Adress-Code-Form:

Halten von Werten in Registern über Basisblockgrenzen hinaus unter Beachtung des Steuerflusses.

Es muss abgesichert sein, dass der Wert einer Variablen, der an verschiedenen Programmpositionen definiert wird, sich immer im gleichen Register befindet.

Modellierung durch ein Graphfärbungsproblem; Lösung durch Heuristik.

Globale Registerallokation für Programme in SSA-Form: Modelliertes Graphfärbungsproblem ist optimal lösbar. Behandlung der -Funktionen erfordert zusätzliche

Kopieroperationen.

Page 44: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

44Optimierungstechniken in modernen Compilern Grundlagen

Modellierung der Globalen Registerallokation durch Graphfärbung

Geeignet für Prozessorarchitekturen mit universellem Registersatz; K sei die Anzahl der Register.

Grundlage ist die Information über die lebendigen Variablen an den Programmpositionen im Steuerflussgraphen.

Sind zwei verschiedene Variablen u und v an derselben Position lebendig, dann können ihre Wert nicht im selben Register gehalten werden.

Modellierung durch einen ungerichteten Graphen (Interferenzgraphen) I = (V,E) :

V ist eine Knotenmenge, wobei jeder Knoten genau eine Variable im Zwischencode repräsentiert.

E {{u,v} | u,v V und u v}, wobei {u,v} E gdw. es existiert eine Programmposition p, an der u und v gemeinsam lebendig sind.

Eine Färbung I : V K des Interferenzgraphen (mit {u,v} E I(u) I(v)) entspricht einer Registerallokation, in der der Wert der Variablen v im Register I(v) gespeichert wird.

Zu jedem ungerichteten Graphen existiert ein Programm, das diesen Graphen als Interferenzgraph besitzt.

Page 45: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

45Optimierungstechniken in modernen Compilern Grundlagen

Beispiel Steuerflussgraph/Interferenzgraph

d := 0a := 1c := 3

f := c

d:= d+1r := 2*ds := 3*ct := r+se := t+5

d:= a+fu := cv := u+1w := v+1e := w

c:= d+3a := e*c

z:= a+d

()(d)(a,d)(a,d,c)

(a,d,c)(a,c,f,d)

(c,d)(c,d)(c,d,r)(d,s,r)(d,t)(d,e)

(a,c,f,d)(c,d)(d,u)(d,v)(d,w)(d,e)

(d,e)(d,c,e)(d,c,a)(a,d)(z)

a d s

f c r

vu

w

t

e

z

Page 46: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

46Optimierungstechniken in modernen Compilern Grundlagen

Färben des Interferenzgraphen

Finden einer Reihenfolge v1,…,vn, in der die Knoten (zusammen mit adjazenten Kanten) aus dem Interferenzgraphen entfernt werden.

Einfügen der Knoten in der Reihenfolge vn,…,v1 und dabei Zuordnung einer Farbe, die verschieden von den Farben der bis dahin wieder eingefügten Nachbarn ist.

Heuristik zum Finden der Reihenfolge: Entferne als nächstes einen Knoten, der weniger als K Nachbarn hat. Dieser Knoten hat beim Einfügen dann auch weniger als K Nachbarn und kann damit sicher

gefärbt werden. Es ergibt sich folgender Algorithmus graphCol:

Eingabe: Interferenzgraph (V',E')Ausgabe: Färbung V := V'; E := E'; i := 1;while es gibt ein v V mit |{{w,u} | {w,u} E und w = v}| < K do vi := v; i := i+1; V := V – {v}; E := E – {{w,u} | {w,u} E und w = v};od := if V then return ;while i > 1 do i := i-1; V := V {vi}; E := E {{vi,w} | {vi,w} E' und w V} (vi) := k, wobei k {0,…,K-1} – {(w) | {vi,w} E}odreturn

Page 47: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

47Optimierungstechniken in modernen Compilern Grundlagen

Beispiel 1

a d s

f c r

vu

w

t

e

I = (V, E), R = {0,1,2,3}

z

v uw t e z s r c f a

a d s

f c r

vu

w

t

e

z

d

Page 48: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

48Optimierungstechniken in modernen Compilern Grundlagen

Spillen

Was, wenn der Interferenzgraph nicht zum leeren Graphen reduziert werden kann?

Falls im Algorithmus graphCol V und kein Knoten mit weniger als |K| Nachbarn existiert, dann Spillentscheidung treffen:

Pessimistische Annahme: Färbung ist nicht möglich, weil die Nachbarn der verbleibenden Knoten mit mindestens K verschiedenen Farben gefärbt werden.

Optimistische Annahme: Färbung ist trotzdem möglich, weil es Nachbarn der verbleibenden Knoten gibt, die mit derselben Farbe gefärbt werden:

R = {0,1}

Page 49: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

49Optimierungstechniken in modernen Compilern Grundlagen

Modifizierter Algorithmus bei optimistischer Strategie

Erst, wenn beim Färben festgestellt wird, dass keine Farbe verfügbar ist, wird eine Spillentscheidung getroffen:

Eingabe: Interferenzgraph (V',E')Ausgabe: Färbung V := V'; E := E'; i := 1;while V do Wähle einen Knoten v V mit |{{w,u} | {w,u} E und w = v}| ist minimal vi := v; i := i+1; V := V – {v}; E := E – {{w,u} | {w,u} E und w = v};od := while i > 1 do i := i-1; V := V {vi}; E := E {{vi,w} | {vi,w} E' und w V} if {0,…,K-1} – {(w) | {vi,w} E} = then return ; (vi) := k, wobei k {0,…,K-1} – {(w) | {vi,w} E}odreturn

Page 50: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

50Optimierungstechniken in modernen Compilern Grundlagen

Beispiel optimistische vs. pessimistische Strategie

a d s

f c r

vu

w

t

e

I = (V, E), R = {0,1,2}

z

v uw t e z s r

a d

f c

v uw t e z s r c f d a

a d

f c

Pessimistische Annahme Optimistische Annahme

Algorithmus graphCol bricht hier ab. Algorithmus graphCol bricht erst hier ab.

Page 51: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

51Optimierungstechniken in modernen Compilern Grundlagen

Auswahl der Spillvariablen

Falls ein Interferenzgraph nicht weiter reduziert werden kann, dann wird aus den verbleibenden Variablen v (Knoten) die ausgewählt, für die

minimal ist.

Dabei sind DefUse(v) alle Programmpositionen, an denen v verwendet/definiert wird. und deepth(p) die Schachtelungstiefe der innersten Schleife, die die Programmposition p enthält.

Mindestend eine Variable zwischen einer Definition und Verwendung von v stirbt.

Vor/nach allen Verwendungen/Definitionen von v wird Spillcode in den Zwischencode eingefügt.

Jede Definition/Verwendung der gespillten Variablen kann einen neuen Namen erhalten.

Dadurch entfallen Kanten im Interferenzgraphen. Interferenzgraph muss neu konstruiert werden. Es können mehrere solcher Iterationen erforderlich sein, bis eine Färbung

des Interferenzgraphen gefunden wird.

( )

( )

( ), wobei ( ) 10

( )deepth p

p DefUse v

spillCost vspillCost v

degv Î

= å

Page 52: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

52Optimierungstechniken in modernen Compilern Grundlagen

Beispiel Spillen

d := 0a := 1c := 3

f := c

d:= d+1r := 2*ds := 3*ct := r+se := t+5

d:= a+fu := cv := u+1w := v+1e := w

c:= d+3a := e*c

z:= a+d

Spillen von d()(d)(a,d)(a,d,c)

(a,d,c)(a,c,f,d)

(c,d)(c,d)(c,d,r)(d,s,r)(d,t)(d,e)

(a,c,f,d)(c,d)(d,u)(d,v)(d,w)(d,e)

(d,e)(d,c,e)(d,c,a)(a,d)(z)

d := 0@&d := da := 1c := 3

f := c

d := @&dd := d+1@&d := dd := @&dr := 2*ds := 3*ct := r+se := t+5

d := a+f@&d := du := cv := u+1w := v+1e := w

d := @&dc:= d+3a := e*c

d := @&dz:= a+d

()(d)()(a)(a,c)

(c)(c,d)(c,d)(c,d)(c,d)(c,r)(s,r)(t)(e)

(a,c,f)(c,d)(c)(u)(v)(w)(e)

(e)(d,e)(c,e)(a,c)

(a)(d)(z)

(a,c)(a,c,f)

Page 53: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

53Optimierungstechniken in modernen Compilern Grundlagen

Interferenzgraph nach Spillen

d := 0@&d := da := 1c := 3

f := c

d := @&dd := d+1@&d := dd := @&dr := 2*ds := 3*ct := r+se := t+5

d := a+f@&d := du := cv := u+1w := v+1e := w

d := @&dc:= d+3a := e*c

d := @&dz:= a+d

()(d)()(a)(a,c)

(c)(c,d)(c,d)(c,d)(c,d)(c,r)(s,r)(t)(e)

(a,c,f)(c,d)(c)(u)(v)(w)(e)

(e)(d,e)(c,e)(a,c)

(a)(d)(z)

(a,c)(a,c,f)

a d s

f c r

vu

w

t

e

z

Page 54: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

54Optimierungstechniken in modernen Compilern Grundlagen

Vollständiger Algorithmus

Interferenzgraphkonstruieren

Interferenzgraphfärben

Spillen

Fertig

3-Adress-Code

3-Adress-Code

nicht erfolgreich

erfolgreich

Page 55: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

55Optimierungstechniken in modernen Compilern Grundlagen

Anwendung der Graphfärbungsmethode auf SSA-Code

Vorgehen wie bisher: Lebendigkeit der SSA-Variablen wird berechnet. Für jede SSA-Variable wird ein Knoten im Interferenzgraphen erzeugt. Eine Kante existiert zwischen zwei Knoten (Variablen), falls diese

gleichzeitig lebendig sind (gilt nicht für Programmpositionen der -Funktionen).

Färbung liefert Registerzuordnung. Vorteil:

Dieselbe Variable v kann auf verschiedene Register abgebildet werden, wenn z.B. eine Definition von v eine Teilmenge der Verwendungen von v dominiert und eine andere Definition eine dazu disjunkte Teilmenge von Verwendungen dominiert.

Problem: Dieser Vorteil führt auch zu folgendem Problem: Unterschiedliche

Färbung verschiedener SSA-Variablen zur selben Variablen möglich. Wie müssen dann -Funktionen behandelt werden, wenn sich der Wert

einer Variablen in verschiedenen Registern befinden kann aber in einem bestimmten Register erwartet wird?

Page 56: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

56Optimierungstechniken in modernen Compilern Grundlagen

Beispiel

Vorteil Problem

a t

b c

def adef bdef t1

use t1

…def cuse ause bdef t2

use t2

use c

a t1

b c

t2

def adef bdef tuse t…def cuse ause bdef tuse tuse c

def a def a

use a

Interferenzgraph besitzt einen Knoten für a.

def a1 def a2

a3 = (a1,a2)use a3

Interferenzgraph besitzt drei verschiedene Knoten für a, die unterschiedlich gefärbt werden können.

(a)(a,b)(a,b,t)(a,b)

(a,b,c)(b,c)(c)(c,t)(c)

(a)(a,b)(a,b,t1)(a,b)

(a,b,c)(b,c)(c)(c,t2)(c)

Page 57: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

57Optimierungstechniken in modernen Compilern Grundlagen

Eliminierung -Funktion - Variante 1

Verschmelzen aller SSA-Variablen v1,…,vn derselben Variablen zur selben Variablen v:

Für jede Variable v:• Es seien v1,…,vn die SSA-Variablen der Variablen v.• N' := {v | vi N}.• E' := {{u,v} | {uj,vi} E}.

Dadurch entsteht der Interferenzgraph (N',E') des nicht SSA-Programms aus dem Interferenzgraphen (N,E) des SSA-Programms.

Problem wird damit auf das ursprüngliche Graphfärbungsproblem zurückgeführt.

a t1

b c

t2

a t

b c

Verschmelzen

Page 58: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

58Optimierungstechniken in modernen Compilern Grundlagen

Eliminierung -Funktion - Variante 2

Behandlung der -Funktionen in einem Block b als Kopieroperation: b habe die Steuerflussvorgänger u und v. Über u erreichen b die Definitionen a11,…,an1 und über v die Definitionen a12,…an2. a13,…an3 seien die Definitionen dieser Variablen in b durch -Funktionen. a11,…,an1, a12,…an2, a13,…an3 wurden Register zugeordnet. Falls b über u betreten wird, müssen die Werte von a11,…,an1 in die Register kopiert

werden, in denen die Werte von a13,…an3 erwartet werden. Falls b über v betreten wird, müssen die Werte von a12,…,an2 in die Register kopiert

werden, in denen die Werte von a13,…an3 erwartet werden. Einfügen der entsprechenden Kopieroperationen am Ende von u und v oder am Beginn von

b.

def a1 def a2

a3 = (a1,a2)use a3

a1

a2 a3

u: v:

b:

load a R0 jump b_left … load a R2 jump b_right …b_left: mov R0 R3 jump b_startb_right: mov R2 R3b_start: …

SteuerflussgraphMögliche Färbung im Interferenzgraphen Zielcode

u:

v:

b:

Page 59: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

59Optimierungstechniken in modernen Compilern Grundlagen

Swap-Problem beim Kopieren Problem:

Alle -Operationen müssen zeitgleich ausgeführt werden. Kopieroperationen generieren eine Permutation der Registerinhalte.

Implementierungsvarianten: xchg-Operation verwenden, falls auf der Architektur vorhanden. Emulation der xchg-Operation durch xor-Operationen:

• Werte a und b in Registern x und y:• x := x xor y • y := y xor x == a • x := x xor y == b

Vertauschung unter Zuhilfenahme eines zusätzlichen Registers, falls vorhanden.

def a1

def b1

def a2

def b2

a3 = (a1,a2)b3 = (b1,b2)

u: v:

b:

a1 und a2 R0

b1 und b2 R1a3 R1b3 R0

SteuerflussgraphMögliche

Registerzuordnung

b_left: b_right: mov R0 R1 mov R1 R0b_start: …

Falscher Zielcode

b_left: b_right: xchg R0,R1b_start: …

Richtiger Zielcode

Page 60: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

60Optimierungstechniken in modernen Compilern Grundlagen

Färbung des Interferenzgraphen eines SSA-Programms

Erweiterung der Relation dom auf die Anweisungen an allen Programmpositionen (i,j) und (i',j') im Programm:

(i,j) dom (i',j') gdw. (i i' und i dom i') oder (i = i' und j j'). Weitere Voraussetzung: Initialisierte Variablen. Es ergeben sich dann für SSA-Programme folgende

Eigenschaften: Jede Verwendung einer Variablen v bei (i',j') wird von der

Definition von v bei (i,j) = Dv dominiert. Wenn zwei Variablen u und v an derselben Programmposition

lebendig sind, dann gilt entweder Du dom Dv oder Dv dom Du. Wenn u und v an derselben Programmposition lebendig sind

und Dv dom Du, dann ist v bei Du lebendig. In einem Interferenzgraphen zu einem SSA-Programm

gilt damit: Für jede Clique {v1,…,vn} im Interferenzgraphen existiert eine

Programmposition, an der alle Variablen v1,…,vn lebendig sind.

Page 61: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

61Optimierungstechniken in modernen Compilern Grundlagen

Finden einer optimalen Färbung des Graphen

Idee: Eliminiere einen Knoten, für den gilt, dass alle seine Nachbarn eine Clique bilden.

Beim Einfügen dieses Knotens sind dann alle Nachbarn verschieden gefärbt und die Anzahl der benötigten Farben ist durch die Größe der maximalen Clique bestimmt.

Wieso kann so ein Knoten im Interferenzgraphen immer gefunden werden?

Es sei (a,b) E und (b,c) E und (a,c) E. Wenn Da dom Db, dann Db dom Dc.

Wenn ein Knoten v aus dem Graphen entfernt wird, dann sind alle Variablen, deren Definitionen durch die Definition von v dominiert wird, bereits entfernt worden. Unter dieser Voraussetzung bilden alle mit Knoten v adjazenten Knoten eine Clique.

Die Reihenfolge, in der die Knoten aus dem Interferenzgraphen zu entfernen sind, erhält man durch die Post-Order-Linearisierung des Dominatorbaums.

Page 62: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

62Optimierungstechniken in modernen Compilern Grundlagen

Beispiel - Interferenzgraph

d0 := 0a0 := 1c0 := 3

d1 := (d0,d4)a1 := (a0,a2)c1 := (c0,c2)f0 := c1

d2:= d1+1r0 := 2*d2

s0 := 3*c1

t0 := r0+s0

e0 := t0+5

d3:= a1+f0

u0 := c1

v0 := u0+1w0 := v0+1e1 := v0

d4 := (d2,d3)e2 := (e0,e1)c2:= d4+3a2 := e2*c2

z0:= a2+d4

()(d0)(a0,d0)(a0,d0,c

0)

(a1,c1,d1)(a1,c1,f0,d

1)

(d1,c1)(c1,d2)(c1,d2,r0

)(d2,s0,r0

)(d2,t0)(d2,e0)

(c1,a1,f0)(c1,d3)(d3,u0)(d3,v0)(d3,w0)(d3,e1)

(d4,e2)(d4,e2,c2)(d4,c2,a2)

(a2,d4)(z0)

a1 d1

f0 c1

u0 e1 z0

a0 d0

c0

r0d2

s0

e0t0d3

v0 w0

a2 d4

c2

e2

Page 63: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

63Optimierungstechniken in modernen Compilern Grundlagen

Beispiel - Dominatorbaum

d0 := 0a0 := 1c0 := 3

d1 := (d0,d4)a1 := (a0,a2)c1 := (c0,c2)f0 := c1

d2:= d1+1r0 := 2*d2

s0 := 3*c1

t0 := r0+s0

e0 := t0+5

d3:= a1+f0

u0 := c1

v0 := u0+1w0 := v0+1e1 := v0

d4 := (d2,d3)e2 := (e0,e1)c2:= d4+3a2 := e2*c2

z0:= a2+d4

(d0)(a0,d0)(a0,d0,c0)

(a1,c1,f0,d1)

(c1,d2)(c1,d2,r0)(d2,s0,r0)(d2,t0)(d2,e0)

(c1,d3)(d3,u0)(d3,v0)(d3,w0)(d3,e1)

(d4,e2,c2)(d4,c2,a2)

(z0)

a0

d0

c0

a1

d1

c1

f0

r0

d2

s0

e0

t0

u0

d3

v0

e1

w0

e2

d4

c2

z0

a2

Page 64: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

64Optimierungstechniken in modernen Compilern Grundlagen

Finden der optimalen Färbung

Reihenfolge zum Entfernen der Knoten aus dem Interferenzgraphen ist die Postfixlinearisierung lrpost(t) des Dominatorbaums t, die durch einen Links-Rechts-Tiefendurchlauf in t berechnet wird.

Offenbar wird ein Knoten immer dann entfernt, wenn alle Knoten, die durch ihn dominiert werden bereits entfernt wurden.

Einfügen und Färben der Knoten in der Reihenfolge lrpost(t).

Einfacher: Färben der Knoten in der Reihenfolge lrpost(t) = rlpre(t), wobei rlpre(t) Präfixlinearisierung nach einen Rechts-Links-Tiefendurchlauf ist.

Page 65: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

65Optimierungstechniken in modernen Compilern Grundlagen

Beispiel - Färbung

a1 d1

f0 c1

u0 e1 z0

a0 d0

c0

r0d2

s0

e0t0d3

v0 w0

a2 d4

c2

a0

d0

c0

a1

d1

c1

f0

r0

d2

s0

e0

t0

u0

d3

v0

e1

w0

e2

d4

c2

z0

a2

e2

Page 66: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

66Optimierungstechniken in modernen Compilern Grundlagen

Spillen in SSA-Code

1. Strategie: Spillen eines Knotens wie bisher mit Einfügen von Speicher- und

Ladecode. Neukonstruktion des Interferenzgraphen wird erforderlich. Falls der Zwischencode nicht in SSA-Code umgeformt wird, kann die

Eigenschaft der optimalen Färbbarkeit verloren gehen. 2. Strategie:

Cliquen im Interferenzgraphen korrespondieren mit gleichzeitig lebendigen Variablen im SSA-Code

Durch maximale Clique ist die Anzahl der benötigten Farben festgelegt. Spillen wird durchgeführt, bevor der Interferenzgraph aufgebaut wird. Finden der gleichzeitig lebendigen Variablen ist einfach. Damit ergibt sich folgender vollständiger Algorithmus:

Interferenzgraphkonstruieren

Interferenzgraphfärben

Spillen Fertig3-

Adress-Code

Page 67: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

67

Vorlesung, Wintersemester 2009/10 M. Schölzel

Optimierungstechniken für DSPs und Mikrocontroller

Codeauswahl

Page 68: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

68Optimierungstechniken in modernen Compilern Grundlagen

Instruktionsauswahl in Basisblöcken

Problem (bereits bekannt): Einfache Zielcodeerzeugung nutzt feste

Übrsetzungsschemata für jede Zwischencodeanweiung.

Unzureichend für Architekturen mit komplexen Befehlssätzen und vielen Adressierungsmöglichkeiten.

Lösung: Code-Selektion durch Berechnung einer Überdeckung

Transformation des 3-Adress-Codes in einen gerichteten azyklischen Graphen (DAG).

Zerlegung des DAG in Bäume. Berechnung einer Überdeckung der Bäume. Zu der berechneten Überdeckung wird eine Sequenz

von Instruktionen der Zielarchitektur generiert.

Page 69: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

69Optimierungstechniken in modernen Compilern Grundlagen

Zerlegung eines DAGs in Bäume

Für jeden Baum der Zerlegung soll gelten: Nur der Wert der Wurzel darf mehrfach benutzt

werden Vorgehen:

Wähle einen Knoten n im DAG ohne Vorgänger: T = {n}

Solange es in T einen Knoten m gibt, für den gilt: (m,n)EDAG und m T und n einziger Nachfolger von m oder (n,m)E und m T und m einziger Nachfolger von n: T := T {m}

Berechne den Wert der Wurzel von T in eine neue Variable newV.

Ersetze im DAG jede Verwendung v der Wurzel von T durch einen Knoten nv mit Beschriftung read newV.

Mi C4

* Cb

+

ld

Mj

* Ca

+

ld

+

+

st

C4

Mn

T1:

Page 70: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

70Optimierungstechniken in modernen Compilern Grundlagen

Zerlegung eines DAGs in Bäume

Für jeden Baum der Zerlegung soll gelten: Nur der Wert der Wurzel darf mehrfach benutzt

werden Vorgehen:

Wähle einen Knoten n im DAG ohne Vorgänger: T = {n}

Solange es in T einen Knoten m gibt, für den gilt: (m,n)EDAG und m T und n einziger Nachfolger von m oder (n,m)E und m T und m einziger Nachfolger von n: T := T {m}

Berechne den Wert der Wurzel von T in eine neue Variable newV.

Ersetze im DAG jede Verwendung v der Wurzel von T durch einen Knoten nv mit Beschriftung read newV.

Mi Mn

* Cb

+

ld

Mj

* Ca

+

ld

+

+

st

C4

Mn

T1:

Mn

Mi Mn

*

T2:

Mm

Page 71: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

71Optimierungstechniken in modernen Compilern Grundlagen

Zerlegung eines DAGs in Bäume

Für jeden Baum der Zerlegung soll gelten: Nur der Wert der Wurzel darf mehrfach benutzt

werden Vorgehen:

Wähle einen Knoten n im DAG ohne Vorgänger: T = {n}

Solange es in T einen Knoten m gibt, für den gilt: (m,n)EDAG und m T und n einziger Nachfolger von m oder (n,m)E und m T und m einziger Nachfolger von n: T := T {m}

Berechne den Wert der Wurzel von T in eine neue Variable newV.

Ersetze im DAG jede Verwendung v der Wurzel von T durch einen Knoten nv mit Beschriftung read newV.

MmCb

+

ld

Mj

* Ca

+

ld

+

+

st

C4

Mn

T1:

Mn

Mi Mn

*

T2:

Mm

Mm

Page 72: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

72Optimierungstechniken in modernen Compilern Grundlagen

Zerlegung eines DAGs in Bäume

Für jeden Baum der Zerlegung soll gelten: Nur der Wert der Wurzel darf mehrfach benutzt

werden Vorgehen:

Wähle einen Knoten n im DAG ohne Vorgänger: T = {n}

Solange es in T einen Knoten m gibt, für den gilt: (m,n)EDAG und m T und n einziger Nachfolger von m oder (n,m)E und m T und m einziger Nachfolger von n: T := T {m}

Berechne den Wert der Wurzel von T in eine neue Variable newV.

Ersetze im DAG jede Verwendung v der Wurzel von T durch einen Knoten nv mit Beschriftung read newV.

MmCb

+

ld

Mj

*Ca

+

ld

+

+

st

C4

Mn

T1:

Mn

Mi Mn

*

T2:

Mm

Mm Ca

T3:

Page 73: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

73Optimierungstechniken in modernen Compilern Grundlagen

Prinzip Code-Selektion

Cb

+

ld

+

ld

+

Mi CaMj

R1

ld

+

ld

+

CaMj

R1

ld ld

+

R2

R1 ld

+

R2

R1

Zielcode:mov Rz,yadd rz,[x]

mov r1,badd r1,[i]

Cy

+

Mx

Rz

Rx

ld

Ry

Rx ld

+

Ry

Rx

Zielcode:mov Ry,[Rx]

Zielcode:add Rx,[Ry]

mov r2,aadd r2,[j]

mov r1,[r1]

add r1,[r2]

Ersetzungsregeln: Zielcode:

Ausdrucksbaum:

Page 74: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

74Optimierungstechniken in modernen Compilern Grundlagen

Ersetzungsregeln

S ist eine Menge von Speicherklassen: Im Folgenden oft S = {M, R, C}, wobei M – Speicher, R – Register, C –

Konstante . Op ist die Menge der Operatoren mit denen Knoten im DAG

beschriftet sein können. (V,l,r,,,z) ist eine Ersetzungsregel, wobei:

V ist eine Variablenmenge, die in der Ersetzungsregel verwendet wird, l ist ein geordneter Baum (Muster genannt), : l S Op ist eine Beschriftung der Knoten des Baums, wobei die

Blätter mit Speicherklassen beschriftet sind und die inneren Knoten mit Operatoren,

: Leaves(l) V ist eine Beschriftung der Blätter in l, wobei Leaves(x) = { | x und i: .i x}

r = (m,v) ist die Ersetzung für l, wobei m S und v V z ( V)* ist die Schablone für den zu erzeugenden Zielcode.

Die Menge aller Ersetzungsregeln wird mit bezeichnet. Jeder Ersetzungsregel g können Kosten cost(g) zugeordnet sein.

Page 75: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

75Optimierungstechniken in modernen Compilern Grundlagen

Wann passt ein Muster?

In einem Ausdrucksbaum T mit Beschriftungsfunktion : T S Op passt ein Muster l aus der Ersetzungsregel g = (V,l,r,,,z) am Knoten n, falls:

T/n = l und Für alle Knoten b T/n gilt: (b) = (b)

Cb

+

ld

+

ld

+

Mi CaMj

Cy

+

Mx

Rz

Page 76: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

76Optimierungstechniken in modernen Compilern Grundlagen

Ersetzung eines Musters

Falls das Muster l aus der Ersetzungsregel g = (V,l,r,,,z) an einem Knoten n passt, dann kann in T der Baum T/n durch den Knoten n ersetzt werden, dessen Beschriftung aus r hervorgeht, wodurch ein Baum T' entsteht, für den gilt:

T' = T – (T/n) {n}, (T' – {n}): '() = () und attr'() = attr() Die Variable (b) an jedem Blatt b in l wird an den Attributwert des Blattes b in T/n

angepasst: val((b)) = attr(b) (attr ist der Index in der Knotenbeschriftung). '(n) = m und attr'(n) = val(v), wobei r = (m,v) Der Zielcode wird erzeugt, indem z als Zielcode ausgegeben wird und jede

Variable v in z durch val(v) ersetzt wird.

Cb

+

ld

+

ld

+

Mi CaMjCy

+

Mx

Rz

Zielcodeschablone:mov Rz,yadd rz,[x]

Variablenanpassung:val(x) = ival(y) = bval(z) = getFreeReg()

R0

Zielcode:mov R0,badd R0,[i]

Page 77: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

77Optimierungstechniken in modernen Compilern Grundlagen

Greedy-Algorithmus

Annahme: Es stehen genügend Prozessorregister zur Auswertung des Ausdrucks zur Verfügung.

Unter Verwendung eines Greedy-Algorithmus kann ein gegebener Ausdrucksbaum durch wiederholte Ersetzung zu einem Knoten reduziert werden.

Vorgehen: Suche ein Muster maximaler Größe (z.B. |l| ist maximal), das an

einem Knoten n passt. Führe eine Ersetzung am Knoten n aus. Wiederhole diese Schritte solange, bis der Baum zu einem

Knoten reduziert wurde. Leicht implementierbar, liefert aber nicht immer

optimale Ergebnisse.

Page 78: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

78Optimierungstechniken in modernen Compilern Grundlagen

Probleme

Was, wenn mehrere Ersetzungsregeln passen? In welcher Reihenfolge sollen Ersetzungen vorgenommen

werden? Effizienz des Zielcodes kann davon abhängen. Verhindern, dass Sackgassen entstehen:

Für jeden einzelnen Knoten im Ausdrucksbaum, der mit einem Operator markiert ist, muss eine Ersetzungsregel existieren.

Es gibt genug Prozessorregister, um jeden dieser Knoten zu übersetzen

Verhindern, dass unendliche Ersetzungen entstehen: Ersetzungsregeln verkleinern den Baum Ersetzungsregeln, die einen Knoten in denselben Knoten

überführen ersetzen die Beschriftung (Speicherort), wobei es eine Ordnung für die Ersetzung der Speicherorte gibt.

Greedy-Algorithmus optimiert nicht die Kosten.

Page 79: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

79Optimierungstechniken in modernen Compilern Grundlagen

Optimale Zielcodeerzeugung für Ausdrucksbäume

Voraussetzung: Zielprozessor ist eine Load/Store-Architektur.

Ershov Nummerierung: Jeder Knoten ist mit der Anzahl der Register beschriftet,

die benötigt werden, um den Wert des Knotens zu berechnen, ohne einen Wert in den Speicher auszulagern.

Berechnung durch:• Jedes Blatt, das mit M beschriftet ist erhält eine 1• Jedes Blatt, das mit C oder R beschriftet ist, erhält eine 1• Jeder innere Knoten mit genau einem Sohn erhält die Nummer

seines Sohns• Jeder innere Knoten mit zwei Söhnen erhält die Nummer i, falls

– beide Söhne verschiedene Nummer m und k haben und i = max(m,k)

– beide Söhne die gleiche Nummer k haben und i = k+1

Page 80: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

80Optimierungstechniken in modernen Compilern Grundlagen

Beispiel Ershov-Nummerierung

t1 = a – bt2 = c + dt3 = e * t2t4 = t1 + t3

-

a b +

c d

*

e

+

1 1 1

1 1

2

2 2

3

Zwischencodefragment Nummerierter Ausdrucksbaum

Page 81: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

81Optimierungstechniken in modernen Compilern Grundlagen

Zielcodeerzeugung für Ausdrucksbäume

Eingabe: Ausdrucksbaum mit Ershov-Nummerierung. Ausgabe: Optimale Zielcodesequenz, um die Wurzel in ein Register zu berechnen. Prinzip: genCode(n,b) generiert Code zur Berechnung des Werts des Knotens n mit

Ershov-Nummer k in Register b+k-1 unter Verwendung der Register b,…b+k-1. Beginne mit genCode(n,0), wobei n die Wurzel des Ausdrucksbaums ist. Arbeitsweise von genCode(n,b):

n ist innerer Knoten mit Ershov-Nummer k, dessen zwei Söhne Ershov-Nummer k-1 haben:• Generiere Code für den linken Sohn von n zur Basis b+1; Ergebnis wird in Register b+k-1

berechnet.• Generiere Code für den rechten Sohn zur Basis b; Ergebnis wird in Register b+k-2 berechnet.• Generiere Code für n mit Beschriftung op: op Rb+k-1,Rb+k-2,Rb+k-1

n ist innerer Knoten mit Ershov-Nummer k, dessen zwei Söhne Ershov-Nummern k und m < k haben:

• Generiere Code für den Sohn mit Ershov-Nummer k zur Basis b; Ergebnis wird in Register b+k-1 berechnet.

• Generiere Code für den Sohn mit Ershov-Nummer m zur Basis b; Ergebnis wird in Register b+m-1 berechnet.

• Generiere Code für n: op Rb+k-1,Rb+m-1,Rb+k-1 oder op Rb+m-1,Rb+k-1,Rb+k-1 n ist inneren Knoten mit Ershov-Nummer k, der genau einen Sohn (mit Ershov-Nummer k)

hat:• Generiere Code für den Sohn zur Basis b• Generiere Code für n mit Beschriftung op: op Rb+k-1,Rb+k-1

n ist ein Blatt: Load Rb,x oder Const Rb,x

Page 82: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

82Optimierungstechniken in modernen Compilern Grundlagen

Beispiel

-

a b +

c d

*

e

+

1 1 1

1 1

2

2 2

3b=0

b=1 b=0

b=2 b=1 b=0

b=0

b=1 b=0

Load R2,a

Load R1,b

Sub R2,R1,R2

Load R1,c

Load R0,d

Add R1,R0,R1

Load R0,e

Mul R0,R1,R1

Add R2,R1,R2

Ausdrucksbaum Zielcodesequenz

Page 83: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

83Optimierungstechniken in modernen Compilern Grundlagen

Einfügen von Spill-Code

Eingabe: Ausdrucksbaum mit Ershov-Nummerierung. Ausgabe: Optimale Zielcodesequenz, um die Wurzel unter Verwendung von

maximal r Registern in ein Zielregister zu berechnen. Prinzip: Arbeitsweise wie bisher, falls Ershov-Nummer eines Knotens n höchstens r

ist. Sonst berechne die Ergebnisse der Söhne von n in den Speicher und das Ergebnis von n nach Rr-1

Beginne mit genCode(n,0), wobei n die Wurzel des Ausdrucksbaums ist. Arbeitsweise von genCode(n,b) für Knoten mit Ershov-Nummer k > r:

n ist innerer Knoten mit Ershov-Nummer k, dessen zwei Söhne Ershov-Nummern k und m < k haben:

• Generiere Code für den Sohn mit Ershov-Nummer k zur Basis b = 0; Ergebnis wird in Register r-1 berechnet.

• Generiere Zielcode Store Rr-1,newT, wobei newT eine neue Variable ist.• Generiere Code für den Sohn mit Ershov-Nummer m

– Falls m r, dann generiere Code zur Basis b = r – m; Ergebnis wird in Register r-1 berechnet.– Falls r < m, dann generiere Code zur Basis b = 0; Ergebnis wird in Register r-1 berechnet.

• Generiere die Instruktion Load newT,Rr-2

• Generiere Code für n: op Rr-2,Rr-1,Rr-1 oder op Rr-1,Rr-2,Rr-1 n ist innerer Knoten mit Ershov-Nummer k, dessen zwei Söhne Ershov-Nummer k-1 haben:

• Vorgehen ist wie im vorigen Fall, wobei o.B.d.A. der linke Sohn als Knoten mit Ershov-Nummer m behandelt wird.

n ist innerer Knoten mit Ershov-Nummer k, der genau einen Sohn (mit Ershov-Nummer k) hat:

• Generiere Code für den Sohn zur Basis b = 1; Ergebnis wird in Register r berechnet.• Generiere Code für n mit Beschriftung op: op Rr,Rr

Page 84: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

84Optimierungstechniken in modernen Compilern Grundlagen

Beispiel

-

a b +

c d

*

e

+

1 1 1

1 1

2

2 2

3b=0

b=0 b=0

b=1 b=0 b=0

b=0

b=1 b=0

Load R1,a

Load R0,b

Sub R1,R0,R1

Load R1,c

Load R0,d

Add R1,R0,R1

Load R0,e

Mul R0,R1,R1

Sub R1,R0,R1

Ausdrucksbaum Zielcodesequenz für r = 2

Store R1,newT

Load newT,R0

Page 85: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

85Optimierungstechniken in modernen Compilern Grundlagen

Finden einer kostenoptimalen Überdeckung durch dynamische Programmierung

Gegeben ist ein Ausdrucksbaum T und ein Ersetzungssystem

Bestimme alle Werte, die in den Speicher berechnet werden sollen und führe diese Berechnungen zuerst aus.

Damit dürfen zur Berechnung jedes dieser Werte alle Register verwendet werden.

3 Phasen: Berechne Bottom-Up für jeden Knoten n von T die minimalen

Kosten Cn[i] die entstehen und die zugehörige Ersetzungsregel, wenn der Wert des Baums mit Wurzel n:

• in den Speicher berechnet wird (i = 0)• in ein Register berechnet wird und i Register (1 i) für die Berechnung

verfügbar sind. Tiefendurchlauf durch T, um festzustellen, die Werte welcher

Knoten in den Speicher berechnet werden müssen. Alle Bäume traversieren (zuerst die, deren Ergebnis in den

Speicher berechnet wird), um den zugehörigen Zielcode zu erzeugen.

Page 86: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

86Optimierungstechniken in modernen Compilern Grundlagen

Details Phase 1Eingabe: Knoten n Cm, Rm für jeden Nachfahren m von nAusgabe: Cn…Kosten für Knoten n Mn …Verwendete Muster am Knoten nAlgorithmus:for(i = 1; i maxRegs; i++) do Cn[i] = ; for each r das an Knoten n passt do m1,…,mz seien die Nachfahren von n, die mit den Blättern in r matchen und als Speicherklasse M haben. r1,…,rk seien die Nachfahren von n, die mit den Blättern in r matchen und als Speicherklasse R haben. costr = cost(r)

// Kosten des Musters r selbst for(j = 1; j <= z; j++) do costr = costr + Cmj

[0]; od

costmin = ; for each p1,…,pk wobei p1,…,pk eine Permutation der Blätter r1,…,rk ist do costreg = 0; for(j = 1; j <= k; j++) do costreg = costreg + Cpj

[i-(j-1)]

od costmin = min(costmin,costreg); fi od if(Cn[i] > costr + costmin) then Cn[i] = costr + costmin; Mn[i] = r; fi odod

Page 87: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

87Optimierungstechniken in modernen Compilern Grundlagen

Beispiel Phase 1

-

Ma Mb +

Mc Md

*

Me

+

Ry

op

Rx

Rx

Mx Ry load [x],Ry

op Rx,Ry,Rx

My

op

Rx

Rx op Rx,[y],Rx

Rx My store Rx,[y]

Ry

op

Rx

Mzop Rx,Ry,Rxstore Rx,[z]

My

op

Rx

Mz op Rx,[y],Rxstore Rx,[z]

Passende Muster für Knoten 0 bis 5:

0 1

3 4

25

6 7

8

Muster Gesamtkosten Verfügbare Register

1 1 1

1 1 2

keins 0 alle, Ziel Speicher

1:

2:

3:

4:

5:

6:

C0 = [0,1,1] C1 = [0,1,1]

C3 = [0,1,1] C4 = [0,1,1]

M0 = [x,1,1] M1 = [x,1,1]

M3 = [x,1,1] M4 = [x,1,1]

C2 = [0,1,1]

Page 88: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

88Optimierungstechniken in modernen Compilern Grundlagen

Beispiel Phase 1

-

Ma Mb +

Mc Md

*

Me

+

C0 = [0,1,1] C1 = [0,1,1]

Ry

op

Rx

Rx

Mx Ry load [x],Ry

op Rx,Ry,Rx

My

op

Rx

Rx op Rx,[y],Rx

Rx My store Rx,[y]

Ry

op

Rx

Mzop Rx,Ry,Rxstore Rx,[z]

My

op

Rx

Mz op Rx,[y],Rxstore Rx,[z]

C2 = [0,1,1]

C3 = [0,1,1] C4 = [0,1,1]

Passende Muster für Knoten 5 und 6:

0 1

3 4

25

6 7

8

Muster Gesamtkosten Verfügbare Register

4 1+1 1

3 1+1+1 | 1+1+1 2

5 1+1+2 | 1+1+2 alle, Ziel Speicher

6 0+1+2 alle, Ziel Speicher

1:

2:

3:

4:

5:

6:

C6 = [3,2,2]

C5 = [3,2,2]

M6 = [6,4,4]

M5 = [6,4,4]

M0 = [x,1,1] M1 = [x,1,1]

M3 = [x,1,1] M4 = [x,1,1]

Page 89: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

89Optimierungstechniken in modernen Compilern Grundlagen

Beispiel Phase 1

-

Ma Mb +

Mc Md

*

Me

+

Ry

op

Rx

Rx

Mx Ry load [x],Ry

op Rx,Ry,Rx

My

op

Rx

Rx op Rx,[y],Rx

Rx My store Rx,[y]

Ry

op

Rx

Mzop Rx,Ry,Rxstore Rx,[z]

My

op

Rx

Mz op Rx,[y],Rxstore Rx,[z]

Passende Muster für Knoten 7:

0 1

3 4

25

6 7

8

Muster Gesamtkosten Verfügbare Register

3 2+1+1 | 1+2+1 2

4 3+1+1 1

4' 0+2+1 1

5 1+2+4 | 2+1+4 alle, Ziel Speicher

6 3+1+2 alle, Ziel Speicher

6' 0+2+2 alle, Ziel Speicher

1:

2:

3:

4:

5:

6:

C6 = [3,2,2]

C5 = [3,2,2]

C7 = [4,3,3]M6 = [6,4,4]

M5 = [6,4,4]

M7 = [6',4',4']

C0 = [0,1,1] C1 = [0,1,1] C2 = [0,1,1]

C3 = [0,1,1] C4 = [0,1,1]

M0 = [x,1,1] M1 = [x,1,1]

M3 = [x,1,1] M4 = [x,1,1]

Page 90: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

90Optimierungstechniken in modernen Compilern Grundlagen

Beispiel Phase 1

-

Ma Mb +

Mc Md

*

Me

+

Ry

op

Rx

Rx

Mx Ry load [x],Ry

op Rx,Ry,Rx

My

op

Rx

Rx op Rx,[y],Rx

Rx My store Rx,[y]

Ry

op

Rx

Mzop Rx,Ry,Rxstore Rx,[z]

My

op

Rx

Mz op Rx,[y],Rxstore Rx,[z]

Passende Muster für Knoten 8:

0 1

3 4

25

6 7

8

Muster Gesamtkosten Verfügbare Register

4 4+2+1 1

4' 3+3+1 1

3 3+2+1 | 2+3+1 2

5 2+3+2 | 3+2+2 alle, Ziel Speicher

6 4+2+2 alle, Ziel Speicher

6' 3+3+2 alle, Ziel Speicher

1:

2:

3:

4:

5:

6:

C6 = [3,2,2]

C5 = [3,2,2]

C7 = [4,3,3]

C8 = [7,7,6]

M6 = [6,4,4]

M5 = [6,4,4]

M7 = [6',4',4']

M8 = [5,4,3]

C0 = [0,1,1] C1 = [0,1,1] C2 = [0,1,1]

C3 = [0,1,1] C4 = [0,1,1]

M0 = [x,1,1] M1 = [x,1,1]

M3 = [x,1,1] M4 = [x,1,1]

Page 91: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

91Optimierungstechniken in modernen Compilern Grundlagen

Details Phase 2

Ziel: Finden der Unterbäume von T, deren Ergebnis in den Speicher berechnet werden soll. Vorgehen:

Tiefendurchlauf durch den Baum T beginnend mit maxReg verfügbaren Registern durch cover(n,maxReg), n ist Wurzel.

Bei Aufruf cover(n,r): Falls am Knoten r = 0, dann

• berechne den Wert von n in den Speicher und setze l = Mn[0], sonst• berechne den Wert von n in Register r-1 und setze l = Mn[r].

Es seien m1,…,mz die Blätter in l mit (mi) = M und b1,…,bz die Knoten in T, die mit m1,…,mz matchen:• Berechne cover(mi,0) für 1 i z.

Es seien r1,…,rk die Blätter in l mit (mi) = R und p1,…,pk die Reihenfolge, in der diese Blätter in Phase 1 ausgewertet wurden und die die minimalen Kosten lieferte:

• Berechne cover(pi,r-i+1) für 1 i k. Erzeuge Zielcode vor dem letzten Verlassen eines Knotens n, dessen Wert in den Speicher berechnet

werden soll, durch Aufruf von genCode(n,0).

M

M

T1

T2 M

T3

Erzeugter Zielcode:genCode(T1,0)genCode(T2,0)genCode(T3,0)Zielcode für T4T4

ld

+

Rx ld

+

Ry

Rx

Zielcode:add Rx,[Ry]

Muster 4:

+

C+ = [7,8,2] cover(+,2)

M+ = [5,3,4]

Page 92: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

92Optimierungstechniken in modernen Compilern Grundlagen

Beispiel Phase 2

Ry

op

Rx

Rx

Mx Ry load [x],Ry

op Rx,Ry,Rx

My

op

Rx

Rx op Rx,[y],Rx

Rx My store Rx,[y]

Ry

op

Rx

Mzop Rx,Ry,Rxstore Rx,[z]

My

op

Rx

Mz op Rx,[y],Rxstore Rx,[z]

1:

2:

3:

4:

5:

6:

-

Ma Mb +

Mc Md

*

Me

+

0 1

3 4

25

6 7

8

C6 = [3,2,2]

C5 = [3,2,2]

C7 = [4,3,3]

C8 = [7,7,6]

M6 = [6,4,4]

M5 = [6,4,4]

M7 = [6',4',4']

M8 = [5,4,3]

Tiefendurchlauf:cover(8,2)cover(7,2)

cover(6,1)

cover(5,2)

Kein Ergebnis wird in den Speicher berechnet!

C0 = [0,1,1] C1 = [0,1,1] C2 = [0,1,1]

C3 = [0,1,1] C4 = [0,1,1]

M0 = [x,1,1] M1 = [x,1,1]

M3 = [x,1,1] M4 = [x,1,1]

cover(3,2)

cover(0,1)

Page 93: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

93Optimierungstechniken in modernen Compilern Grundlagen

Details Phase 3

Teilbäume in T, deren Ergebnis in Phase 2 in den Speicher geschrieben wurde, werden aus T gelöscht. Dadurch entsteht der Baum T'.

Wiederholung des Tiefendurchlaufs aus Phase 2 in T' durch genCode(n,maxReg): Wähle am Knoten n Muster M[r] Es seien r1,…,rk die Blätter in M[r] mit (mi) = R und p1,…,pk die Reihenfolge, in der

diese Blätter in Phase 1 und 2 ausgewertet wurden und die die minimalen Kosten lieferte:

• Berechne genCode(pi,r-i+1) für 1 i k. Generiere Zielcode beim letzten Verlassen eines Knotens n entsprechend dem

gewählten Muster M[r] und berechne das Ergebnis in Register maxReg-r.

M

M

T1

T2 M

T3

T4

M

M

T'M

M

T2 M

T3

T4

M

M

T3

T4

Phase 2 Phase 3

Page 94: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

94Optimierungstechniken in modernen Compilern Grundlagen

Beispiel Phase 3

Ry

op

Rx

Rx

Mx Ry load [x],Ry

op Rx,Ry,Rx

My

op

Rx

Rx op Rx,[y],Rx

Rx My store Rx,[y]

Ry

op

Rx

Mzop Rx,Ry,Rxstore Rx,[z]

My

op

Rx

Mz op Rx,[y],Rxstore Rx,[z]

1:

2:

3:

4:

5:

6:

Tiefendurchlauf:cover(8,2)cover(7,2)

cover(6,1)

cover(5,2)cover(3,2) genCode(3,0)

cover(0,1)

load [c],R0

-

Ma Mb +

Mc Md

*

Me

+

0 1

3 4

25

6 7

8

C6 = [3,2,2]

C5 = [3,2,2]

C7 = [4,3,3]

C8 = [7,7,6]

M6 = [6,4,4]

M5 = [6,4,4]

M7 = [6',4',4']

M8 = [5,4,3]

C0 = [0,1,1] C1 = [0,1,1] C2 = [0,1,1]

C3 = [0,1,1] C4 = [0,1,1]

M0 = [x,1,1] M1 = [x,1,1]

M3 = [x,1,1] M4 = [x,1,1]

Page 95: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

95Optimierungstechniken in modernen Compilern Grundlagen

Beispiel Phase 3

Ry

op

Rx

Rx

Mx Ry load [x],Ry

op Rx,Ry,Rx

My

op

Rx

Rx op Rx,[y],Rx

Rx My store Rx,[y]

Ry

op

Rx

Mzop Rx,Ry,Rxstore Rx,[z]

My

op

Rx

Mz op Rx,[y],Rxstore Rx,[z]

1:

2:

3:

4:

5:

6:

Tiefendurchlauf:cover(8,2)cover(7,2)

cover(6,1)

cover(5,2) genCode(5,0)cover(3,2) genCode(3,0)

cover(0,1)

load [c],R0

-

Ma Mb +

R0 Md

*

Me

+

0 1

3 4

25

6 7

8

C6 = [3,2,2]

C5 = [3,2,2]

C7 = [4,3,3]

C8 = [7,7,6]

M6 = [6,4,4]

M5 = [6,4,4]

M7 = [6',4',4']

M8 = [5,4,3]

C0 = [0,1,1] C1 = [0,1,1] C2 = [0,1,1]

C3 = [0,1,1] C4 = [0,1,1]

M0 = [x,1,1] M1 = [x,1,1]

M3 = [x,1,1] M4 = [x,1,1]

add R0,[d],R0

Page 96: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

96Optimierungstechniken in modernen Compilern Grundlagen

Beispiel Phase 3

Ry

op

Rx

Rx

Mx Ry load [x],Ry

op Rx,Ry,Rx

My

op

Rx

Rx op Rx,[y],Rx

Rx My store Rx,[y]

Ry

op

Rx

Mzop Rx,Ry,Rxstore Rx,[z]

My

op

Rx

Mz op Rx,[y],Rxstore Rx,[z]

1:

2:

3:

4:

5:

6:

Tiefendurchlauf:cover(8,2)cover(7,2) ) genCode(7,0)

cover(6,1)

cover(5,2) genCode(5,0)cover(3,2) genCode(3,0)

cover(0,1)

load [c],R0

-

Ma Mb R0

*

Me

+

0 1 25

6 7

8

C6 = [3,2,2]

C5 = [3,2,2]

C7 = [4,3,3]

C8 = [7,7,6]

M6 = [6,4,4]

M5 = [6,4,4]

M7 = [6',4',4']

M8 = [5,4,3]

C0 = [0,1,1] C1 = [0,1,1] C2 = [0,1,1]

M0 = [x,1,1] M1 = [x,1,1]

add R0,[d],R0

mul R0,[e],R0

Page 97: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

97Optimierungstechniken in modernen Compilern Grundlagen

Beispiel Phase 3

Ry

op

Rx

Rx

Mx Ry load [x],Ry

op Rx,Ry,Rx

My

op

Rx

Rx op Rx,[y],Rx

Rx My store Rx,[y]

Ry

op

Rx

Mzop Rx,Ry,Rxstore Rx,[z]

My

op

Rx

Mz op Rx,[y],Rxstore Rx,[z]

1:

2:

3:

4:

5:

6:

Tiefendurchlauf:cover(8,2)cover(7,2) ) genCode(7,0)

cover(6,1)

cover(5,2) genCode(5,0)cover(3,2) genCode(3,0)

cover(0,1) genCode(0,1)

load [c],R0

-

Ma Mb

R0

+

0 1

6 7

8

C6 = [3,2,2]

C7 = [4,3,3]

C8 = [7,7,6]

M6 = [6,4,4]

M7 = [6',4',4']

M8 = [5,4,3]

C0 = [0,1,1] C1 = [0,1,1]

M0 = [x,1,1] M1 = [x,1,1]

add R0,[d],R0

mul R0,[e],R0

load [a],R1

Page 98: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

98Optimierungstechniken in modernen Compilern Grundlagen

Beispiel Phase 3

Ry

op

Rx

Rx

Mx Ry load [x],Ry

op Rx,Ry,Rx

My

op

Rx

Rx op Rx,[y],Rx

Rx My store Rx,[y]

Ry

op

Rx

Mzop Rx,Ry,Rxstore Rx,[z]

My

op

Rx

Mz op Rx,[y],Rxstore Rx,[z]

1:

2:

3:

4:

5:

6:

Tiefendurchlauf:cover(8,2)cover(7,2) ) genCode(7,0)

cover(6,1) genCode(6,1)

cover(5,2) genCode(5,0)cover(3,2) genCode(3,0)

cover(0,1) genCode(0,1)

load [c],R0

-

R1 Mb

R0

+

0 1

6 7

8

C6 = [3,2,2]

C7 = [4,3,3]

C8 = [7,7,6]

M6 = [6,4,4]

M7 = [6',4',4']

M8 = [5,4,3]

C1 = [0,1,1]

M1 = [x,1,1]

add R0,[d],R0

mul [e],R0,R0

load [a],R1

sub R1,[b],R1

Page 99: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

99Optimierungstechniken in modernen Compilern Grundlagen

Beispiel Phase 3

Ry

op

Rx

Rx

Mx Ry load [x],Ry

op Rx,Ry,Rx

My

op

Rx

Rx op Rx,[y],Rx

Rx My store Rx,[y]

Ry

op

Rx

Mzop Rx,Ry,Rxstore Rx,[z]

My

op

Rx

Mz op Rx,[y],Rxstore Rx,[z]

1:

2:

3:

4:

5:

6:

Tiefendurchlauf:

cover(8,2) genCode(8,0)cover(7,2) ) genCode(7,0)

cover(6,1) genCode(6,1)

cover(5,2) genCode(5,0)cover(3,2) genCode(3,0)

cover(0,1) genCode(0,1)

load [c],R0

R1 R0

+

6 7

8

C7 = [4,3,3]

C8 = [7,7,6]

M7 = [6',4',4']

M8 = [5,4,3]

add R0,[d],R0

mul [e],R0,R0

load [a],R1

sub R1,[b],R1

add R1,R0,R0

Page 100: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

100Optimierungstechniken in modernen Compilern Grundlagen

Beispiel Phase 3

Ry

op

Rx

Rx

Mx Ry load [x],Ry

op Rx,Ry,Rx

My

op

Rx

Rx op Rx,[y],Rx

Rx My store Rx,[y]

Ry

op

Rx

Mzop Rx,Ry,Rxstore Rx,[z]

My

op

Rx

Mz op Rx,[y],Rxstore Rx,[z]

1:

2:

3:

4:

5:

6:

Tiefendurchlauf:

cover(8,2) genCode(8,0)cover(7,2) ) genCode(7,0)

cover(6,1) genCode(6,1)

cover(5,2) genCode(5,0)cover(3,2) genCode(3,0)

cover(0,1) genCode(0,1)

load [c],R0

add R0,[d],R0

mul [e],R0,R0

load [a],R1

sub R1,[b],R1

add R1,R0,R0

-

Ma Mb +

Mc Md

*

Me

+

0 1

3 4

25

6 7

Page 101: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

101Optimierungstechniken in modernen Compilern Grundlagen

Beispiel mit unzureichender Registeranzahl

-

Ma Mb +

Mc Md

*

Me

+

0 1

3 4

25

6 7

8

C6 = [3,2,2]

C5 = [3,2,2]

C7 = [4,3,3]

C8 = [7,7,6]

M6 = [6,4,4]

M5 = [6,4,4]

M7 = [6',4',4']

M8 = [5,4,3]

C0 = [0,1,1] C1 = [0,1,1] C2 = [0,1,1]

C3 = [0,1,1] C4 = [0,1,1]

M0 = [x,1,1] M1 = [x,1,1]

M3 = [x,1,1] M4 = [x,1,1]

7

-

+8'

C8' = [7,7,6]M8' = [5,4,3]

9

Muster Gesamtkosten Verfügbare Register

4 7+7+1 1

4' 7+7+1 1

3 7+6+1 | 7+6+1 2

5 7+6+2 | 7+6+2 alle, Ziel Speicher

6 7+6+2 alle, Ziel Speicher

6' 7+6+2 alle, Ziel Speicher

Ry

op

Rx

Rx

Mx Ry load [x],Ry

op Rx,Ry,Rx

My

op

Rx

Rx op Rx,[y],Rx

Rx My store Rx,[y]

Ry

op

Rx

Mzop Rx,Ry,Rxstore Rx,[z]

My

op

Rx

Mz op Rx,[y],Rxstore Rx,[z]

1:

2:

3:

4:

5:

6:

C9 = [15,15,14]

M9 = [5,4,3]

Page 102: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

102Optimierungstechniken in modernen Compilern Grundlagen

Beispiel mit unzureichender Registeranzahl

-

Ma Mb +

Mc Md

*

Me

+

0 1

3 4

25

6 7

8

C6 = [3,2,2]

C5 = [3,2,2]

C7 = [4,3,3]

C8 = [7,7,6]

M6 = [6,4,4]

M5 = [6,4,4]

M7 = [6',4',4']

M8 = [5,4,3]

C0 = [0,1,1] C1 = [0,1,1] C2 = [0,1,1]

C3 = [0,1,1] C4 = [0,1,1]

M0 = [x,1,1] M1 = [x,1,1]

M3 = [x,1,1] M4 = [x,1,1]

7

-

8'

C8' = [7,7,6]M8' = [5,4,3]

9

Ry

op

Rx

Rx

Mx Ry load [x],Ry

op Rx,Ry,Rx

My

op

Rx

Rx op Rx,[y],Rx

Rx My store Rx,[y]

Ry

op

Rx

Mzop Rx,Ry,Rxstore Rx,[z]

My

op

Rx

Mz op Rx,[y],Rxstore Rx,[z]

1:

2:

3:

4:

5:

6:

C9 = [15,15,14]

M9 = [5,4,3]

Tiefendurchlauf:cover(9,2)cover(8',2)

…cover(8,1)

Page 103: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

103Optimierungstechniken in modernen Compilern Grundlagen

Beispiel mit unzureichender Registeranzahl

-

Ma Mb +

Mc Md

*

Me

+

0 1

3 4

25

6 7

8

C6 = [3,2,2]

C5 = [3,2,2]

C7 = [4,3,3]

C8 = [7,7,6]

M6 = [6,4,4]

M5 = [6,4,4]

M7 = [6',4',4']

M8 = [5,4,3]

C0 = [0,1,1] C1 = [0,1,1] C2 = [0,1,1]

C3 = [0,1,1] C4 = [0,1,1]

M0 = [x,1,1] M1 = [x,1,1]

M3 = [x,1,1] M4 = [x,1,1]

7

-

8'

C8' = [7,7,6]M8' = [5,4,3]

9

Ry

op

Rx

Rx

Mx Ry load [x],Ry

op Rx,Ry,Rx

My

op

Rx

Rx op Rx,[y],Rx

Rx My store Rx,[y]

Ry

op

Rx

Mzop Rx,Ry,Rxstore Rx,[z]

My

op

Rx

Mz op Rx,[y],Rxstore Rx,[z]

1:

2:

3:

4:

5:

6:

C9 = [15,15,14]

M9 = [5,4,3]Tiefendurchlauf:cover(9,2)cover(8',2)

…cover(8,1)cover(7,0)cover(5,2)cover(3,2)

load [c],R1

add R1,[d],R1

mul [e],R1,R1store r1,[t1]

Page 104: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

104Optimierungstechniken in modernen Compilern Grundlagen

Beispiel mit unzureichender Registeranzahl

-

Ma Mb

Mt1

+

0 1

6 7

8

C6 = [3,2,2]

C8 = [7,7,6]

M6 = [6,4,4]

M8 = [5,4,3]

C0 = [0,1,1] C1 = [0,1,1]

M0 = [x,1,1] M1 = [x,1,1]

-

8'

C8' = [7,7,6]M8' = [5,4,3]

9

Ry

op

Rx

Rx

Mx Ry load [x],Ry

op Rx,Ry,Rx

My

op

Rx

Rx op Rx,[y],Rx

Rx My store Rx,[y]

Ry

op

Rx

Mzop Rx,Ry,Rxstore Rx,[z]

My

op

Rx

Mz op Rx,[y],Rxstore Rx,[z]

1:

2:

3:

4:

5:

6:

C9 = [15,15,14]

M9 = [5,4,3]Tiefendurchlauf:cover(9,2)cover(8',2)

…cover(8,1)cover(7,0)cover(5,2)cover(3,2)

load [c],R1

add R1,[d],R1

mul [e],R1,R1store r1,[t1]

cover(6,1)

Page 105: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

105Optimierungstechniken in modernen Compilern Grundlagen

Beispiel mit unzureichender Registeranzahl

-

Ma Mb

Mt1

+

0 1

6 7

8

C6 = [3,2,2]

C8 = [7,7,6]

M6 = [6,4,4]

M8 = [5,4,3]

C0 = [0,1,1] C1 = [0,1,1]

M0 = [x,1,1] M1 = [x,1,1]

-

8'

C8' = [7,7,6]M8' = [5,4,3]

9

Ry

op

Rx

Rx

Mx Ry load [x],Ry

op Rx,Ry,Rx

My

op

Rx

Rx op Rx,[y],Rx

Rx My store Rx,[y]

Ry

op

Rx

Mzop Rx,Ry,Rxstore Rx,[z]

My

op

Rx

Mz op Rx,[y],Rxstore Rx,[z]

1:

2:

3:

4:

5:

6:

C9 = [15,15,14]

M9 = [5,4,3]Tiefendurchlauf:cover(9,2)cover(8',2)

…cover(8,1)cover(7,0)cover(5,2)cover(3,2)

load [c],R1

add R1,[d],R1

mul [e],R1,R1store r1,[t1]

cover(6,1)

// Code für 8'load [a],R0

sub R0,[b],R0

add R0,[t1],R0

sub R0,R1,R1

Page 106: Vorlesung, Wintersemester 2009/10M. Schölzel 1 Optimierungstechniken in modernen Compilern Optimierungstechniken für DSPs und Mikrocontroller.

106Optimierungstechniken in modernen Compilern Grundlagen

Zusammenfassung

Für Ausdrucksbäume können die drei Phasen Code-Selektion, Registerallokation und Ablaufplanung kombiniert werden.

Für Ausdrucksbäume und Load-/Store-Architekturen ist das Finden einer kostenminimalen Zielcodesequenz optimal lösbar.

Für DAGs ist das Problem NP-vollständig. Finden einer Ausführungsreihenfolge der

Operationen im DAG, die eine minimale Registeranzahl erfordert ist NP-vollständig (Pebble-Game).