Universität Karlsruhe (TH)

Werbung
Universität Karlsruhe (TH)
Institut für Innovatives Rechnen und Programmstrukturen (IPD)
Übersetzerbau WS 2004/05
Dozent: Prof. Dr.rer.nat. G. Goos
Übungsleiter: Rubino Geiß
Übungsblatt 7
http://www.info.uni-karlsruhe.de/
[email protected]
[email protected]
Ausgabe: 25.01.2005
Besprechung: 03.02.2005
Aufgabe 1: Auswertung Boolescher Ausdrücke
Boolesche Ausdrücke können oft mit bedingten Sprüngen ausgewertet werden. Dabei muss jeweils die Adresse
spezifiziert werden, an der die Berechnung nach dem Sprung fortgesetzt wird. Gegeben sei folgende Syntax
Boolescher Ausdrücke:
conditional clause
boolean expr
boolean expr
boolean op
::=
::=
::=
::=
if boolean expr then stmt list else stmt list end
boolean expr boolean op boolean expr
not boolean expr
and | or
Sprungmarken sollen mit Referenzen auf Knoten des Syntaxbaumes spezifiziert werden, für die der Assembler
später Adressen einsetzen muss. Die Funktion new label liefert jeweils eine neue Sprungmarke.
Geben Sie eine attributierte Grammatik an, die die Auswertung Boolescher Ausdrücke spezifiziert.
Aufgabe 2: Codegenerierung für Signalprozessoren
Betrachten wir eine Standardfilteroperation:
yn := c0 · xn + c1 · xn−1 + c2 · xn−2 + c3 · xn−3
Der Einfachheit wegen ignorieren wir Lade- und Speicheroperationen. Der Berechnungsbaum ist im Folgenden
abgebildet:
*
*
*
+
*
+
REG
*
+
+
REG
Angenommen Multiplikation und Addition können gleichzeitig ausgeführt werden und benötigen einen Takt.
Mit wievielen Takten kann die Berechnung durchgeführt werden?
Aufgabe 3: Codeselektion
Der IA-32 Prozessor kennt u.a. die folgenden Befehle (vereinfacht):
Übersetzerbau WS 2004/05
Befehl
lea dst, (src)
mov dst, src
add op2, op1
lea op3, (op1,op2)
inc op
test op1, op2
cmp op1, op2
jne label
jmp label
label:
#int const
label
S. 2
Bedeutung
Berechne Adresse von src und speichere in dst.
Kopiere src nach dst.
op2 := op1 + op2
op3 := op1 + op2
op := op + 1
Berechnet op1 AND op2 und setzt setzt Conditioncode (CC) Flagbits.
Vergleicht op1 mit op2 und setzt die CC Flagbits.
Wenn das CC Flagbit zero nicht gesetzt ist, springe zu label, sonst führe nächste
Anweisung aus.
Wenn das CC Flagbit less gesetzt ist, springe zu label, sonst führe nächste
Anweisung aus.
Springe zu label
Setzt die Codemarke label.
jl label
eax . . . edx, esi, edi
ri
(ri )
identifier
Übungsblatt 7
Die Operanden können sein:
Register, ebp und esp werden für andere Zwecke benötigt.
Register eax . . . edi direkt, d.h. der Inhalt des Registers ri wird benutzt.
Register indirekt, d.h. der Inhalt des Speichers unter der Adresse Inhalt von ri .
Speicher direkt, d.h. identifier steht für die Adresse, an der die Variable
identifier gespeichert ist.
Integerkonstante mit dem Wert int const.
Codemarke.
Gegeben sei die folgende 3-Adreßzwischensprache:
1
2
3
4
5
6
7
8
ti
ti
ti
ti
ti
ti
ti
ti
:
:
:
:
:
:
:
:
adr identifier
load tj
const int const
plus tj tk
less tj tk
if tj tk
goto tj
store tj tk
ti := Speicheradresse der Variablen identifier
ti := Memory [tj ]
ti := int const
ti := tj + tk
ti := tj < tk
Wenn tj <> 0 springe Anweisung tk sonst führe ti+1 aus
Springe zur Anweisung tj
Memory [tj ] := tk
3.1 on the fly“-Registerzuteilung
”
Die Register werden on the fly“ zugeteilt, d.h. wird ein Wert berechnet, muß ein freies“ Register beschafft
”
”
werden, das diesen Wert aufnimmt. Nachdem der Wert eines Registers in einer anderen Instruktion benutzt
wurde, wird das Register wieder freigegeben. Falls nicht mehr ausreichend viele Register zur Verfügung stehen,
wird die Fehlermeldung Expression too complex ausgegeben und das Programm abgebrochen.
Die Verwaltung der freien/belegten Register wird durch die folgenden Prozeduren erledigt:
PROCEDURE new reg() : INTEGER
liefert die Nummer eines freien Registers,
PROCEDURE release reg(reg : INTEGER)
gibt das Register reg wieder frei.
Implementieren Sie die Prozeduren.
3.2 Codeselektion mit AG’s
Entwerfen Sie eine Attributgrammatik, die fr diese Zwischensprache IA32-Code erzeugt, und Register zuteilt.
Die ti haben die Attribute reg, code und label1 . Der Aufruf der Registerzuteilungsprozeduren kann man sich
1 PROCEDURE
new label():tLabel liefert bei jedem Aufruf eine neue Labelkennung.
Übersetzerbau WS 2004/05
Übungsblatt 7
S. 3
als Berechnungsvorschriften für ein zusätzliches Attribut vorstellen, das in jedem Knoten berechnet werden muß
(vgl. Testen von Bedingungen).
3.3 Codeerzeugung am Beispiel
Erzeugen Sie Zwischen- und IA32-Code für die folgenden Quellsprachanweisungen:
i := 1,
i := i + 1,
i := j + k und
IF i < j THEN min := i ELSE min := j END.
3.4 Optimierung
Geben Sie besseren IA32-Code an.
3.5 Baum Überdeckungen
Wie könnte dieser Code erzeugt werden? Beschreiben Sie Ihr Verfahren.
(Hinweis: Betrachten Sie eine andere Darstellungsform für die Liste der 3-Adreßanweisungen, z.B.: Jede Anweisung ist ein Knoten in einem Baum, die ti sind Kanten zwischen diesen Knoten; oder: Jede Anweisung ist ein
Termkonstruktor, die ti repräsentieren entsprechende Subterme. Anstatt nun für jede Anweisung einzeln Code
zu erzeugen (Makroexpansion) könnte nun Code für einen komplexeren Teilbaum / Subterm erzeugt werden,
vgl. Patternmatching auf Bäumen / Termen.)
3.6 delayed branch“
”
Ältere RISC-Prozessoren, deren Instruktionen in einer Pipeline ausgeführt werden, kennen sogenannte delayed
branch Instruktionen. Bei ihnen wird die ihnen folgende Instruktion ausgeführt, bevor der eigentliche Sprung
erfolgt. Z.B. wird bei der Instruktionsfolge: jmp lab; mov r1, (r2); vor dem Sprung nach lab noch die mov
Instruktion ausgeführt. Man sagt, daß die mov Instruktion im delay slot des verzögerten Sprunges steht.
Angenommen, der IA-32 hätte delayed branch Instruktionen und einen Befehl nop, der nichts macht.
1. Was ist bei der Codeerzeugung zu beachten?
2. Wann kann eine Instruktion, die ursprünglich vor dem normalen“ Sprung ausgeführt werden soll, in das
”
delay slot eines verzögerten Sprunges verschoben werden?
3. Kann auch eine Instruktion nach vorne verschoben werden, die ursprünglich nach dem normalen“ Sprung
”
ausgeführt werden sollte?
4. Es gibt allerdings nicht nur verzögerte Sprünge sondern, z.B. auch verzögerte Speicherladebefehle, deren
Ergebnis erst in der übernächsten Instruktion verwendbar ist. (Der Grund liegt in dem im Vergleich zum
Prozessor langsameren Speicher.) Was ist hierbei zu beachten?
5. Neuere Architekturen verwenden spekulative Auswertung, bei denen ein Zweig als bevorzugt angenommen
wird. Was muß hierbei beachtet werden?
Aufgabe 4: Auswertung von Ausdrücken / lokale Registerzuteilung
Gegeben seien die folgenden Maschinenbefehle:
Befehl
Bedeutung
ld offset, ri ri := Memory [offset]
st offset, ri Memory [offset] := ri
add ri , rj
ri := ri + rj
ri seien Register
4.1 Codeerzeugung
Erzeugen Sie für folgende Ausdrücke Code:
Übersetzerbau WS 2004/05
Übungsblatt 7
S. 4
• (a1 + (a2 + (a3 + (a4 + a5)))) und
• ((((a1 + a2) + a3) + a4) + a5) sowie
• ((((a1 + a2) + a3) + a4) + (a5 + (a6 + (a7 + a8)))).
Verwenden Sie zuerst das Verfahren: zuerst linken, dann rechten Ausdruck auswerten, dann das Verfahren zuerst
rechten, dann linken Ausdruck auswerten.
Wieviele Register benötigen Sie?
4.2 Optimale Registerzuteilung
Gibt es ein besseres Verfahren? (Hinweis: Die Auswertungsreihenfolge wird abhängig vom Ausdruck bestimmt.)
Wann kann dieses Verfahren angewandt werden, welche Probleme können entstehen?
(Siehe [Waite/Goos, 10.2.1])
4.3 Lösung als AG
Geben Sie für Ihr Verfahren eine Attributgrammatik an, die die Anzahl der benötigten Register und die Auswertungsreihenfolge der Operanden bestimmt. Betrachten Sie nullstellige, unäre und binäre Operatoren:
Expr ::= id | const.
Expr ::= op Expr.
Expr ::= Expr op Expr.
4.4 INMOS
Der Transputer [INMOS, The transputer instruction set - a compiler writer’s guide, Prentice Hall 1988] hat
anstatt eines Registersatzes, bei dem auf jedes Register direkt zugegriffen werden kann, einen Auswertungskeller
der Tiefe drei. Jedes Kellerelement hat einen Namen:
Name
A
B
C
Position im Keller
top
bottom
Jeder Prozedur ist eine Prozedurschachtel zugeordnet, in der Variablen gespeichert werden. Diese werden relativ
zum WSP (Workspace Pointer) adressiert. Der Transputer kennt u.a. die folgenden Befehle:
Befehl
LDL offset
STL offset
LDC int const
ADD
SUB
REV
Bedeutung
C := B; B := A; A := Memory [WSP + offset];
Memory [WSP + offset] := A; A := B; B := C; C := undefiniert;
C := B; B := A; A := int const;
A := B + A; B := C; C := undefiniert;
A := B - A; B := C; C := undefiniert;
A,B := B,A; C := C; (vertauscht die Werte von A und B)
Entwerfen Sie ein Schema zur Codeerzeugung, das Spillcode einfügt. Spillcode sind Instruktionen, die eingefügt
werden, um Ausdrücke, für deren Berechnung eigentlich mehr als die verfügbaren Register benötigt werden,
dennoch auswerten zu können. Zum Beispiel: STL/LDL um Zwischenergebnisse abzuspeichern und wieder in
Register zu laden. Die Kostenfunktion, die der Anzahl der Instruktionen entspricht, gilt es zu minimieren.
Betrachten Sie die Grammatik aus Aufgabe 2.3. Die Konvention sei, daß das Ergebnis (d.h. der Wert von Expr0 )
in A erwartet wird. Der Operator op erwartet seine Operanden in den Registern wie folgt:
Regel
Expr0 ::= op Expr1 .
Expr0 ::= Expr1 Op Expr2 .
Konvention
Der Wert von Expr1 in A.
Der Wert von Expr1 in B;Expr2 in A.
Herunterladen