28.06.2013 Aufrufe

Datenflußanalyse

Datenflußanalyse

Datenflußanalyse

MEHR ANZEIGEN
WENIGER ANZEIGEN

Sie wollen auch ein ePaper? Erhöhen Sie die Reichweite Ihrer Titel.

YUMPU macht aus Druck-PDFs automatisch weboptimierte ePaper, die Google liebt.

<strong>Datenflußanalyse</strong><br />

Christoph Dreyer<br />

Projektgruppe Programmanalyse für Java<br />

1


<strong>Datenflußanalyse</strong><br />

<strong>Datenflußanalyse</strong> wird in Compilern benutzt.<br />

Sie liefert Informationen über das Programm.<br />

Diese werden zur Optimierung genutzt.<br />

Compiler<br />

<br />

Optimierung<br />

<br />

Analyse<br />

<br />

Kontrollflußanalyse<br />

<br />

<br />

Transformation<br />

<strong>Datenflußanalyse</strong><br />

<strong>Datenflußanalyse</strong> ist nicht nur zur Optimierung nützlich.<br />

Auch für andere Zwecke formuliert man Datenflußprobleme.<br />

Sie können dann mit Standardverfahren gelöst werden.<br />

2


Programmanalyse<br />

Was wird berechnet?<br />

f0 = 0;<br />

f1 = 1;<br />

if (m ≤ 1) {<br />

return m;<br />

}<br />

else {<br />

i = 2;<br />

while (i ≤ m) {<br />

f2 = f0 + f1;<br />

f0 = f1;<br />

f1 = f2;<br />

i++;<br />

}<br />

return f2;<br />

}<br />

Wie wird f2 berechnet?<br />

Welche Werte kann f0 haben?<br />

Wo wird f0 berechnet?<br />

3


Ziele<br />

• Datenflußprobleme kennen<br />

• Datenflußgleichungen aufstellen können<br />

• Lösungsverfahren verstehen<br />

4


Überblick<br />

1. ein Datenflußproblem<br />

2. Datenflußgleichungen<br />

3. ein Lösungsverfahren<br />

4. andere Probleme<br />

5. Verbesserungen des Algorithmus<br />

6. ein anderes Verfahren<br />

5


Erreichende Definitionen<br />

Welche Definitionen erreichen eine bestimmte Verwendung?<br />

Definition einer Variablen Der Variablen wird ein Wert<br />

zugewiesen<br />

Zerstören einer Definition Eine spätere Definition weist<br />

derselben Variable einen Wert zu<br />

Definition erreicht Verwendung Zwischen Definition<br />

und Verwendung wird die Definition nicht zerstört<br />

x = 0;<br />

x = 1;<br />

y = x + 1;<br />

6


Programmablauf<br />

Die Menge der erreichenden Definitionen ist unabhängig<br />

vom Programmablauf.<br />

x = 0;<br />

if (a = 0) {<br />

x = 1;<br />

}<br />

y = x + 1;<br />

Eine Definition erreicht alle möglichen Verwendungen.<br />

→ Ergebnismenge nicht exakt, sondern zu groß.<br />

→ Suche nach kleinster Menge<br />

7


Kontrollflußanalyse<br />

Die Kontrollflußanalyse liefert einen Ablaufgraph auf dem<br />

die <strong>Datenflußanalyse</strong> durchgeführt wird.<br />

Kontrollflußanalyse<br />

Ablaufgraph<br />

<br />

<strong>Datenflußanalyse</strong><br />

B2<br />

Y<br />

<br />

<br />

<br />

<br />

<br />

entry<br />

<br />

B1<br />

B5<br />

<br />

exit<br />

<br />

<br />

N<br />

N <br />

<br />

B3<br />

<br />

<br />

B4<br />

Y <br />

B6<br />

<br />

8


Definitionen<br />

Jeder Definition wird eine Nummer zugeordnet.<br />

Block Variable Nummer<br />

B1 m 1<br />

B1 f0 2<br />

B1 f1 3<br />

B3 i 4<br />

B6 f2 5<br />

B6 f0 6<br />

B6 f1 7<br />

B6 i 8<br />

GEN[b] Menge der erzeugten Definitionen<br />

KILL[b] Menge der zerstörten Definitionen<br />

Ein Block zerstört die durch ihn erzeugten Definitionen.<br />

9


Datenflußgleichungen<br />

Wenn der erste Befehl eines Grundblocks ausgeführt wird,<br />

dann auch alle anderen.<br />

in[b] Definitionen, die den Block erreichen<br />

out[b] Definitionen, die den Block verlassen<br />

By<br />

Y<br />

<br />

<br />

<br />

<br />

<br />

Bx<br />

<br />

N<br />

Bz<br />

Eine Definition erreicht einen Block, wenn sie einen der<br />

Vorgängerblöcke verlassen hat.<br />

in[b] = ∪ p∈P RED[b] out[p]<br />

Eine Definition verläßt einen Block, wenn sie entweder in<br />

ihm erzeugt wurde oder ihn erreicht hat und nicht zerstört<br />

wurde.<br />

out[b] = GEN[b] ∪ (in[b] \ KILL[b])<br />

10


iterativer Algorithmus<br />

for all (b ∈ BLOCK) {<br />

out[b] = GEN[b];<br />

}<br />

do {<br />

change = false;<br />

for all (b ∈ BLOCK) {<br />

in[b] = ∪ p∈P RED[b] out[p];<br />

oldout = out[b];<br />

out[b] = GEN[b] ∪ (in[b] \ KILL[b]);<br />

if (out[b] = oldout) {<br />

change = true;<br />

}<br />

}<br />

}<br />

while (change == true);<br />

11


Beispiel<br />

Die Blöcke B4 und B6 bilden zusammen eine Schleife.<br />

<br />

<br />

B4 <br />

<br />

B6<br />

Der Block B6 enthält die Befehle des Schleifenrumpfs.<br />

f2 = f0 + f1;<br />

f0 = f1;<br />

f1 = f2;<br />

i++;<br />

GEN[B6]= {5, 6, 7, 8}<br />

KILL[B6]= {2, 3, 4, 5, 6, 7, 8}<br />

in1[B6] = out1[B4] = ∅<br />

out1[B6] = {5, 6, 7, 8}<br />

in2[B6] = out2[B4] = {1, 2, 3, 4, 5, 6, 7, 8}<br />

out2[B6] = {1, 5, 6, 7, 8}<br />

12


Upwards Exposed Uses<br />

Welche Verwendungen erreichen eine bestimmte Definition?<br />

x = 0<br />

<br />

<br />

<br />

<br />

x = 1<br />

y = x + 1 z = x + 1<br />

<br />

Verwendungen bewegen sich von unten nach oben.<br />

Es handelt sich um ein Rückwärtsproblem.<br />

out[b] = ∪ s∈SUCC[b] in[s]<br />

in[b] = GEN ′ [b] ∪ (out[b] \ KILL ′ [b])<br />

13


Verfügbare Ausdrücke<br />

Welche Ausdrücke sind an einem Punkt verfügbar?<br />

<br />

x = a + b<br />

<br />

z = a + b<br />

<br />

<br />

<br />

<br />

<br />

y = a + b<br />

Der verfügbare Ausdruck muß auf jedem Pfad berechnet<br />

werden.<br />

Es handelt sich um ein Allproblem.<br />

in[b] = ∩ p∈P RED[b] out[p]<br />

Problem Konfluenzoperator gesuchte Lösung<br />

Existenzproblem ∪ minimale Lösung<br />

Allproblem ∩ maximale Lösung<br />

14


Mengen<br />

Mengen werden mit Bitvektoren implementiert.<br />

Block Variable Nummer<br />

B1 m 1<br />

B1 f0 2<br />

B1 f1 3<br />

B3 i 4<br />

B6 f2 5<br />

B6 f0 6<br />

B6 f1 7<br />

B6 i 8<br />

Nummer der Definition entspricht Position im Bitvektor.<br />

GEN[B6] = 〈0, 0, 0, 0, 1, 1, 1, 1〉<br />

KILL[B6] = 〈0, 1, 1, 1, 1, 1, 1, 1〉<br />

Datenflußgleichungen:<br />

in[b] = ∨ p∈P RED[b] out[p]<br />

out[b] = GEN[b] ∨ (in[b] ∧ ¬KILL[b])<br />

15


Transferfunktion<br />

Transferfunktion F b berechnet den Effekt eines Blocks.<br />

out[b] = F b(in[b])<br />

F b(x) = GEN ∨ (x ∧ ¬KILL)<br />

Die Menge P RSV [b] (preserve) enthält die Definitionen,<br />

die durch den Block nicht beeinflußt werden.<br />

P RSV = ¬KILL<br />

F b(x) = GEN ∨ (x ∧ P RSV )<br />

P RSV [B6] = 〈1, 0, 0, 0, 0, 0, 0, 0〉<br />

F B6(x) = 〈x1, 0, 0, 0, 1, 1, 1, 1〉<br />

Datenflußgleichungen →<br />

→ Transferfunktionen und Konfluenzoperator<br />

16


Beschleunigung<br />

Zur Lösung des Datenflußproblems reicht im Idealfall ein<br />

Durchlauf durch den Ablaufgraph.<br />

Bx<br />

Y<br />

<br />

<br />

<br />

<br />

<br />

<br />

Bw<br />

Bz<br />

<br />

<br />

<br />

N <br />

<br />

By<br />

Schleifenköpfe müssen mehrmals berechnet werden. Nach<br />

jeder Änderung müssen auch alle abhängigen Blöcke neu<br />

berechnet werden.<br />

<br />

<br />

B4 <br />

<br />

B6<br />

in[B4] = out[B3] ∪ out[B6]<br />

in[B6] = out[B4]<br />

Bei Schleifen, die hintereinander ausgeführt werden, addieren<br />

sich die zusätzlichen Berechnungen.<br />

17


Reihenfolge<br />

In und zwischen Schleifen profitiert man von der richtigen<br />

Reihenfolge.<br />

Vorwärtsrichtung: Knoten vor allen Nachfolgern besuchen<br />

Rückwärtsrichtung: Knoten vor allen Vorgängern besuchen<br />

Bx<br />

Y<br />

<br />

<br />

<br />

<br />

<br />

<br />

Bw<br />

Bz<br />

<br />

<br />

<br />

N <br />

<br />

By<br />

Richtung Reihenfolge Beispiel<br />

vorwärts topologisch Bw, By, Bx, Bz<br />

rückwärts postorder Bz, Bx, By, Bw<br />

18


Strukturbasierte Analyse<br />

Anderes Verfahren zum Lösen von Datenflußgleichungen.<br />

Verallgemeinerung der Intervallanalyse.<br />

Gemeinsamkeiten mit iterativem Verfahren:<br />

• Transferfunktionen<br />

• Konfluenzoperator<br />

• Initialisierungswerte<br />

Kontrollflußanalyse liefert jetzt control tree.<br />

Control tree enthält Grundblöcke und abstrakte Blöcke.<br />

Abstrakte Blöcke fassen Grundblöcke zusammen.<br />

19


Verfahren<br />

Zunächst Berechnung der Transferfunktionen für die<br />

Grundblöcke.<br />

Lösung wird mit zwei Durchläufen durch den control tree<br />

berechnet.<br />

<br />

entrya<br />

entry B1a<br />

<br />

<br />

B1 B2 B3a<br />

<br />

B3 B4a<br />

<br />

B4 B6<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

exit<br />

B5<br />

Im ersten Durchlauf werden bottom-up die Transferfunktionen<br />

der abstrakten Blöcke berechnet.<br />

Im zweiten Durchlauf werden top-down für jeden Block<br />

Datenflußgleichungen aufgestellt und gelöst.<br />

20


lock-Konstrukt<br />

Alle Blöcke werden der Reihe nach ausgeführt.<br />

<br />

<br />

B3a<br />

B3 B4a<br />

<br />

<br />

<br />

<br />

<br />

Transferfunktion:<br />

<br />

block<br />

B5<br />

F B3a = F B5 ◦ F B4a ◦ F B3<br />

Datenflußgleichungen:<br />

in[B3] = in[B3a]<br />

in[B4a] = F B3(in[B3])<br />

in[B5] = F B4a(in[B4a])<br />

21


if-then-else-Konstrukt<br />

Zuerst wird der Block ausgeführt, der die Bedingung auswertet,<br />

danach einer der beiden anderen Blöcke.<br />

<br />

<br />

<br />

B1a<br />

B1 B2 B3a<br />

<br />

Transferfunktion:<br />

<br />

if-then-else<br />

<br />

<br />

<br />

<br />

<br />

F B1a = (F B2 ◦ F B1) ∨ (F B3a ◦ F B1)<br />

Datenflußgleichungen:<br />

in[B1] = in[B1a]<br />

in[B2] = F B1(in[B1])<br />

in[B3a] = F B1(in[B1])<br />

22


while-Konstrukt<br />

Die Bedingung wird ausgewertet, danach die Schleife entweder<br />

verlassen oder der Schleifenrumpf ausgeführt und<br />

noch einmal die Bedingung ausgewertet.<br />

<br />

<br />

B4a<br />

<br />

B4 B6<br />

Transferfunktion:<br />

while<br />

F B4a’ = (F B6 ◦ F B4) ∨ id<br />

F B4a = F B4 ◦ F B4a’<br />

Datenflußgleichungen:<br />

in[B4] = F B4a’(in[B4a])<br />

in[B6] = F B4a(in[B4])<br />

23


improper region<br />

Einteilung in Gruppen:<br />

acyclic keine rückführenden Kante<br />

cyclic mit Rückwärtskante<br />

improper Schleife mit mehreren Eingängen<br />

Ablaufgraph einer improper region:<br />

By<br />

<br />

<br />

<br />

<br />

Bx<br />

<br />

<br />

<br />

<br />

<br />

Bz<br />

Datenflußgleichungen sind rekursiv:<br />

in[Bx] = in[Bxa]<br />

in[By] = F Bx(in[Bx]) ∨F Bz(in[Bz])<br />

in[Bz] = F Bx(in[Bx]) ∨F By(in[By])<br />

24


Knotenaufspaltung<br />

Gleichungen werden mit iterativem Verfahren gelöst.<br />

By<br />

<br />

<br />

<br />

<br />

Bx<br />

<br />

<br />

<br />

<br />

<br />

Bz<br />

Oder durch Knotenaufspaltung:<br />

By<br />

<br />

<br />

Bx<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

Bz<br />

Bza<br />

Neue Schleife hat nur einen Eingang.<br />

25


Zusammenfassung<br />

<strong>Datenflußanalyse</strong> liefert Informationen über Programm.<br />

Ergebnisse gelten für alle Programmabläufe.<br />

Klassifizierung nach . . .<br />

• Flußrichtung (vorwärts oder rückwärts)<br />

• Allproblem oder Existenzproblem (Konfluenzoperator)<br />

Transferfunktion aufstellen, dann Lösung berechnen.<br />

viele Verfahren, hier: iterativ und strukturbasiert.<br />

Aspekt iterativ strukturbasiert<br />

Geschwindigkeit schnell schneller<br />

Implementierung einfach kompliziert<br />

Transformationen neue Berechnung Änderung<br />

26


Ausblick<br />

<strong>Datenflußanalyse</strong> wird auch benutzt, . . .<br />

• zur interprozeduralen <strong>Datenflußanalyse</strong><br />

• um Decknamen zu bestimmen<br />

• um Typinformationen zu berechnen<br />

• zur Verfifikation von Programmen<br />

27

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!