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

56
orlesung, Wintersemester 2009/10 M. Schölzel Optimierungstechniken in modernen Compilern Optimierungstechniken für superskalare Prozessoren

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 superskalare Prozessoren.

1

Vorlesung, Wintersemester 2009/10 M. Schölzel

Optimierungstechniken in modernen Compilern

Optimierungstechniken für superskalare Prozessoren

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

2

Vorlesung, Wintersemester 2009/10 M. Schölzel

Optimierungstechniken für superskalare Prozessoren

Erzeugen feingranularer Parallelität

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

3Optimierungstechniken in modernen Compilern Grundlagen

Erzeugen feingranularer Parallelität

Problem: Im Programmcode kann nicht genügend Parallelität

gefunden werden, um alle Ausführungseinheiten eines superskalaren Prozessors auszulasten, weil:

• Basisblöcke bilden Grenzen für lokale Schedulingalgorithmen.• Schleifen bilden für viele globale Schedulingalgorithmen Grenzen.

Lösungsansätze: Zusammenfassen mehrerer Basisblöcke zu einem

Basisblock und Anwendung lokaler Planungsverfahren. Erzeugen von feingranularer Parallelität aus Schleifen

durch parallele Abarbeitung verschiedener Iterationen.

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

4Optimierungstechniken in modernen Compilern Grundlagen

Grundprinzipien der Erzeugung feingranularer Parallelität aus Schleifen

s1

s3

s1Iteration 1

Iteration 2

Iteration k

s1Iteration 1

Iteration 2

Iteration k

s2

s2

s1

s3

s2

s1

s3

s2

s3

s1 s2

s3

s1 s2

s3

s3

s2

s1

s3

s2

s1

s3

s2

Takt 1Takt 2Takt 3

Takt 4Takt 5Takt 6

Takt 3k

Takt 1Takt 2

Takt 3Takt 4

Takt 2k

Takt 1Takt 2Takt 3

Anweisungen innerhalb des Schleifenkörpers können

umgeordnet werden, solange dadurch keine

schleifenunabhängigen Abhängigkeiten verletzt

werden.

Schleife ohne schleifengetragene

Abhängigkeiten

Parallelisierung von Anweisungen derselben

Iteration

Parallelisierung von Anweisungen aus

verschiedenen Iterationen

Iterationen einer Schleife können parallel ausgeführt werden, falls

es keine schleifengetragenen Abhängigkeiten zwischen den

Iterationen gibt.

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

5Optimierungstechniken in modernen Compilern Grundlagen

Grundprinzipien der Erzeugung feingranularer Parallelität aus Schleifen

Eliminierung von schleifengetragenen Abhängigkeiten in der innersten Schleife durch:

Loop Distribution, Scalar Expansion, Loop Interchange.

Anschließende Parallelisierung der Iterationen der innersten Schleife.

s1

s3

s2

s1

s3

s2

s1

s3

s2

Takt 1Takt 2

Takt 3

Schleife mit schleifengetragene

Abhängigkeiten

s1

s3

Iteration 1

Iteration 2

Iteration k

s2

s1

s3

s2

s1

s3

s2

Takt 1Takt 2Takt 3

Takt 4Takt 5Takt 6

Takt 3k

Schleife mit schleifengetragenen

Abhängigkeiten s1

s3

Iteration 1

Iteration 2

Iteration k

s2

s1

s3

s2

s1

s3

s2

Takt 1Takt 2

Takt 4Takt 5Takt 6

Takt 3kIteration 1

Iteration 2

Iteration k

Schleife 1

Schleife 2

Ursprüngliche Schleife aufgeteilt in 2 Schleifen

(Loop Distribution)

Separate Parallelisierung beider Schleifen

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

6Optimierungstechniken in modernen Compilern Grundlagen

Loop Distribution bei vorwärts gerichteten schleifengetragenen Abhängigkeiten

Anweisungen im Schleifenkörper sind parallelisierbar

Maximal 2 gleichzeitige Multiplikationen

Iterationen sind nicht parallelisierbar:

Schleife trägt eine Abhängigkeit

Iterationen jeder Schleife sind parallelisierbar:

Bis zu N Multiplikationen können parallel ausgeführt werden!

for i = 1 to N step 1 do(s) a[i+1] = b[i] * 3;(t) d[i] = a[i] * 5; od

{1}D

s

t

s1

t1

s2

t2

s3

t3

sN

tN

…s1

t1

s2

t2

s3

t3

sN

tN

for i = 1 to N step 1 do(s) a[i+1] = b[i] * 3; od for i = 1 to N step 1 do(t) d[i] = a[i] * 5; od

Quelltext Quelltext nach Loop DistributionAbhängigkeitsgraph

Ausführungsreihenfolge mit Abhängigkeiten Ausführungsreihenfolge mit Abhängigkeiten

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

7Optimierungstechniken in modernen Compilern Grundlagen

Loop Distribution bei rückwärts gerichteten schleifengetragenen Abhängigkeiten

Anweisungen im Schleifenkörper sind parallelisierbar

Maximal 2 gleichzeitige Multiplikationen

Iterationen sind nicht parallelisierbar:

Schleife trägt eine Abhängigkeit

Durch Vertauschung der Anweisungen (s) und (t) erhalten wir die Schleife von Folie 4.

Iterationen jeder Schleife sind parallelisierbar:

Bis zu N Multiplikationen können parallel ausgeführt werden!

for i = 1 to N step 1 do(s) d[i] = a[i] * 3;(t) a[i+1] = b[i] * 5; od

{1}D

s

t

s1

t1

s2

t2

s3

t3

sN

tN

Quelltext

Ausführungsreihenfolge mit Abhängigkeiten

t1

s1

t2

s2

t3

s3

tN

sN

for i = 1 to N step 1 do(t) a[i+1] = b[i] * 3; od for i = 1 to N step 1 do(s) d[i] = a[i] * 5; od

Quelltext nach Loop DistributionAbhängigkeitsgraph

Ausführungsreihenfolge mit Abhängigkeiten

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

8Optimierungstechniken in modernen Compilern Grundlagen

Wann funktioniert Loop Distribution nicht?

Tauschen zweier Anweisungen s und t im Schleifenkörper führt nach Loop Distribution dazu, dass alle Instanzen von s nach den Instanzen von t ausgeführt werden.

Loop-Distribution nicht möglich, weil zyklische Abhängigkeit im Abhängigkeitsgraphen existiert. Diese entsteht, weil:

Es ex. eine rückwärtsgerichtete schleifengetragene Abhängigkeit von t nach s es existieren schleifenunabhängige bzw. vorwärtsgerichtete schleifengetragene

Abhängigkeiten von s nach t. Dadurch:

• können Anweisungen auf dem Pfad von s nach t nicht getauscht werden und • wegen der rückwärtsgerichteten Abhängigkeit können nicht alle Instanzen von s vor den Instanzen

von t ausgeführt werden.

for i = 1 to N step 1 do(s) b[i] = a[i] * 3;(t) a[i+1] = b[i] * 5; od {1}D

s

t

{0}D

s1

t1

s2

t2

s3

t3

sN

tN

Ausführungsreihenfolge mit AbhängigkeitenQuelltext Abhängigkeitsgraph

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

9Optimierungstechniken in modernen Compilern Grundlagen

Planung mit Loop-Distribution und Paralleliserung von Schleifeniterationen

L sei das Schleifennest, das die zu parallelisierenden Anweisungen in der innersten Schleife enthält, wobei die innerste Schleife von 1 bis N läuft.

D ist der Abhängigkeitsgraph für die Anweisungen in L. Berechne die Menge {C1,...,Cm} maximaler stark

zusammenhängender Komponenten in D. Konstruiere D' aus D durch Ersetzung der Knoten in jedem Ci durch

einen einzelnen Knoten i, wobei alle Kanten, die adjazent mit genau einem Knoten in Ci sind, mit i adjazent gemacht werden.

Es seien P = {1,...,m} die m Knoten in D' Solange P nicht leer ist:

Falls ein Knoten i P ohne Vorgänger existiert und Ci ein Zykel ist:• Plane die Anweisungen aus Si in eine Schleife.

Falls ein Knoten i P ohne Vorgänger existiert und Ci kein Zykel ist:• Erzeuge N parallele Anweisungen Ci (Ci enthält nur eine Anweisung).

Entferne i und seine adjazenten Kanten aus P.

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

10Optimierungstechniken in modernen Compilern Grundlagen

Beispiel

{1}D

S1

S2

{0}D

S0

{0}A

S3

S4

S5

2

1

3

4

5

C1

C2

C3

C4

C5

for i = 1 to N step 1 do S0;odfor i = 1 to N step 1 do S1; S2;odS3;...;S3;S4;...;S4;S5;...;S5;

N-mal

Abhängigkeitsgraph DAbhängigkeitsgraph D' Parallelisierter Programmcode

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

11Optimierungstechniken in modernen Compilern Grundlagen

Loop Interchange

Loop Interchange permutiert die Schachtelung der Schleifen und tauscht die korrespondierenden Komponenten in den Richtungsvektoren:

Beweis: Jede Abhängigkeit wird für zwei Anweisungen si und sk berechnet, indem zwei Belegung der

Indexvariablen gesucht werden (Indexvektoren). Richtungsvektor der Abhängigkeit ergibt sich aus dem Verhältnis der Komponenten der

Indexvektoren. Reihenfolge der Komponenten in den Indexvektoren hängt nur von der Reihenfolge der

Schachtelung ab. Vertauschen von Schleifen vertauscht entsprechende Komponenten in den Indexvektoren. Damit: Tausch zweier Schleifen tauscht die korrespondierenden Spalten in der

Abhängigkeitsmatrix.

for i1 = L1 to U1 step 1 do for i2 = L2 to U2 step 1 do ... for id = Ld to Ud step 1 do s1;...;sn

od ... odod

for i2 = L2 to U2 step 1 do for i1 = L1 to U1 step 1 do ... for id = Ld to Ud step 1 do s1;...;sn

od ... odod

Richtungsvektor für eine Abhängigkeit: (<,=, <, ... ,>)Richtungsvektor für dieselbe Abhängigkeit: (=,<, <, ... ,>)

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

12Optimierungstechniken in modernen Compilern Grundlagen

Gültigkeit einer Vertauschung

Bei Vertauschung der Schleifen auf Level i und j werden auch die Komponenten i und j in den Richtungsvektoren aller Abhängigkeiten vertauscht.

Falls jeder der daraus entstehenden Richtungsvektoren ein gültiger Richtungsvektor ist, dann ist die Vertauschung gültig.

Beispiel:for i = 1 to N step 1 do for j = 1 to M step 1 do for k = 1 to L step 1 do a[i+1][j+1][k] = a[i][j][k] + a[i][j+1][k+1] od odod

[<,<,=][<,=,>]

Richtungsvektoren[<,<,=][=,<,>]

Tausch von Level 1 und 2Tausch von Level 1 und 3 (ungültig)[=,<,<][>,=,<]

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

13Optimierungstechniken in modernen Compilern Grundlagen

Beispiel

for i = 1 to N step 1 do for j = 1 to M step 1 do a[i][j+1] = a[i][j] + 2 odod

for j = 1 to N step 1 do for i = 1 to M step 1 do a[i][j+1] = a[i][j] + 2 odod

Innere Schleife trägt die Abhängigkeit

Äußere Schleife trägt die Abhängigkeit

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

14Optimierungstechniken in modernen Compilern Grundlagen

Scalar Expansion - Motivation

Zyklen im Abhängigkeitsgraphen verhindern Parallelisierung von Schleifeniterationen.

Zyklen im Abhängigkeitsgraphen sind eliminiert – Schleifeniterationen können parallelisiert werden.

for i = 1 to N step 1 do(s) t = a[i];(t) a[i] = b[i];(u) b[i] = t; od

{0,1}D

s

u

{0}A

t

{0}A

{1}A

{1}O

for i = 1 to N step 1 do(s) t[i] = a[i];(t) a[i] = b[i];(u) b[i] = t[i]; od

{0,1}D

s

u

{0}A

t

{0}A

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

15Optimierungstechniken in modernen Compilern Grundlagen

Überdeckende Definition

Eine Definition X einer skalaren Variablen S ist eine überdeckende Definition für die Schleife L, falls eine Definition für S, die am Beginn der Schleife L eingefügt wird, keine Verwendungen von S erreicht, ohne vorher X erreicht zu haben.

Eine Menge C von Definition einer skalaren Variablen S ist eine Menge überdeckender Definitionen für L, falls eine Definition für S, die am Beginn der Schleife L eingefügt wird, keine Verwendungen von S erreicht, ohne vorher eine Definition aus der Menge C erreicht zu haben.

Beispiele: for i = 1 to N step 1 do(s) t = a[i];(u) b[i] = t; od

Beispiel 1: s ist eine überdeckende Definition.

for i = 1 to N step 1 do if anyCond then(s) t = a[i]; fi(u) b[i] = t; od

Beispiel 2: Es existiert keine überdeckende Definition. for i = 1 to N step 1 do if anyCond then(s) t = a[i]+1; else(t) t = a[i]-1; fi(u) b[i] = t; od

Beispiel 3: {s, t} sind eine Menge von überdeckenden Definitionen.

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

16Optimierungstechniken in modernen Compilern Grundlagen

Berechnen Überdeckender Definitionen für ein SSA-Programm

Q sei die -Funktion am Beginn der Schleife L, die die Variable t definiert und eine SSA-Kante von außerhalb der Schleife nach Q führt.

Setze Menge der überdeckenden Definitionen C := ; Leere den Stack S. D sei die erste Definition von t in L. C := C {D}. Für jede -Funktion P, die verschieden von Q und SSA-Nachfolger von D ist:

push(S,P) und markiere P. Solange S nicht leer ist:

P = pop(S) Füge alle SSA-Vorgänger von P, die keine -Funktion sind, zur Menge C hinzu. Für jede unmarkierte -Funktion R (verschieden von Q), die ein SSA-Vorgänger von P ist:

push(S,R) und markiere R. Für jede unmarkierte -Funktion R, die SSA-Nachfolger von P ist und die nicht von P

dominiert ist: push(S,R) und markiere R. Falls ein SSA-Kantenweg von Q nach P existiert, dann füge eine Anweisung T = T als letzte

Anweisung auf dem Pfad von Q nach P ein und füge diese Anweisung zu C hinzu.

t = 0;for i = 1 to N step 1 do a[i] = t; if anyCond then t = t + b[i] + c[i]; fi d[i] = t;od

1 t0 = 0; for i = 1 to N step 1 do2 t1 = (t0,t3);3 a[i] = t1; if anyCond then4 t2 = t1 + b[i] + c[i]; fi5 t3 = (t1,t2);6 d[i] = t3; od

Q = 2 D = 4 C = {4}

S = (5)

C = {4}P = 5

7 else t = t C = {4,7}

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

17Optimierungstechniken in modernen Compilern Grundlagen

Scalar Expansion durchführen

Erzeuge für die skalare Variable t ein Feld T geeigneter Länge. Für jede Anweisung S in C ersetze t auf der linken Seite durch T[i]. Jede Verwendung von t, die vor den Definitionen in C liegt (direkte SSA-Nachfolger

von Q): Ersetze t durch T[i-1]. Jede andere Definition und Verwendung von t, ersetze durch T[i]. Falls Q vorhanden, dann füge T[0] = t vor dem Beginn der Schleife ein. Falls eine SSA-Kante von einer Definition von t nach außerhalb von L führt, dann

füge t = T[N] nach dem Ende der Schleife ein, wobei N die obere Grenze der Schleife ist.

Beispiel:

1 t0 = 0; for i = 1 to N step 1 do2 t1 = (t0,t3);3 a[i] = t1; if anyCond then4 t2 = t1 + b[i] + c[i]; else7 t = t fi5 t3 = (t1,t2);6 d[i] = t3; od

1 t = 0; for i = 1 to N step 1 do3 a[i] = t; if anyCond then4 t = t + b[i] + c[i]; else7 t = t fi6 d[i] = t; od

1 t = 0; T[0] = t; for i = 1 to N step 1 do3 a[i] = T[i-1]; if anyCond then4 T[i] = T[i-1] + b[i] + c[i]; else7 T[i] = T[i-1] fi6 d[i] = T[i]; od

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

18

Vorlesung, Wintersemester 2009/10 M. Schölzel

Optimierungstechniken für superskalare Prozessoren

Schleifenfreie Ablaufplanung für superskalare Prozessorarchitekturen

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

19Optimierungstechniken in modernen Compilern Grundlagen

Trace-Scheduling

Trace: Folge aufeinander folgender Basisblöcke. Steuerfluss führt an beliebigen Positionen in Traces hinein oder heraus:

Ein Split ist eine Verzweigung aus dem Trace heraus. Ein Join ist eine Verzweigung in den Trace hinein.

Planung der Operationen in einem Trace durch einen List-Scheduling-Algorithmus.

Trace-Scheduling erlaubt: Abwärtsverschiebung von Operationen hinter Splits. Aufwärtsverschiebung von Operationen vor einen Split nur bei

Operationen ohne Seiteneffekte. Aufwärts-/Abwärtsverschiebung von Operationen vor/hinter Joins. In praktischen Implementierungen (z.B. Multiflow-Compiler) wird

die Reihenfolge von Sprunganweisungen in einem Trace nicht verändert.

Einfügen von Korrekturcode an solchen Positionen, an denen in einen gescheduleten Trace hineingesprungen oder herausgesprungen wird.

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

20Optimierungstechniken in modernen Compilern Grundlagen

Algorithmus

Auswahl einer Folge von Basisblöcken (Trace), deren Operationen gemeinsam geplant werden sollen. Grenzen eines Traces:

Start-/Stoppknoten des Steuerflussgraphen. Schleifen (kein Trace enthält Blöcke einer Schleife und Blöcke, die

nicht zu dieser Schleife gehören). Bereits geplante Blöcke.

Entfernen des Traces aus dem Steuerflussgraphen und Anwendung eines List-Scheduling-Algorithmus auf den Trace.

Einsetzen des Ergebnisses des List-Schedulers in den Steuerflussgraphen und Einfügen von Korrekturcode für solche Operationen, die hinter Splits oder vor/hinter Joins verschoben wurden.

Wiederholung dieser Schritte, bis alle Blöcke im Steuerflussgraphen verplant wurden.

Ausgabe des Codes im Steuerflussgraphen in einer geeigneten Reihenfolge.

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

21Optimierungstechniken in modernen Compilern Grundlagen

Korrektur bei Verschiebung hinter Split

Korrekturcode: Für jeden Split mit einem Sprungziel b:

• Erzeuge einen neuen Vorgängerblock für b und kopiere jede Operation, die hinter den Split verschoben wurde, in diesen Block unter Beachtung der ursprünglichen Reihenfolge.

Op 1

Op 2

Branch

Op 4

Op 5

Op 6

Trace

b

Op 3

Op 2Branch

Op 1 Op 4

Op 3 Op 5

Op 6

Schedule

b

Op 1

Op 3

Op 1

Op 3

Korrekturcode

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

22Optimierungstechniken in modernen Compilern Grundlagen

Korrektur bei Verschiebung vor/hinter einen Join

Korrekturcode: Für jeden Join Bestimme im Schedule die maximale Position p an der eine Operation

ausgeführt wird, die im Trace vor dem Join ausgeführt wurde. Bestimme alle Operationen, die im Trace nach dem Join ausgeführt wurden und im

Schedule bis zur Position p ausgeführt werden. Füge diese Operationen als neuen Nachfolgerblock von b in den Steuerflussgraphen ein. Am Ende dieses Blocks wird an Position p+1 in den Schedule des Traces verzweigt.

Op 1

Op 2

Op 4

Op 5

Op 6

Trace

b

Op 3

Op 3

Op 2

Op 4Op 1

Op 5

Op 6

Schedule

b

Op 1

Op 3Op 4

Korrekturcode

Op 5

Op 3

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

23Optimierungstechniken in modernen Compilern Grundlagen

Split-Operationen im Korrekturcode für Joins

Für Splits, die sich im Korrekturcode für Joins befinden, müssen die Operationen bestimmt werden, die im Trace vor dem Split ausgeführt wurden und sich im Schedule hinter dem Einsprung des Korrekturcodes für den Join befinden.

Op 1

Op 2

Op 4

Branch

Op 5

Trace

b

Op 3

Op 1

Op 3

b'

Op 1Branch

Op 3

Op 2

Op 4

Op 5

b'

Op 2

Op 3

Op 4

b

Op 3

Branch

Op 5

Op 4

Schedule

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

24Optimierungstechniken in modernen Compilern Grundlagen

Beispiel für Explosion des Korrekturcodes

C1

A1

B1

C2

A2

B2

Cn

An

Bn

Trace Schedule

Cn

An

Cn-1

An-1

C1

A1

...

...

C1 A1 C2 A2 BnCn-1 An-1...

C1 A1 C2 A2 Bn-1Cn-2 An-2...

Cn

An

B1 C2 A2 Cn An...

Korrekturcode, der zu n neuen Traces führt.

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

25Optimierungstechniken in modernen Compilern Grundlagen

Superblöcke

Vereinfachung von Traces: Trace darf nur am Anfang betreten werden. Verlassen ist an beliebigen Positionen möglich.

Erzeugen von Superblöcken in 2 Schritten: Auswählen eines Traces. Tail-Duplication: Eliminierung von Eintrittspunkten

durch Duplizierung des Resttraces nach dem Eintrittspunkt.

Vorteil: Vereinfachung der Erzeugung des Korrekturcodes.

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

26Optimierungstechniken in modernen Compilern Grundlagen

Tail-Duplication

A

B

E

F

C

D

Start

Stopp

A

B

E

F

C

D

Start

Stopp

F'

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

27Optimierungstechniken in modernen Compilern Grundlagen

Superblock Scheduling

Auswahl eines Traces. Tailduplication ausführen. Konstruktion des Abhängigkeitsgraphen. Anwendung eines List-Schedulers unter Beachtung des

Abhängigkeitsgraphen. Korrekturen ausführen:

Operation wurde vor einen Split verschoben, dann wird Operation spekulativ ausgeführt:

• Nur dann möglich, wenn die Operation keine Exception verursacht und

• wenn der definierte Wert vor dem Split nicht lebendig war. Operationen wurden hinter einen Split verschoben, dann muss

Korrekturcode wie bei Trace-Scheduling erzeugt werden.

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

28Optimierungstechniken in modernen Compilern Grundlagen

Unterstützung zur Ausführung spekulativer Operationen

Bisher zwei wesentliche Probleme bei der spekulativen Ausführung einer Operation:

Operation mit Seiteneffekten kann Exception auslösen.

Falls die Operation eine load-Operation ist, muss der Compiler beweisen, dass keine RAW-Abhängigkeit zwischen dem load und einer vorangehenden store-Operation existiert, falls load vor dieses store verschoben werden soll.

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

29Optimierungstechniken in modernen Compilern Grundlagen

Spekulative Ausführung von loads

Problem: In einigen Fällen kann der Compiler nicht beweisen,

dass es keine RAW-Abhängigkeit zwischen store- und load-Operation gibt, da die zugegriffene Adresse nicht statisch berechnet werden kann.

Spekulative Ausführung trotzdem möglich durch:

Einfügen von Test- und Korrekturcode ins Programm oder

Hardwareunterstützung (Memory Conflict Buffer) für das Programm.

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

30Optimierungstechniken in modernen Compilern Grundlagen

Test- und Korrekturcode

load-Operation u wird spekulativ ausgeführt. Nach jeder store-Operation v, für die es eine Datenabhängigkeit (v,u)

geben kann, wird Programmcode eingefügt, der prüft, ob u und v dieselbe Adresse nutzen.

Falls ja, müssen alle von u datenabhängigen Operationen, die vor v ausgeführt wurden, wiederholt werden.

Deren Operanden dürfen nicht verändert worden sein.

mul R2,R3 R1

store R11 [R9]

store R1 [R3]

load [R5] R4

add R4,R1 R6

mul R2,R3 R1

load [R5] R4

store R11 [R9]

jmpneq R9,R5 skip1

mov R11 R4

skip1:

store R1 [R3]

jmpneq R3,R5 skip2

mov R1 R4

skip2:

add R4,R1 R6

Originalcode spekulative Ausführung des loads

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

31Optimierungstechniken in modernen Compilern Grundlagen

Hardwareunterstützung zur spekulativen Ausführung von load-Operationen

Memory-Conflict-Buffer (MCB) speichert Tripel mit Registernummer, Speicheradresse und Konfliktbit.

Unterscheidung im Befehlssatz des Prozessors zwischen spekulativem load und nicht-spekulativem load.

Spekulatives load von der Adresse a in ein Register b erzeugt im MCB einen Eintrag (a,b,0).

store-Operation an eine Adresse c im Speicher ändert Konfliktbit in allen Einträgen (a,b,x) des MCB mit a = c auf 1.

Befehlssatz enthält eine Operation check r, label, wobei r ein Register und label die Adresse des Korrekturcodes ist.

Ausführung der check r, label Operation an der ursprünglichen Position des loads, wobei r Zielregister der load-Operation ist.

Falls Im MCB ein Eintrag (a,r,1) existiert, wird die Operation mit dem Label label angesprungen.

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

32Optimierungstechniken in modernen Compilern Grundlagen

Integration in Superblock Scheduling

Erzeugen eines Superblocks. Erzeugen des Abhängigkeitsgraphen. check r, label_i nach jeder Operation i der Form load [a]

r einfügen. check-Operation übernimmt die Abhängigkeiten mit

store-Operationen des zugehörigen loads und ist abhängig von der zugehörigen load-Operation sowie umgebenden Sprunganweisungen.

RAW-Abhängigkeiten für jede load-Operation entfernen, wodurch das load verschoben werden kann.

Superblock planen. Korrekturcode einfügen: Quelloperanden der

Operationen im Korrekturcode dürfen nicht überschrieben worden sein (es darf kein WAR-Abhängigkeiten zwischen den Operationen des Korrekturcodes geben).

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

33Optimierungstechniken in modernen Compilern Grundlagen

Beispiel

mul R2,R3 R1

store R11 [R9]

store R1 [R3]

load [R5] R4

add R4,R1 R6

store R6 [R10]

add R6,R12 R11

...

Originalcode mit möglichen

Abhängigkeiten des loads von stores

Geplanter Superblock mit Korrekturcode und dupliziertem

Ende, um Einsprung zu vermeiden.

mul R2,R3 R1

store R11 [R9]

store R1 [R3]

load [R5] R4

check R4, Korrektur

add R4,R1 R6

store R6 [R10]

add R6,R12 R11

...

Abhängigkeiten der check-

Operation

mul R2,R3 R1

load [R5] R4

add R4,R1 R6

store R11 [R9]

store R1 [R3]

check R4, Korrektur

store R6 [R10]

add R6,R12 R11

...

Korrektur:

load [R5] R4

add R4,R12 [R11]

jmp tailDup

TailDup:

store R6 [R10]

add R6,R12 R11

...

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

34Optimierungstechniken in modernen Compilern Grundlagen

Behandlung von Exceptions bei spekulativer Ausführung analog

Behandlung von Exceptions durch E-Tags in Registern: Jede Operation ist in zwei Varianten vorhanden:

• Auftretende Exception wird sofort ausgeführt,• Auftretende Exception wird verzögert.

Im Fehlerfall wird E-Tag im Zielregister gesetzt und PC in das Register kopiert.

Falls kein Fehler auftritt wird das Ergebnis der Operation ins Zielregister geschrieben und E-Tag gelöscht.

Falls eine spekulative Operation einen ungültigen Operanden verwendet (E-Tag gesetzt), wird dieser in das Zielregister kopiert.

An der Position, an der sich die Operation ursprünglich befunden hat wird durch eine check-Operation geprüft, ob eine Execption ausgelöst wurde.

Für Recovery wurde der PC gespeichert, außerdem müssen alle spekulativ ausgeführten Operationen wiederholt werden.

Operanden der Operation müssen an dieser Stelle auch noch zur Verfügung stehen, um Operation zu wiederholen.

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

35

Vorlesung, Wintersemester 2009/10 M. Schölzel

Optimierungstechniken für Superskalare Prozessoren

Ablaufplanung von Schleifen

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

36Optimierungstechniken in modernen Compilern Grundlagen

Scheduling von Schleifen

Bisher konnten Operationen nicht über die Grenzen des Schleifenkörpers verschoben werden.

Lösung: Schleife ausrollen, Trace-Scheduling anwenden. Bewegung der Operationen nur innerhalb der

ausgerollten Schleifenkörper.

B

H

E

B

H

B

H

B E

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

37Optimierungstechniken in modernen Compilern Grundlagen

Prinzip Modulo-Scheduling

Aus dem gegebenen Schleifenkörper wird ein neuer Moduloschleifenkörper erzeugt, der die Länge II hat. Die Operationen des Schleifenkörpers werden in II vielen Instruktionen geplant. Dabei können Operationen, die in derselben Iteration des Schleifenkörpers ausgeführt werden, in eine andere

Iteration der Moduloschleife verschoben werden, wenn dadurch keine Abhängigkeiten verletzt werden. Gesucht ist somit ein Schedule (,), der einer Operation v einen Zeitpunkt 0 (v) < II und eine Iteration (v)

zuordnet, in der v ausgeführt wird:

Op1

Schleifenkörper, der keine

schleifengetragenen

Abhängigkeiten besitzt.

Op2

Op3

Op4

Op10 Op20

Op30

Op40

Op11 Op21

Op31

Op41

Op12 Op22

Op32

Op42

Op10 Op20

Op11 Op21 Op30

Op12 Op22 Op31 Op40

Op13 Op23 Op32 Op41

Op13 Op23 Op32 Op41

Iteration 1

Iteration 2

Iteration 3

Normale Ausführung

Moduloschleifeniterationen für II = 1

Moduloschleifenkörper

Op1 Op2 Op3 Op4

Iteration 1

Iteration 2

Iteration 3

Iteration 4

Iteration 5

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

38Optimierungstechniken in modernen Compilern Grundlagen

Planung der Operation

Zunächst Einschränkung auf azyklische Abhängigkeitsgraphen. Damit bei vorhandener Kante (v,w) keine Abhängigkeit verletzt

wird, muss (v) + d(v,w) (w), falls (w) = (v) oder II * (v) + (v) + d(v,w) II * (w) + (w), was die erste Forderung

überflüssig macht. Konsequenz: Jede mögliche Position innerhalb von II kann zur

Planung von v genutzt werden. Einschränkung entsteht nur durch vorhandene Ressourcen.

Untere Schranke für II:

Potentieller Ausführungszeitpunkt für w

vII

d(v,w)Iteration (v)

wIIIteration (w)

...w

{ | und ( ) }( ) max

( )v v V type v t

ResII G tR t

ì üï ïÎ =ï ï= Îí ýï ïï ïî þT

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

39Optimierungstechniken in modernen Compilern Grundlagen

Schedulingalgorithmus für azyklische Abhängigkeitsgraphen

Algorithmus: moduloScheduleEingabe: Abhängigkeitsgraph G Länge II des Initiation IntervallsAusgabe: Schedule (,) Es sei v1,...,vn eine topologische Sortierung der Knoten im Abhängigkeitsgraphen G.for i = 1 to n do earlyS = 0; earlyI = 0; for each w mit (w,vi) E do thisS = (w) + d(w); thisI = (w); if(thisS II) then thisI = thisI + (thisS div II) thisS = thisS mod II; fi if(thisI > earlyI or thisS > earlyS) then earlyI = thisI; earlyS = thisS; fi od Versuche ab earlyS eine Position c mit freier Ressource für w zu finden. Falls das nicht möglich ist, dann ab Anfang des Moduloschleifenkörpers die Suche fortsetzen. (v) = c; if Suche wurde ab Schleifenanfang fortgesetzt then (v) = earlyI + 1; else (v) = earlyI; fiod

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

40Optimierungstechniken in modernen Compilern Grundlagen

Beispiel

Op1 Op2

Op3

Op4

Op1 Op2 (1) = 0, (2) = 0

Op3

Op4

Ursprünglicher Schleifenkörper Scheduling für II = 2 und 2 Ressourcen pro Takt.Topologische Sortierung: Op1, Op2, Op3, Op4.

i = 1 und 2

i = 3Op1 Op2 (1) = 0, (2) = 0

(3) = 0

Op3

i = 4Op1 Op2 (1) = 0, (2) = 0

(3) = 0, (4) = 1

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

41Optimierungstechniken in modernen Compilern Grundlagen

Interschleifenabhängigkeiten

Schleifen ohne Interschleifenabhängigkeiten sind unrealistisch:

Schreiboperationen auf skalare Variablen (Schleifenzähler, Zeiger in Felder) erzeugen WAW-Abhängigkeit zwischen aufeinander folgenden Iterationen.

Häufig auch Abhängigkeiten zwischen Zugriffen auf Feldelemente. Beispiele:

for(i = 1; i < n; i++) A[i] = A[i-1] + k;

for(i = 2; i < n; i++) A[i] = A[i-2] + k;

for(i = 0; i < n; i++) A[i] = A[i+2] + k;

Iteration i = k

load A[k-1]store A[k]

Iteration i = k+1

load A[k]store A[k+1]

RAW

Iteration i = k

load A[k-2]store A[k]

Iteration i = k+1

load A[k-1]store A[k+1]RAW

Iteration i = k+2

load A[k]store A[k+2]

Iteration i = k

load A[k+2]store A[k]

Iteration i = k+1

load A[k+3]store A[k+1]WAR

Iteration i = k+2

load A[k+4]store A[k+2]

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

42Optimierungstechniken in modernen Compilern Grundlagen

Beachtung von Interschleifenabhängigkeiten

Es sei (w,v) eine Kante mit cross((w,v)) > 0. Wo muss v geplant werden? w muss im Moduloschedule d(w,v) viele Takte vor der Operation v

ausgeführt werden, die cross(w,v) viele Iterationen nach der Operation w im ursprünglichen Schleifenkörper ausgeführt wird: (w) * II + (w) + d(w,v) (v) * II + (v) + cross(w,v) * II

Es ergibt sich: (w) + d(w,v) (v) + ((v) – (w) + cross(w,v))*II

vm

(w) – (v) mal

wm...

...cross(w,v) mal

vz

Instruktion (w) * II + (w)

Instruktion (v) * II + (v)

cross(w,v) * II viele Instruktionen

z = m + cross(w,v)

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

43Optimierungstechniken in modernen Compilern Grundlagen

Welche Einschränkungen ergeben sich bei der Planung?

Es seien v1,...,vk die Knoten eines Zykels im Abhängigkeitsgraphen, wobei: für alle Kanten (vi,vi+1) mit 1 i < k gilt: cross((vi,vi+1)) = 0 und cross((vk,v1)) > 0.

Planung der Operationen v1,...,vk durch Moduloscheduling führt dazu, dass für Operation vk gilt: (vk) (v1).

Das bedeutet, dass bei Ausführung von v1 und vk in einer Moduloschleifeniteration, wobei v1 aus der Schleifeniteration m sein soll, die Operation vk aus der Schleifeniteration m – ((vk) – (v1)) ausgeführt wird.

Analog: Stammt vk aus der Schleifenitertion m, dann gehört v1 zur Schleifeniteration m + ((vk) – (v1)).

Damit (vk) + d(vk,v1) (v1) + ((v1) – (vk) + cross(vk,v1))*II erfüllt ist, darf vk nicht um mehr als cross(vk,v1) viele Iterationen nach v1 ausgeführt werden.

Beispiel:Op1 Op2

Op3

Op4

<1,1>

<0,1>

Op1 Op2 Op3 Op4Op4 muss einen Takt

bevor Op3 aus der nächsten Iteration ausgeführt wird,

ausgeführt worden sein.

II = 1: Op1

Op2

II = 2: Op3

Op4(1) = 0(2) = 0(3) = 1(4) = 2

Op1Op3

II = 2: Op2

Op4

(1) = 0(2) = 0(3) = 0(4) = 1

(1) = 0(2) = 0(3) = 1(4) = 1

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

44Optimierungstechniken in modernen Compilern Grundlagen

Weitere untere Schranke für II

Da bei einer Kante (vk,v1) vk nicht um mehr als cross(vk,v1) viele Iterationen nach v1 ausgeführt werden darf, müssen alle Operationen auf einem Pfad von v1 in diesen Iterationen der Moduloschleife verteilt werden.

Es ergibt sich für einen Zykel v1,...,vk,vk+1 mit v1 = vk+1 im Abhängigkeitsgraphen:

Und damit als weitere untere Schranke für II:

11

11

( , )( )

( , )

k

i ii

k

i ii

d v vRecII z

cross v v

+=

+=

é ùê úê úê ú=ê úê úê úê ú

å

å

( ) max{ ( ) | ist Zykel im Abhängigkeitsgraphen }RecII G RecII z z G=

Op1

Op2

Op3

Op4

Op5

II = 2:Op1Op2

Op3Op4

Op5

Iteration

n n–1

n–2

II = 3:Op1Op2Op3

Op4Op5

Iteration

n n–1

<2,1><0,1>

<0,1>

<0,1>

<0,1>

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

45Optimierungstechniken in modernen Compilern Grundlagen

Schedulingalgorithmus für zyklische Abhängigkeitsgraphen

Eingabe: Abhängigkeitsgraph G mit Knotenmenge N und Kantenmenge EAusgabe: Schedule (,)

MinII = max(ResII(G),RecII(G))Es sei G' der Graph G, in dem alle Zyklen durch entfernen der Rückkante aufgebrochen wurden

failed = true;for II = MinII to |N| do (,) = moduloSchedule(G',II) allOk = true; for each Zykel z in G do Es sei v1 die erste und vk die letzte Operation auf dem Zykel z in G if not ((vk) + delay(vk) (v1) + ((vk) – (v1) + cross(vk,v1))*II) then allOk = false fi od if allOk then return (,) fiod

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

46Optimierungstechniken in modernen Compilern Grundlagen

Prologgenerierung

Prolog zum Initialisieren des Moduloschleifenkörpers. Epilog zum Beenden der begonnenen Iterationen. range(,) = max{(n) | n ist Operation im Schedule} ist die Anzahl der

Iterationen, die ausgeführt werden müssen, bevor der Moduloschedule ausgeführt werden kann.

Es werden immer range(,) + 1 viele Iterationen ausgeführt. Generierung des Prolog:

Einfügen von range vielen Kopien des Moduloschedules vor dem Moduloschedule und Ersetzen von allen Operationen v in Kopie k mit (v) k durch NOPs.

Generierung des Epilogs: Einfügen von range vielen Kopien des Moduloschedules nach dem

Moduloschedule und Ersetzen von allen Operationen v in Kopie k mit (v) < k durch NOPs.

Op1Op2

Op3Op4

(1) = 0(2) = 0(3) = 1(4) = 1

Moduloschedule

Op1Op2

Op3Op4 Moduloschleifenkör

per

Op1Op2

nopnop Kopie 1

nopnop

Op3Op4 Kopie 1

Prolog

Epilog

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

47Optimierungstechniken in modernen Compilern Grundlagen

Beispiel für Prologgenerierungload [R1] R4

add R3,R4 R5

store R5 [R0]

inc R1

inc R0

dec R2

bne R2,L

<0,0>

<0,0>

<0,1>

<0,1>

<0,1><1,0>

<1,0>

<1,0>

load [R1] R4 add R3,R4 R5 store R5 [R0] inc R1 inc R0 dec R2

bne R2,L

bne R2,L

0 01 2 2 1 2

<1,1>

load [R1] R4 add R3,R4 R5 nop inc R1 nop dec R2 nop

load [R1] R4 nop nop inc R1 nop nop nop

L:

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

48Optimierungstechniken in modernen Compilern Grundlagen

Zusammenfassung Scheduling von Schleifen

Ausrollen einer Schleife zur Bildung längerer Traces: Transformation relativ einfach, Schleifenkörper darf keine Schleifen enthalten, Bedingte Verzweigungen sind zulässig, Es entsteht viel Programmcode, Sprung zum Schleifenanfang stellt Grenze für den

Schedulingalgorithmus dar, an der Ressourcen oft nicht ausgelastet werden.

Moduloscheduling: Komplexe Transformation, Schleifenkörper muss ein Basisblock sein, Kompakter Programmcode, Rücksprung ist keine Grenze für den Schedulingalgorithmus. Transformation von Steuerfluss- in Datenabhängigkeiten, um

bedingte Verzweigungen im Schleifenkörper zuzulassen.

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

49

Vorlesung, Wintersemester 2009/10 M. Schölzel

Optimierungstechniken für superskalare Prozessoren

Behandlung von Steuerflussabhängigkeiten

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

50Optimierungstechniken in modernen Compilern Grundlagen

Bedingte Ausführung und If-Conversion

Technik zur Transformation von Steuerflussabhängigkeiten in Datenabhängigkeiten.

Prinzip: Prozessorarchitektur unterstützt bedingt Ausführung (Guarded

Statements). Guard ist ein 1-Bit-Register, das als zusätzlicher Operand einer

Operation genutzt werden kann. Falls Wert des Guard-Registers 1 ist, wird die Operation normal ausgeführt, sonst wird die Operation nicht ausgeführt.

Verzweigungsbedingungen im Programm werden negiert und nicht negiert in Guard-Register berechnet.

Alle steuerflussabhängigen Operationen erhalten dieses Register als zusätzlichen Operanden.

Spekulative Ausführung nicht mehr möglich, da dann Datenflussabhängigkeit verletzt wäre.

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

51Optimierungstechniken in modernen Compilern Grundlagen

Prinzip If-Conversion

Ziel: Eliminierung von Vorwärtssprüngen in schleifenfreiem Programmcode. Idee:

Jede bedingte Verzweigung berechnet einen neuen Guard-Wert in ein Guardregister, der

• 0 ist, falls die Verzweigungsanweisung gar nicht ausgeführt wird,• 0 ist, falls die Verzweigungsanweisung ausgeführt wird und die Bedingung falsch• 1 ist, falls die Verzweigungsanweisung ausgeführt wird und die Bedingung wahr.

Für jede Anweisung, die mit einem Label versehen ist (angesprungen werden kann) merken der Guardregister, die den Guard-Wert enthalten, der festlegt, ob von der zugehörigen bedingten Verzweigung zu diesem Label verzweigt wurde.

Beim Lauf durch den Steuerflussgraphen bilden eines Ausdrucks, der an der aktuellen Position wahr sein muss, damit diese erreicht wird.

Label: Anweisung

if c then Label

Start

Stopp

Bedingung b muss gelten.

Bedingungen b und c müssen gelten.Bedingungen b und !c müssen gelten.

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

52Optimierungstechniken in modernen Compilern Grundlagen

Algorithmus

Eingabe: azyklischer Steuerflussgraph mit Blöcken b1,...,bn

Es sei i1,...,in die Anweisungsfolge in einer topologischen Sortierung der Blöcke.currentGuard = g, der mit True initialisiert ist.Für jede Anweisung ik mit einem Label wird cond(ik) = gesetztfor j = 1 to n do if(aj besitzt ein Label) then g sei ein unbenutztes Guardregister initialisiert mit currentGuard for each g' cond(aj) do Erzeuge Code g := g or g' od currentGuard = g fi if(aj ist ein bedingter Sprung zum Label L abhängig von c) then al sei die Anweisung mit dem Label L g,g' seien unbenutzte Guardregister Erzeuge Code g := currentGuard and c cond(al) = cond(al) {g} Erzeuge Code g' := currentGuard and !c Ersetze aj durch erzeugten Code currentGuard = g' else Ersetze aj durch currentGuard: aj. fiod

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

53Optimierungstechniken in modernen Compilern Grundlagen

Beispiel

if c1 then l1

s1

if c2 then l2

s2

s3

s5

s6

l1:

l2:

s4

Anweisungen currentGuard und Ausdruck darin

g0 = True

g0 and c1 g1

g1 = c1

g0 and !c1 g0

g0 = !c1

g0 = !c1

g0 : s1

g0 and c2 g2

g0 and !c2 g0

g2 = !c1 and c2

g0 = !c1 and !c2

g2 = (!c1 and !c2) or (c1) = !c2 or c1

g0 : s2

g0 or g1 g3

g3 : s3

g3 : s4

g3 =!c2 or c1

g4 = (!c2 or c1) or (!c1 and c2) = True

g3 or g2 g4

g4 : s5

g4 : s6

g4 = (!c2 or c1) or (!c1 and c2) = True

cond(aj)

Zielcode:

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

54Optimierungstechniken in modernen Compilern Grundlagen

Anwendung von If-Conversion zur Bildung von Hyperblöcken

Kombination von Basisblöcken aus verschiedenen Pfaden des Programms.

Dienen der Unterstützung des Schedulings von stark steuerflussdominierten Programmabschnitten.

Ein Eintrittspunkt; Verlassen an mehreren Positionen möglich. Konstruktion des Hyperblocks aus den Basisblöcken einer Region

(z.B. Schleifenkörper): Initial besteht der Hyperblock aus den Blöcken der Region. Basisblöcke werden anhand folgender Kriterien ausgeschlossen:

• Ausführungshäufigkeit (Ausschluss selten ausgeführter Blöcke),• Größe (Ausschluss großer Basisblöcke, die nicht zum hauptsächlich

ausgeführten Trace der Region gehören),• Charakteristik der Operationen (Ausschluss von BBs mit

Unterprogrammaufrufen und nicht vorhersagbaren Speicherzugriffen). So gebildeter Hyperblock muss zwei Kriterien erfüllen:

Nur ein Eintrittspunkt (evtl. Tail-Duplication durchführen). Darf keine Schleifen enthalten (evtl. Loop-Peeling durchführen).

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

55Optimierungstechniken in modernen Compilern Grundlagen

Beispiel Hyperblockbildung

A

B

E

F

C

D

Start

Stopp

ABCEF

D

Start

Stopp

F'

A

B

E

F

C

D

Start

Stopp

F'

Aus der Region A, B, C, D, E, F wurde der Block D aus dem Hyperblock

ausgeschlossen.

Tail-Duplication wurde durchgeführt.

If-Conversion wurde durchgeführt.

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

56Optimierungstechniken in modernen Compilern Grundlagen

Loop-Peeling

Schleife in einem Hyperblock wird n-mal ausgerollt. Für verbleibende Durchläufe wird der Schleifenkörper kopiert. Konsequenz: Nur wenn die Schleife öfter als n-mal ausgeführt wird,

wird der Hyperblock verlassen.

A

B

C

D

Start

Stopp

A

B

C

D

Start

Stopp

B'

C'

B

C

D