Datenflussanalyse - Klassisch Seminar “Progammanalyse” (SS 2009) Referent: Lorenz Schauer Vortrag: 24.06.2009 Agenda Agenda - Einleitung - Einführung in die Sprache WHILE - Die Intraprozedurale Analyse - Available Expressions Analysis - Reaching Definitions Analysis - Very Busy Expressions Analysis - Live Variables Analysis - Live Variables Analysis - Richtigkeit Folie 2 Einleitung Was bedeutet “Datenflussanalyse”? Ermittlung der Zusammenhänge zwischen einzelnen Stellen im Programm und den darin berechneten Werten. Typische Fragen sind: o Was genau wird in dem Programmabschnitt berechnet? o Wie und wo wird eine bestimmte Variable berechnet? o Welche Werte kann sie annehmen? o Welche Befehle beinflussen welche Variable zu welchem Zeitpunkt? Folie 3 Einleitung Datenflussanalyse – wie und wozu? Wozu? - Primär zur Codeoptimierung - Gegebenenfalls zur Lösung von entstandenen Problemen Wie? - Programmcode analysieren und verstehen (Hilfsmittel: Flussgraph) - Datenflussprobleme erkennen und Gleichung aufstellen - Code optimieren bzw. Probleme lösen Folie 4 Einführung in WHILE Die Sprache: WHILE - Imperative Sprache - Programmcode glieder sich in Blöcke - Jeder Block besitzt ein eindeutiges Etikett (Label) - Bezeichnen Zuweisungen und boolsche Bedingungen - Haben intern keinen Datenfluss Folgende Elemente werden definiert: o Zuweisung o Skip o Bedingung o Sequenz o While-Schleife l [x := a] l [skip] l if [b] then S1 else S2 S1 ; S2 l while [b] do S Folie 5 Intraprozedurale Analyse Intraprozedurale Analyse - Beschäftigt sich mit Elementaraussagen - Gliedert sich in mehrere Datenflussanalysen (spätere Folien) - Unterscheidet Vorwärts- und Rückwärtsanalysen Flussfunktionen (Um Flussgraph aufzustellen) Fluss-Funktion: flow: Stmt P(Lab x Lab) R Rückflussfunktion: flow : Stmt P(Lab x Lab) Beschreiben den Fluss zwischen den Lables der Aussagen Folie 6 Intraprozedurale Analyse - Flussfunktion Wie sieht der Flussgraph von folgendem Code aus ? [ z : 1]1; while[ x 0]2 do([ z : z * y]3 ;[ x : x 1]4 ) Die Flussfunktion liefert folgende Menge an Werten: {(1,2),(2,3),(3,4),(4,2)} Damit können wir den nachfolgenden Graphen zeichnen… Folie 7 Intraprozedurale Analyse - Flussgraph [ z : 1]1; while[ x 0]2 do([ z : z * y]3 ;[ x : x 1]4 ) [z:=1] [x>0] no yes [z:=z*y] [x:=x-1] Folie 8 Available Expressions Analysis Available Expressions Analysis o Analyse Algorithmus (Vorwärtsanalyse) o Beschreibt die Verfügbarkeit einzelner Ausdrücke an bestimmten Programmstellen o Frage: Welche Ausdrücke / Werte sind an einer bestimmten Programmstelle gültig? o Ziel: Codeoptimierung o Beispiel: [ x : a b]1;[ y : a * b]2 ; while[ y a b]3 do([a : a 1]4 ;[ x : a b]5 ) Folie 9 Available Expressions Analysis Definition von kill- und gen-Funktionen Kill-Funktion: Ausdruck ist killed, wenn eine der Variablen verändert wird (Innerhalb des Blocks). killAE : Blocks P(AExp) Gen-Funktion: Ausdruck wird im Programmbereich generiert und keine Variable davon innerhalb des Blocks verändert. genAE : Blocks P(AExp) Folie 10 Available Expressions Analysis kill- und gen-Funktionen bei AEA kill AE ([ x : a]l ) {a' AExp* | x FV (a' )} kill AE ([ skip]l ) {} kill AE ([b]l ) {} gen AE ([ x : a ]l ) {a' AExp(a) | x FV (a ' )} gen AE ([ skip]l ) {} gen AE ([b]l ) AExp(b) Folie 11 Available Expressions Analysis Entry- & Exit-Funktionen Durch diese beiden Funktionen wird die Analyse bestimmt: AEentry , AEexit : Lab* P( AExp* ) AEentry (l ) {} Falls: l init (S* ) AEentry (l ) { AEexit (l ' ) | (l ' , l ) flow( S* )} AEexit (l ) ( AEentry (l ) \ kill AE ( B l )) gen AE ( B l ) B l blocks( S* ) Folie 12 Available Expressions Analysis – Beispiel1 Beispiel 1: [ z : x y]l ; while[true]l ' do[ skip]l '' o Nur Block 1 generiert den Ausdruck: {x+y} o Andere generieren / killen keine Ausdrücke o Der Flussgraph sieht wie folgt aus: […] l […] l ' no yes l '' […] Folie 13 Available Expressions Analysis – Beispiel1 Gesucht wird: größte Lösung der Gleichung für AEentry [ z : x y]l ; while[true]l ' do[ skip]l '' Bestimmen der AE-Gleichungen: AEentry (l ) {} AEentry (l ' ) AEexit (l ) Aexit (l ' ' ) AEentry (l ' ' ) AEexit (l ' ) AEexit (l ) AEentry (l ) {x y} AEexit (l ' ) AEentry (l ' ) AEexit (l ' ' ) AEentry (l ' ' ) Folie 14 Available Expressions Analysis – Beispiel1 Wir erhalten: AEentry (l ' ) {x y} AEentry (l ' ) Deutung: o Es gibt 2 Lösungen für die Gleichung: - {x+y} - die leere Menge o Informativ aber nur {x+y} o {x+y} stellt die größte Lösung der Gleichung dar. => Der Ausdruck {x+y} ist jedesmal verfügbar, wenn l’ betreten wird (hier: Schleifeneintritt) Folie 15 Available Expressions Analysis – Beispiel2 Beispiel 2: [ x : a b]1;[ y : a * b]2 ; while[ y a b]3 do([ a : a 1]4 ;[ x : a b]5 ) Aufstellen der kill & gen Funktionen: gen AE (l ) kill AE (l ) l ---------------------------------------------------{} {a b} 1 {a * b} 2 {} {a b} 3 {} 4 {a b, a * b, a 1} {} {a b} 5 {} Folie 16 Available Expressions Analysis – Beispiel2 Aufstellen der AE-Funktionen: AEentry (1) {} AEexit (1) AEentry (1) {a b} AEentry (2) AEexit (1) AEexit (2) AEentry (2) {a * b} AEentry (3) AEexit (2) AEexit (5) AEexit (3) AEentry (3) {a b} AEentry (4) AEexit (3) AEexit (4) AEentry (4) \ {a b, a * b, a 1} AEentry (5) AEexit (4) AEexit (5) AEentry (5) {a b} [ x : a b]1;[ y : a * b]2 ; while[ y a b]3 do([ a : a 1]4 ;[ x : a b]5 ) Folie 17 Available Expressions Analysis – Beispiel2 Als Ergebnis erhält man folgende Tabelle: AEentry (l ) l AEexit (l ) ---------------------------------------------{a b} 1 {} {a b, a * b} 2 {a b} {a b} {a b} 3 {} {a b} 4 {a b} {} 5 [x:=a+b] [y:=a*b] [y>a+b] [a:=a+1] [x:=a+b] [ x : a b]1;[ y : a * b]2 ; while[ y a b]3 do([ a : a 1]4 ;[ x : a b]5 ) Folie 18 Available Expressions Analysis – Beispiel2 Deutung: o Der Ausdruck a wird innerhalb der Schleife neu definiert o Der Ausdruck {a+b} ist immer am Schleifeneingang verfügbar o {a*b} nur beim ersten Schleifeneingang verfügbar wird vor dem nächsten Durchlauf gekilled Folie 19 Reaching Definition Analysis Reaching Definition Analysis o sehr ähnlich zur AE-Analyse (Vorwärtsanalyse) o Frage: Welche Definition/Zuweisung ist bei einer bestimmten Stelle im Programm gültig? o Ziele: Kenntnis über die jeweilige Gültigkeit einer Zuweisung o Beispiel: [ x : a b]1;[ y : a * b]2 ; while[ y a b]3 do([a : a 1]4 ;[ x : a b]5 ) Nach Label 2: (x,1),(y,2) Nach Label 3: (x,1),(y,2),(a,4),(x,5) Folie 20 Reaching Definition Analysis - Vorgehensweise Vorgehensweise o Definieren der killRD, genRD, RDentry und RDexit funktionen: kill RD ([ x : a]l ) {( x, ?)} {( x, l ' ) | B l ' asgm _ to _ x( S* )} kill RD ([ skip]l ) {} kill RD ([b]l ) {} genRD ([ x : a ]l ) {( x, l )} genRD ([ skip]l ) {} genRD ([b]l ) {} Folie 21 Reaching Definition Analysis - Vorgehensweise RDentry (l ) {( x, ?) | x FV ( S* )} if l init ( S* ) {RDentry (l ' ) | (l ' , l ) flow( S* )} RDexit (l ) ( RDentry (l ) \ kill RD ( B l )) genRD ( B l ) wo B l blocks( S* ) Folie 22 Reaching Definition Analysis - Beispiel o Funktionen am Programmteil anwenden: 1 2 3 4 5 Beispiel: [ x : 5] ;[ y : 1] ; while[ x 1] do([ y : x * y] ;[ x : x 1] ) Es entsteht folgende Tabelle der kill & gen Funktionen: genRD (l ) kill RD (l ) ------------------------------------------------------------------------{( x,1)} 1 {( x, ?), ( x,1), ( x,5)} {( y ,2)} 2 {( y , ?), ( y ,2), ( y ,4)} {} 3 {} {( y ,4)} 4 {( y , ?), ( y ,2), ( y ,4)} 5 {( x, ?), ( x,1), ( x,5)} {( x,5)} Folie 23 Reaching Definition Analysis - Beispiel Damit ergibt sich für die RD Funktionen (1): RDentry (l ) RDexit (l ) _______________________________________________________ ( RDentry (1) \ {( x, ?), ( x,1), ( x,5)}) {( x,1)} 1 {( x, ?), ( y, ?)} 2 RDexit (1) 3 RDexit (2) RDexit (5) ( RDentry (2) \ {( y, ?), ( y,2), ( y,4)}) {( y,2)} 4 RDexit (3) ( RDentry (4) \ {( y, ?), ( y,2), ( y,4)}) {( y,4)} 5 RDexit (4) ( RDentry (5) \ {( x, ?), ( x,1), ( x,5)}) {( x,5)} RDentry (3) [ x : 5]1;[ y : 1]2 ; while[ x 1]3 do([ y : x * y]4 ;[ x : x 1]5 ) Folie 24 Reaching Definition Analysis - Beispiel Damit ergibt sich für die RD Funktionen (2): RDexit (l ) RDentry (l ) _______________________________________________________ ({( x, ?), ( y, ?)} \ {( x, ?), ( x,1), ( x,5)}) {( x,1)} 1 {( x, ?), ( y, ?)} ( RDexit (1) \ {( y, ?), ( y,2), ( y,4)}) {( y,2)} 2 ( RDentry (1) \ {( x, ?), ( x,1), ( x,5)}) {( x,1)} 3 ( RDentry (2) \ {( y, ?), ( y,2), ( y,4)}) {( y,2)} ( RDentry (5) \ {( x, ?), ( x,1), ( x,5)}) {( x,5)} RDexit (2) RDexit (5) 4 RDentry (3) ( RDexit (3) \ {( y, ?), ( y,2), ( y,4)}) {( y,4)} 5 ( RDentry (4) \ {( y, ?), ( y,2), ( y,4)}) {( y,4)} ( RDexit (4) \ {( x, ?), ( x,1), ( x,5)}) {( x,5)} [ x : 5]1;[ y : 1]2 ; while[ x 1]3 do([ y : x * y]4 ;[ x : x 1]5 ) Folie 25 Reaching Definition Analysis - Beispiel Damit ergibt sich für die RD Funktionen (3): RDexit (l ) RDentry (l ) _______________________________________________________ {( y, ?), ( x,1)} 1 {( x, ?), ( y, ?)} 2 ({( x, ?), ( y, ?)} \ {( x, ?), ( x,1), ( x,5)}) {( x,1)} 3 ({( y, ?), ( x,1)} \ {( y, ?), ( y,2), ( y,4)}) {( y,2)} ({( y, ?), ( x,1)} \ {( y, ?), ( y,2), ( y,4)}) {( y,2)} {( x,1), ( y,2)} RDexit (5) ( RDentry (4) \ {( x, ?), ( x,1), ( x,5), ( y, ?), ( y,2), ( y,4)}) {( y,4)} {( x,5)} 4 RDentry (3) ({( x,1), ( y,2)} RDexit (5) \ {( y, ?), ( y,2), ( y,4)}) 5 ( RDentry (3) \ {( y, ?), ( y,2), ( y,4)}) {( y,4)} {( y,4)} ( RDexit (4) \ {( x, ?), ( x,1), ( x,5)}) {( x,5)} [ x : 5]1;[ y : 1]2 ; while[ x 1]3 do([ y : x * y]4 ;[ x : x 1]5 ) Folie 26 Reaching Definition Analysis - Beispiel Damit ergibt sich für die RD Funktionen (4): RDexit (l ) RDentry (l ) _______________________________________________________ {( y, ?), ( x,1)} 1 {( x, ?), ( y, ?)} 2 {( y, ?), ( x,1)} 3 {( x,1), ( y,2), ( y,4), ( x,5)} {( x,1), ( y,2)} 4 {( x,1), ( y,2), ( y,4), ( x,5)} 5 ( RDentry (3) \ {( y, ?), ( y,2), ( y,4)}) {( y,4)} {( x,1), ( y,4), ( x,5)} ( RDexit (4) \ {( x, ?), ( x,1), ( x,5)}) {( x,5)} {( x,1), ( y,2)} RDexit (5) [ x : 5]1;[ y : 1]2 ; while[ x 1]3 do([ y : x * y]4 ;[ x : x 1]5 ) Folie 27 Reaching Definition Analysis - Beispiel Damit ergibt sich für die RD Funktionen (5): RDentry (l ) RDexit (l ) _______________________________________________________ {( y, ?), ( x,1)} 1 {( x, ?), ( y, ?)} 2 {( y, ?), ( x,1)} 3 {( x,1), ( y,2), ( y,4), ( x,5)} 4 {( x,1), ( y,2), ( y,4), ( x,5)} 5 {( x,1), ( y,4), ( x,5)} {( x,1), ( y,2)} {( x,1), ( y,2), ( y,4), ( x,5)} {( x,1), ( y,4), ( x,5)} {( y,4), ( x,5)} [ x : 5]1;[ y : 1]2 ; while[ x 1]3 do([ y : x * y]4 ;[ x : x 1]5 ) Somit sind alle RD-Funktionen aufgelöst. Deutung: Man erkennt nun, welche Zuweisung an welcher Stelle existiert! Folie 28 Very Busy Expressions Analysis Very Busy Expressions Analysis o Ein Ausdruck wird als „very busy“ bezeichnet, wenn: - am Ende eines Labels sichergestellt ist, dass er im weiteren Verlauf auf jeden Fall gebraucht wird. => Wichtig: Der Ausdruck muss verwendet bzw. betrachtet werden bevor einer seiner Werte verändert wird! o Es handelt sich um eine Rückwärtsanalyse o Ziel: Codeoptimierung Folie 29 Very Busy Expressions Analysis Veranschaulichung und Analyse am Beispiel: if [a b]1 then([ x : b a]2 ;[ y : a b]3 )else ([ y : b a]4 ;[ x : a b]5 ) o Die Ausrücke {a-b} und {b-a} sind „very busy“ zum Zeitpunkt 1 o Um das Programm zu analysieren müssen wieder alle Funktionen aufgestellt werden! Folie 30 Very Busy Expressions Analysis o Hier gleich angewendet (allgemeine Formeln nachlesen!) l killVB (l ) genVB (l ) 1 2 {} {} {} {b a} 3 4 {} {} {a b} {b a} 5 {} {a b} o kill & gen Funktionen: o VB Funktionen: l VBentry (l ) VBexit (l ) 1 VBexit (1) VBentry (2) VBentry (4) 2 VBexit (2) {b a} VBentry (3) 3 {a b} 4 VBexit (4) {b a} 5 {a b} {} VBentry (5) {} Folie 31 Very Busy Expressions Analysis Nach Vereinfachung erhält man: l VBentry (l ) VBexit (l ) 1 {a b, b a} {a b, b a} 2 {a b, b a} {a b} 3 {a b} 4 {a b, b a} 5 {a b} {} {a b} {} o Deutung: Aus dieser Tabelle lässt sich nun jeder Ausdruck, der zu einem bestimmten Zeitpunkt „very busy“ ist, ablesen. Folie 32 Live Variables Analysis Live Variables Analysis o Eine Variable wird als „live“ bezeichnet, wenn: - sie am Ende eines Labels einen Wert enthält, der später benötigt werden könnte. o Rückwärtsanalyse o Verwendung: - Dead code elimination (Variable nicht live – Zuweisungsblock löschen) - Registerzuweisung Folie 33 Live Variables Analysis Beispiel: [ x : 2]1;[ y : 4]2 ;[ x : 1]3 ; (if [ y x]4 then[ z : y]5 else[ z : y * y]6 ); [ x : z ]7 Frage: Welche variablen sind zu welchem Zeitpunkt „live“? Antwort: x nach Label 1 ist nicht live x nach Label 3 live y nach Label 2 live => Erste Zuweisung ist Redundant, kann also gelöscht werden. Folie 34 Live Variables Analysis Definitionen der kill, gen und LV Funktionen: kill LV ([ x : a ]l ) {x} kill LV ([ skip]l ) {} kill LV ([b]l ) {} genLV ([ x : a ]l ) FV (a ) genLV ([ skip]l ) {} genLV ([b]l ) FV (a ) LVexit (l ) {} falls l final ( S* ) {LVentry (l ' ) | (l ' , l ) flow R ( S* )} LVentry (l ) ( LVexit (l ) \ kill LV ( B l )) genLV ( B l ) wo B l blocks( S* ) Folie 35 Live Variables Analysis Analyse nach Aufstellen der gen, kill und LV Funktionen ergibt folgendes: l 1 2 3 4 5 6 7 kill LV (l ) {x} { y} {x} genLV (l ) {x, y} { y} { y} {z} {z} {z} {x} l LVentry (l ) LVexit (l ) 1 LVexit (1) \ {x} LVentry (2) 2 LVexit (2) \ { y} LVentry (3) 3 LVexit (3) \ {x} LVentry (4) 4 LVexit (4) {x, y} LVentry (5) LVentry (6) 5 ( LVexit (5) \ {z}) { y} LVentry (7) 6 ( LVexit (6) \ {z}) { y} LVentry (7) 7 {z} Folie 36 Live Variables Analysis Durch einsetzten und vereinfachen erhält man wieder die Ergebnistabelle: l 1 2 3 4 5 6 7 LVentry (l ) {} {} { y} { x, y} { y} { y} { z} LVexit (l ) {} { y} { x, y} { y} { z} { z} {} Deutung: - Alle „live“-Variablen bzgl ihrem Programmpunkt ablesbar - Am Programmende sind alle Variablen tot – nicht „live“ Folie 37 Live Variables Analysis - Richtigkeit Die Richtigkeit der Live Variables Analysis o Um Richtigkeit zu zeigen, benutzen wir folgendes Theorem: 1. falls S , 1 S ' , 1' und 1 ~ N (init( S )) 2 2' : S , 2 S ' , 2' 2. falls S , 1 1' 2' : S , 2 2' dann und 1' ~ N (init( S ' )) 2' und 1 ~ N (init( S )) 2 und dann und 1' ~ X (init( S )) 2' Folie 38 Live Variables Analysis - Richtigkeit Veranschaulichung am Beispiel: [ x : y z ]l , 1 , V1 = {y,z} und V2 = {x} o 1 ~V 1 2 1 ( y) 2 ( y) 1 ( z ) 2 ( z ) o 1 ~V 2 2 1 ( x) 2 ( x) o [ x : y z ]l , 1 1' [ x : y z ]l , 2 2' o Nach Theorem und 1 ~V 1 2 1' ~V 2 2' folgt, dass wenn V2 nach dem Block live ist, muss V1 davor live sein. Folie 39 Servus Vielen Dank für die Aufmerksamkeit! Folie 40