367 lines
18 KiB
TeX
367 lines
18 KiB
TeX
% !TeX spellcheck = de_DE
|
|
\documentclass[11pt,a4paper,toc]{scrartcl}
|
|
\usepackage[a4paper,left=2.5cm,right=2.5cm,top=2.5cm,bottom=2.5cm]{geometry}
|
|
\usepackage[ngerman]{babel}
|
|
\usepackage{amssymb}
|
|
\usepackage{scrextend}
|
|
\usepackage[utf8]{inputenc}
|
|
\usepackage{amsmath}
|
|
\usepackage{enumitem}
|
|
\usepackage{mathtools}
|
|
\usepackage[load=named]{siunitx}
|
|
\usepackage{csquotes}
|
|
\usepackage[hidelinks]{hyperref}
|
|
%\usepackage{listings}
|
|
\usepackage{algorithmicx}
|
|
\usepackage{algpseudocode}
|
|
%\usepackage{pgfplots}
|
|
\usepackage{tikz}
|
|
%\usetikzlibrary{positioning}
|
|
%\usetikzlibrary{arrows.meta}
|
|
%\usetikzlibrary{quotes}
|
|
%\usetikzlibrary{angles}
|
|
%\usetikzlibrary{babel}
|
|
%\usetikzlibrary{fit}
|
|
%\usepackage{datetime}
|
|
%\usepackage{xcolor}
|
|
|
|
%\pdfminorversion=7 % Import-Unterstützung für PDFs bis Version 1.7
|
|
%\pgfplotsset{compat=1.16} % verhindern, dass pgfplots im Rückwärtskompatibilitätsmodus arbeitet
|
|
|
|
|
|
\setlist[enumerate,1]{label={\arabic*.}}
|
|
\setlist[enumerate,2]{label={\alph*)}}
|
|
|
|
\title{Optimierungen in Übersetzern: Verfahren}
|
|
\author{Marco Ammon (my04mivo)}
|
|
\date{\today}
|
|
|
|
\makeatletter
|
|
\g@addto@macro\bfseries{\boldmath}
|
|
\makeatother
|
|
|
|
\begin{document}
|
|
\maketitle
|
|
|
|
\tableofcontents
|
|
\clearpage
|
|
\section{Kontrollflussanalyse}
|
|
\subsection{Kontrollflussgraph}
|
|
\begin{itemize}
|
|
\item Gerichteter Graph
|
|
\item Knoten: Grundblöcke (meist maximal)
|
|
\item Kante zwischen zwei Blöcken $A$ und $B$ wenn $B$ direkt nach $A$ ausgeführt werden kann (etwa [un-]bedingter Sprung oder Fallthrough)
|
|
\item Synthetische Ergänzung um Entry- und Exit-Knoten, die mit Kante verbunden sind
|
|
\item Kontrollflussabhängigkeit: Bei Verzweigungsknoten $v$ mit direkten Nachfolgern $a$ und $b$: $y$ kontrollflussabhängig von $v$ $\Leftrightarrow$ mindestens ein Pad von $a$ zum Exit-Knoten ohne $y$ und jeder Pfad von $b$ zum Exit-Knoten über $y$
|
|
\end{itemize}
|
|
\subsection{Dominanz}
|
|
\begin{itemize}
|
|
\item Knoten $x$ dominiert $y$ ($x \geq \geq y$), wenn jeder Pfad von Wurzel zu $y$ durch $x$ laufen muss
|
|
\item Strikte Dominanz $x >> y$, falls zusätzlich $x \neq y$ gilt
|
|
\item $\mathrm{ImmDom[}y\mathrm{]}$ ist strikter Dominator von $y$, der $y$ am Nächsten ist
|
|
\item Dominatorbaum enthält jeden Knoten als Kind seines ImmDomms $\rightarrow$ Pfad zwischen $x$ und $z$ in Dominatorbaum $\Leftrightarrow$ $x >> z$
|
|
\end{itemize}
|
|
|
|
\subsubsection{Berechnung der Dominatoren $D(n)$ eines Knoten $n$}
|
|
|
|
\paragraph{Iterativer Fixpunkt-Algorithmus (Lengauer)}
|
|
\begin{itemize}
|
|
\item mit $\mathcal{O}(\vert E\vert \vert N\vert ^2)$
|
|
\item Zunächst Überapproximation der Dominatorenmenge
|
|
\item Initialisierung aller $D(n) \in N$ mit $N$ außer Startknoten $S$ mit $D(S) = S$
|
|
\item Bis Fixpunkt erreicht ist: alle $D(n)$ zu $D'(n) = \lbrace n\rbrace \cup \bigcap_{(p, n) \in E} D(p)$
|
|
\item $n$ am besten in Tiefensuchereihenfolge durchlaufen
|
|
\end{itemize}
|
|
|
|
\paragraph{Verfahren mit Spannendem Tiefenbaum $T$}
|
|
\begin{itemize}
|
|
\item Besuch des KFG in Tiefensuchereihenfolge mit zugehöriger Nummerierung: \begin{itemize}
|
|
\item \enquote{Spannende} Kanten gehen zu frisch nummerierten Knoten
|
|
\item Rückschreitende Kanten gehen zu Vorgänger (kleinere DFS-Nummer) in $T$
|
|
\item Fortschreitende Kanten gehen zu Nachfolger (größere DFS-Nummer) in $T$
|
|
\item Kreuzkanten führen in früher besuchten Ast in $T$
|
|
\end{itemize}
|
|
\item Dominatoren $D(n)$ liegen auf jeden Fall \enquote{über} $n$ in $T$
|
|
\item Berechnung der Semidominatoren $\mathrm{SemDom}\lbrack w\rbrack$ in Reihenfolge fallender DFS-Nummern: \begin{itemize}
|
|
\item Direkte Vorgänger auf $T$ sind Kandidaten
|
|
\item $\min_{u\in \mathrm{Pred}(w)} \mathrm{SemDom}\lbrack u\rbrack$ ist Kandidat
|
|
\item Minimum der Kandidaten ist $\mathrm{SemDom}\lbrack w\rbrack$
|
|
\end{itemize}
|
|
\item Berechnung von $\mathrm{ImmDom}\lbrack w\rbrack$ durch Durchlaufen in Tiefenordnung von $\mathrm{SemDom}\lbrack w\rbrack$ nach $w$:\begin{itemize}
|
|
\item Jeweils alle Vorgänger $u$ untersuchen und $u$ mit kleinstem $\mathrm{SemDom}\lbrack u\rbrack$ finden
|
|
\item \begin{equation*}
|
|
\mathrm{ImmDom}\lbrack w\rbrack = \begin{cases}
|
|
\mathrm{SemDom}\lbrack u\rbrack & \mathrm{falls}\, \mathrm{SemDom}\lbrack w\rbrack = \mathrm{SemDom}\lbrack u \rbrack\\
|
|
\mathrm{ImmDom}\lbrack u\rbrack & \mathrm{sonst}
|
|
\end{cases}
|
|
\end{equation*}
|
|
\end{itemize}
|
|
\end{itemize}
|
|
|
|
\subsubsection{Dominanzgrenze}
|
|
\begin{itemize}
|
|
\item Dominanzgrenze $DG[x]$ enthält Knoten $y$, die einen von $x$ dominierten Vorgänger besitzen, aber nicht von $x$ streng dominiert werden
|
|
\item Berechnung der $DG[x]$: \begin{align*}
|
|
DG[x] &= DG_\text{local}[x] \cup \bigcup_{z \in N, \mathrm{ImmDom}[z] = x} DG_\text{up}[x, z] \\
|
|
DG_\text{local}[x] &= \lbrace y \in \mathrm{Succ}(x) \mid \mathrm{ImmDom}[y] \neq x\rbrace\\
|
|
DG_\text{up}[x, z] &= \lbrace y \in DG[z] \mid \mathrm{ImmDom}[y] \neq x\rbrace
|
|
\end{align*}
|
|
\item Invertierung der Dominanzgrenzen liefert Kontrollflussabhängigkeiten
|
|
\end{itemize}
|
|
|
|
\subsection{Schleifenerkennung}
|
|
\begin{itemize}
|
|
\item Region: \begin{itemize}
|
|
\item Untergraph mit einem \enquote{Header} $d$, der (potentiell mehrere) Eingangskante von außerhalb besitzt
|
|
\item Wichtige Region: maximale Region mit $d$ dominiert alle Knoten der Region
|
|
\item Hierarchischer Flussbaum: Baum der Regionen
|
|
\end{itemize}
|
|
\item Rückwärtskante: Kante $(n,d)$ mit $d \geq \geq n$
|
|
\item Natürliche Schleife: \begin{itemize}
|
|
\item Rückwärtskante $(n, d)$ sowie alle Knoten $k$ mit $d \ge \ge k$ und es gibt einen Pfad von $k$ nach $n$ ohne $d$
|
|
\item Bestimmung mit Worklist-Algorithmus, der bei $n$ beginnt und rekursiv die Vorgänger bis $d$ durchläuft und in Menge aufnimmt
|
|
\end{itemize}
|
|
\item Suche nach Rückwärtskanten und natürlichen Schleifen in wichtigen Regionen ausreichend
|
|
\item \enquote{Unsaubere} Regionen: \begin{itemize}
|
|
\item ein Knoten dominiert nachgeordneten Zyklus
|
|
\item Erkennung durch Prüfung der Reduzierbarkeit des Graphs: \begin{itemize}
|
|
\item Entfernung der Rückwärtskanten aus KFG $\rightarrow$ azyklischer Graph, in dem jeder Knoten von der Wurzel erreicht werden kann $\Leftrightarrow$ KFG frei von unnatürlichen Schleifen
|
|
\item Alternative mit Transformationen: Am Ende Graph aus einem einzigen Knoten $\Leftrightarrow$ KFG reduzierbar (ohne Zyklen) \begin{description}
|
|
\item[T1-Transformation] Selbstschleifen aus Graph löschen
|
|
\item[T2-Transformation] Knoten mit eindeutigem Vorgänger mit diesem zusammenfassen
|
|
\end{description}
|
|
\end{itemize}
|
|
\end{itemize}
|
|
\end{itemize}
|
|
|
|
\section{Datenflussanalyse}
|
|
\begin{itemize}
|
|
\item Datenabhängigkeiten: \begin{itemize}
|
|
\item Schreiben vor Lesen:
|
|
\item Schreiben vor Schreiben: Ausgabeabhängigkeit
|
|
\item Lesen vor Schreiben: Anti-Abhängigkeit
|
|
\end{itemize}
|
|
\item Starke Variablendefinition: sichere Zuweisung zu einer Variablen
|
|
\item Schwache Variablendefinition: mögliche Zuweisung zu einer Variablen (etwa über Zeiger oder Referenz, die möglicherweise auf Variable zeigen)
|
|
\end{itemize}
|
|
|
|
\subsection{Berechnung von Datenflusswissen}
|
|
\begin{itemize}
|
|
\item Funktion pro Grundblock: \begin{itemize}
|
|
\item Eingabe: bei Vorwärtsproblem (Rückwärtsproblem) Datenflusswissen der Vorgängerknoten (Nachfolgerknoten)
|
|
\item Vorverarbeitung: logische Operationen oder Mengenoperationen \begin{itemize}
|
|
\item sicher (must): Eigenschaft muss auf allen Eingangskanten erfüllt sein
|
|
\item möglich (may): Eigenschaft muss auf mindestens einer Eingangskante erfüllt sein
|
|
\end{itemize}
|
|
\item Ausgabe: auf Eingabe und in Grundblock enthaltenen Befehlen basierendes, aktualisiertes Datenflusswissen
|
|
\end{itemize}
|
|
\item Iterativer Fixpunkt-Algorithmus für Vorwärtsproblem: optimal Besuch in Reihenfolge des spannenden Tiefenbaums \begin{algorithmic}[]
|
|
\State $\mathrm{in}(\mathrm{Entry}) \gets \mathrm{Init}$
|
|
\ForAll{$n \in N \setminus \lbrace \mathrm{Entry}\rbrace$}
|
|
\State $\mathrm{in}(n) \gets \bot$
|
|
\EndFor
|
|
\State $\mathrm{WL} \gets N\setminus \lbrace \mathrm{Entry}\rbrace$
|
|
\While{$\mathrm{WL} \neq \emptyset$}
|
|
\State $B \gets \mathrm{pop}(\mathrm{WL})$
|
|
\State $\mathrm{out} \gets f_B(\mathrm{in}(B))$
|
|
\ForAll{$B' \in \mathrm{Succ}(B)$}
|
|
\State $\mathrm{in}(B') \gets \mathrm{in}(B') \sqcup \mathrm{out}$
|
|
\If{$\mathrm{out} \neq \mathrm{out}(B)$}
|
|
\State $\mathrm{WL} \gets \mathrm{WL} \cup \lbrace B'\rbrace$
|
|
\State $\mathrm{out}(B) \gets \mathrm{out}$
|
|
\EndIf
|
|
\EndFor
|
|
\EndWhile
|
|
\end{algorithmic}
|
|
\item Probleme bei Verwendung von Bitvektoren:\begin{itemize}
|
|
\item Transformation erfordert komplettes Neuberechnen
|
|
\item Bitvektoren oft zu groß für jeweilige Nutzungsstelle
|
|
\end{itemize}
|
|
\item Alternative Datenstrukturen: \begin{itemize}
|
|
\item Definitions-Nutzungs-Graph für erreichbare Nutzungen
|
|
\item Nutzungs-Definitions-Graph für erreichenden Definitionen
|
|
\item Variablen-Netz als Vereinigung aller sich schneidenden DU-Graphen
|
|
\item Single Static-Assignment (SSA)
|
|
\end{itemize}
|
|
\end{itemize}
|
|
|
|
\subsection{Typische Datenflussprobleme}
|
|
\begin{itemize}
|
|
\item Erreichende Definitionen: \begin{itemize}
|
|
\item mindestens ein Pfad, auf dem Variable nicht erneut schwach definiert wird
|
|
\item Optimierungen: \begin{itemize}
|
|
\item Keine erreichende Definition $\rightarrow$ Variable nicht initialisiert
|
|
\item Genau eine oder gleiche Definition $\rightarrow$ Konstantenweitergabe oder Kopienfortschreibung möglich
|
|
\item Alle Variablen nur außerhalb einer Schleife definiert $\rightarrow$ Ausdruck schleifeninvariant
|
|
\end{itemize}
|
|
\item Umsetzung: \begin{itemize}
|
|
\item Eine Bitposition pro Variablendefinition
|
|
\item Setzen bei Definition der Variable
|
|
\item Zurücksetzen bei mindestens schwacher Definition
|
|
\item Anfangsbelegung: false
|
|
\item Vorverarbeitung: oder
|
|
\end{itemize}
|
|
\end{itemize}
|
|
\item Konstantenweitergabe: \begin{itemize}
|
|
\item Eine Bitposition plus Wert pro Variable
|
|
\item Setzen von Bit und Wert bei konstanter Definition
|
|
\item Zurücksetzen von Bit bei mindestens schwacher oder nicht konstanter Definition
|
|
\item Anfangsbelegung: false, ?
|
|
\item Vorverarbeitung: und sowie Wertgleichheit
|
|
\end{itemize}
|
|
\item Kopienfortschreibung: \begin{itemize}
|
|
\item Eine Bitposition pro aus Kopieren entstandener Wergleichtheitsbeziehung
|
|
\item Setzen bei Kopieroperation
|
|
\item Zurücksetzen wenn Original oder Kopie mindestens schwach definiert wird
|
|
\item Anfangsbelegung: false
|
|
\item Vorverarbeitung: und
|
|
\end{itemize}
|
|
\item Verfügbare Ausdrücke: \begin{itemize}
|
|
\item auf allen Pfaden von Entry-Knoten aus wird Ausdruck bestimmt und verwendete Variablen anschließend nicht mehr schwach definiert
|
|
\item Optimierungen: \begin{itemize}
|
|
\item Elimination gleicher Teilausdrücke
|
|
\item Wiederverwendung statt Neuberechnung
|
|
\end{itemize}
|
|
\item Umsetzung: \begin{itemize}
|
|
\item Eine Bitposition pro wertnummeriertem (Teil-)Ausdruck
|
|
\item Setzen wenn Ausdruck ausgewertet wird
|
|
\item Zurücksetzen wenn vorkommende Variable mindestens schwach definiert wird
|
|
\item Anfangsbelegung: false
|
|
\item Vorverarbeitung: und sowie Ausdruck muss auf allen Pfaden verfügbar sein
|
|
\end{itemize}
|
|
\end{itemize}
|
|
\item Lebendige Variablen: \begin{itemize}
|
|
\item lebendig in Knoten $D$, wenn es einen Pfad von $D$ zum Exit-Knoten gibt, auf der die Variable ohne vorherige Redefinition schwach benutzt wird; sonst tot
|
|
\item Optimierungen: \begin{itemize}
|
|
\item Tote Variablen müssen nicht ausgerechnet werden
|
|
\item Weniger Registerdruck
|
|
\item Elimination redudanter Schleifenlaufvariablen nach der Schleife
|
|
\end{itemize}
|
|
\item Umsetzung: \begin{itemize}
|
|
\item Eine Bitposition pro Variable
|
|
\item Setzen bei Verwendung der Variable
|
|
\item Zurücksetzen bei starker Redefinition
|
|
\item Anfangsbelegung: false
|
|
\item Vorverarbeitung: oder
|
|
\end{itemize}
|
|
\end{itemize}
|
|
\item Erreichbare Nutzungen: \begin{itemize}
|
|
\item Alle Nutzungen einer Variable durch Bestimmen der Pfade, auf denen Variable ohne vorherige Redefinition verwendet wird
|
|
\item Zweck: Hilfreich für Lebendigkeitsspannen und Registerallokation
|
|
\end{itemize}
|
|
\item Vorhersehbare Ausdrücke: \begin{itemize}
|
|
\item auf allen Pfaden zum Exit-Knoten wird Ausdruck bestimmt und verwendete Variablen werden nicht vorher schwach redefiniert
|
|
\item Optimierungen: \begin{itemize}
|
|
\item Vorziehen der Ausdrucksberechnung zur Verkleinerung der Code-Größe
|
|
\item Geringerer Registerdruck in folgenden Zweigen
|
|
\end{itemize}
|
|
\item Umsetzung: \begin{itemize}
|
|
\item Eine Bitposition pro (Teil-)Ausdruck
|
|
\item Setzen bei Auswertung des Audrucks
|
|
\item Zurücksetzen bei mindestens schwacher Redefinition einer der verwendeten Variablen
|
|
\item Anfangsbelegung: false
|
|
\item Vorverarbeitung: und
|
|
\end{itemize}
|
|
\end{itemize}
|
|
\end{itemize}
|
|
|
|
\section{Wertnummerierung in Grundblock}
|
|
\begin{itemize}
|
|
\item Post-Order-Traversierung des Ausdrucksbaums
|
|
\item Jede referenzierte Variable bekommt eindeutige Id
|
|
\item Kombination aus Operator und beiden Argumenten bekommt entweder frische Id oder bei Duplikat (auch kommutativ) bereits verwendete
|
|
\item Gleiche Ids $\Leftrightarrow$ gleicher Ausdruck
|
|
\end{itemize}
|
|
|
|
\section{Static Single Assignment (SSA)}
|
|
\begin{itemize}
|
|
\item Jede Variable hat exakt eine starke und keine schwache Definition
|
|
\item erfordert Verwendung von $\phi$-Funktionen, die verschiedene Variablen zusammenführt
|
|
\end{itemize}
|
|
|
|
\subsection{Konstruktion der SSA-Form}
|
|
\begin{itemize}
|
|
\item In isoliertem Grundblock trivial: Erzeugung einer neuen Variable $x_i$ bei jeder Definition
|
|
\item $\phi$-Funktionen sollten möglichst sparsam nur wenn notwendig eingefügt werden
|
|
\end{itemize}
|
|
|
|
\subsubsection{Iteratives Dominanzgrenzenverfahren nach Cytron ($\mathcal{O}(N^2)$)}
|
|
\begin{itemize}
|
|
\item Dominanzgrenzenkriterium: Aus Definition von $v$ in Grundblock $X$ folgt eine $\phi$-Funktion für $v$ in jedem Grundblock der Dominanzgrenze von $X$
|
|
\item Eingefügte $\phi$-Funktionen werden Variablen zugewiesen, für die das Dominanzgrenzenkriterium erneut angewendet werden muss
|
|
\end{itemize}
|
|
|
|
\subsubsection{Wertnummerierungsverfahren nach Click}
|
|
\begin{itemize}
|
|
\item Wertnummerierung für jeden Grundblock $Z$ durchführen: \begin{itemize}
|
|
\item $\mathrm{wn}_Z(\mathrm{const}) = \mathrm{const}$
|
|
\item Wenn $Z$ Entry-Knoten, alle Wertnummern der Tupel in $Z$ auf ungültig setzen
|
|
\item Bei zwei Vorgängern $X, Y$ von $Z$, welche beide bereits besucht sind:\begin{itemize}
|
|
\item Wenn $\mathrm{wn}_X(t) \neq \mathrm{wn}_Y(t)$, dann neue Wertnummer $x$ für $\mathrm{wn}_Z(t)$ einführen und $\mathrm{wn}_Z(t) = \phi(\mathrm{wn}_X(t), \mathrm{wn}_Y(t))$ generieren
|
|
\item Ansonsten: $\mathrm{wn}_Z(t) = \mathrm{wn}_X(t)$
|
|
\end{itemize}
|
|
\item Bei einem Vorgänger $X$ mit undefiniertem $\mathrm{wn}_X(t)$ diesen rekursiv initialisieren
|
|
\item Bei zwei Vorgängern $X, Y$ von $Z$, wobei nur $X$ noch unbesucht ist:\begin{itemize}
|
|
\item Neue Wertnummer für $\mathrm{wn}_Z(t)$ einführen
|
|
\item Neue besondere Wertnummer für $\mathrm{wn}_X(t)$ einführen
|
|
\item Vorläufige $\phi'$-Funktion $\mathrm{wn}_Z(t) = \phi'(\mathrm{wn}_X(t), \mathrm{wn}_Y(t))$ generieren
|
|
\end{itemize}
|
|
\end{itemize}
|
|
\item Wertnummerierung für alle Tupel $t$ in $Z$ durchführen
|
|
\item Nach Durchführung für alle Blöcke, $\phi'$-Funktionen korrigieren: \begin{itemize}
|
|
\item Besondere Wertnummern in $X$ durch letzte in $X$ gültige Wertnummer ersetzen
|
|
\item Offene $\phi'$-Funktionen durch abgeschlossene $\phi$-Funktion mit ersetzten Werten ersetzen
|
|
\item Falls $t$ in unbesuchten Blöcken nicht geändert wurde, $\mathrm{wn}_Z(t) = \phi'(\mathrm{wn}_X(t),\mathrm{wn}_Y(t))$ löschen und alle Verwendungen von $\mathrm{wn}_Z(t)$ durch $\mathrm{wn}_X(t)$ ersetzen
|
|
\end{itemize}
|
|
\end{itemize}
|
|
|
|
\subsection{Optimierungen auf SSA-Form}
|
|
\begin{itemize}
|
|
\item Konstantenweitergabe: \begin{itemize}
|
|
\item Aus $v_i = c$ können alle Verwendungen von $v_i$ durch die Konstante $c$ ersetzt werden
|
|
\item Aus $v_i = \phi(c_1, c_2, \textellipsis)$ kann $v_i$ durch $c_1$ ersetzt werden, wenn alle $c_i$ gleich sind
|
|
\item Datenflussanalyse muss nach Ersetzung nicht wiederholt werden, Worklist-Algorithmus reicht aus
|
|
\end{itemize}
|
|
\item Kopienfortschreibung: Aus $v_i = y_j$ kann jede Verwendung von $v_i$ durch $y_j$ ersetzt werden
|
|
\item Lebendigkeit einer Variable lässt sich direkt aus weiterem lesenden Zugriff erkennen
|
|
\item Gemeinsame Teilausdrücke, verfügbare Ausdrücke und vorhersehbare Ausdrücke lassen sich durch Wertnummerierung in gesamter Prozedur leicht erkennen
|
|
\item Elimination toten Codes:\begin{itemize}
|
|
\item alles, was nicht als lebendig markiert ist, ist tot
|
|
\item Markierung von Anweisungen als lebendig, falls sie \begin{itemize}
|
|
\item Seiteneffekte wie I/O, Funktionsaufrufe oder die Rückgabe von Werten hat
|
|
\item eine später von einer lebendigen Anweisung benutzte Variable schreibt
|
|
\item eine Verzweigung ist, von der eine lebendige Anweisung kontrollflussabhängig ist
|
|
\end{itemize}
|
|
\end{itemize}
|
|
\end{itemize}
|
|
|
|
\subsection{Rücktransformation aus SSA-Form}
|
|
\begin{itemize}
|
|
\item $\phi$-Funktion nicht in Hardware abbildbar, Umwandlung notwendig
|
|
\item Aus $v_3 = \phi(v_1, v_2)$ wird \begin{itemize}
|
|
\item $v_3 = v_i$ in Vorgängerblock $i$ falls sich Lebensspannen der $v_i$ nicht paarweise überlappen (konventionelle SSA-Form)
|
|
\item $v_3 = t$ ($t$ frische Temporärvariable) in Block mit $\phi$-Funktion sowie $t = v_i$ in Vorgängerblock $i$
|
|
\end{itemize}
|
|
\item Sequentialisierung paralleler Kopieroperationen (TODO VL-06)
|
|
\item Variablen können auch nur schwach definiert sein, etwa durch Zeiger auf Variablen oder Seiteneffekte von Prozeduren auf globale Variablen $\rightarrow$ Hilfsfunktion $\mathrm{isAlias}(p, v)$\begin{itemize}
|
|
\item \begin{equation*}
|
|
\mathrm{isAlias}(p, v) = \begin{cases}
|
|
*p & \text{falls}\, p = \&v\\
|
|
v & \text{sonst}
|
|
\end{cases}
|
|
\end{equation*}
|
|
\item Für jede Zuweisung $*p = $ für jede Variable $v_i$, auf die $p$ zeigen könnte, neue Zuweisung $v_{i+1} = \mathrm{isAlias}(p, v_i)$ einfügen
|
|
\end{itemize}
|
|
\end{itemize}
|
|
|
|
\section{Aliasanalyse}
|
|
|
|
\section{Induktionsvarianten und schleifeninvarianter Code}
|
|
|
|
\section{Schleifen und Arrays}
|
|
|
|
\section{Schleifentransformationen}
|
|
|
|
\section{Schleifenrestrukturierungen}
|
|
\end{document}
|