% !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{Alias-Analyse}
\begin{itemize}
	\item Aliase: Verschiedene Möglichkeiten auf gleiche Speicherstelle zuzugreifen
	\item Sprachabhängige Quellen von Aliasen: \begin{itemize}
		\item dynamisch allokierte Datenstrukturen
		\item Zeiger
		\item überlappende Speicherbereiche
		\item Referenzen auf Arrays, -Abschnitte, -Dimensionen und -Elemente
		\item Prozedurparameter
		\item Zeigerarithmetik
	\end{itemize}
	\item Sprachunabhängige Quellen wie Transitivität ($a$ zeigt auf $b$ und $b$ zeigt auf $c$ $\rightarrow$ $c$ ist von $a$ erreichbar)
	\item TODO: Aliase in Fortran, Pascal, C und Java (VL-07)
	\item mögliche Aliase (may) müssen nur in einem Pfad Aliase sein
	\item sichere Aliase (must) müssen in allen Pfaden Aliase sein
	\item Fluss-ignorierende Analyse bestimmt, ob Namen irgendwo im KFG Aliase sein können: \begin{itemize}
		\item vergleichsweise einfach berechenbar
		\item oft für interprozedurale Analyse eingesetzt
		\item Relation $\mathrm{Alias}(a, b)$ gibt an, dass $a$ und $b$ für ganze Prozedur Aliase sind, ist reflexiv, symmetrisch und bei must-Analyse auch transitiv
	\end{itemize}
	\item Fluss-sensitive Analyse bestimmt, ob Namen in einem Basisblock Aliase sein können: \begin{itemize}
		\item aufwändige Berechnung
		\item oft für intraprozedurale Analyse eingesetzt
		\item Funktion $\mathrm{Alias}(P, v) = S$ gibt an, dass $v$ an Programmpunkt $P$ auf Speicherstelle $S$ zeigen kann
		\item Bei may-Analyse: \begin{itemize}
			\item $\mathrm{Alias}(P, v_1) \cap \mathrm{Alias}(P, v_2) \neq \emptyset \Leftrightarrow$ $v_1, v_2$ sind in $P$ Aliase
			\item nicht transitiv
		\end{itemize}
		\item Bei must-Analyse: \begin{itemize}
			\item $\vert \mathrm{Alias}(P, v)\vert = 1$, Aliase wenn Speicherstelle gleich
			\item transitiv
		\end{itemize}
	\end{itemize}
	\item intraprozedurale Analyse: \begin{itemize}
		\item Betrachtung einer einzelnen Prozedur
		\item Worst-Case-Annahmen bei Aufruf anderer Prozedur
		\item häufig auf Datenflussproblem zurückgeführt
	\end{itemize}
	\item interprozedurale Analyse: \begin{itemize}
		\item Standard-Verfahren
		\item Andersens Algorithmus
		\item Steensgards Algorithmus
	\end{itemize}
\end{itemize}

\subsection{DFA-Ansatz zur intraprozeduralen, fluss-sensitiven may-Analyse nach Muchnick}
\begin{itemize}
	\item Vorwärtsproblem mit minimalen Grundblöcken
	\item Sprachabhängige lokale Flussfunktionen für unmittelbare Auswirkungen pro Instruktion (Sammler/Gatherer): \begin{itemize}
		\item TODO (VL-07)
	\end{itemize}
	\item Sprachunabhängiger Fixpunktpunktalgorithmus (Verbreiter/Propagator): \begin{itemize}
		\item TODO (VL-07)
	\end{itemize}
\end{itemize}

\subsection{Standard-Verfahren zur interprozeduralen, fluss-insensitiven may-Analyse mit $\mathcal{O}(n^2 + n \cdot e)$}
\begin{itemize}
	\item Alias-Quellen in Sprachen ohne \&-Operator: \begin{itemize}
		\item Übergabe globaler Variable an Funktion
		\item Übergabe der gleichen Variable an mehrere formale Parameter einer Funktion
		\item Zugriff auf umgebende Variablen/formale Parameter bei geschachtelten Prozeduren (vgl. globale Variablen)
	\end{itemize}
	\item Prozeduraufrufgraph (PCG): \begin{itemize}
		\item Knoten: Prozeduren des Programms
		\item Gerichtete Kante von $p$ nach $q$ wenn $p$ $q$ aufrufen kann
	\end{itemize}
	\item Variablenbindungsgraph: \begin{itemize}
		\item Knoten: formale Parameter
		\item Gerichtete Kante von $x$ nach $y$ wenn $(p, q)$ in PCG, $x$ formaler Parameter von $p$ und $x$ Argument für formalen Parameter $y$ von $q$
		\item transitiver Abschluss liefert Alias-Menge der formalen Parameter (aber globale Variablen sind nicht berücksichtigt)
	\end{itemize}	
	\item Paarbindungsgraph: \begin{itemize}
		\item Knoten: alle Paare formaler Parameter
		\item Gerichtete Kante von $(x, y)$ nach $(X, Y)$, wenn \begin{itemize}
			\item $(x,y)$ bei einem Anruf an $(X,Y)$ gebunden werden oder
			\item $(x,y)$ bei einem Aufruf im Inneren einer geschachtelten Prozedur an $(X, Y)$ gebunden werden, wobei ggf. Aliase von $x$ oder $y$ verwendet werden
		\end{itemize}
	\end{itemize}
\end{itemize}\begin{enumerate}
	\item Aliase globaler Variablen: \begin{enumerate}
		\item Bindungen von globalen Variablen an formalen Parametern entdecken
		\item Aus Pfaden in Variablenbindungsgraph zusätzliche formale Parameter, an die globale Variable weitergegeben werden können, bestimmen (in topologischer Reihenfolge durchlaufen; bei Zyklen bis Fixpunkt erreicht)
		\item Aliase der globalen Variablen ablesen
	\end{enumerate}
	\item Parameterpaare als Aliase: Zwei formale Parameter sind Aliase, wenn \begin{itemize}
		\item die gleiche Variable an beide übergeben wird
		\item eine globale Variable und einer ihrer Aliase übergeben wird
	\end{itemize}\begin{enumerate}
		\item Betrachtung aller Paare formaler Parameter
		\item Markierung der Paare, die beim Aufruf zu Alias-Paaren werden können
		\item Propagation von Alias-Informationen durch den PCG
		\item Ablesen der Aliase formaler Parameter
	\end{enumerate}
\end{enumerate}

\subsection{Steensgards Algorithmus für interprozedurale, fluss-insensitive may-Analyse}
\begin{itemize}
	\item Speichergraph: \begin{itemize}
		\item Knoten: eine oder mehrere Speicherstellen
		\item gerichtete Kante: \enquote{zeigt (möglicherweise) auf}-Beziehung, damit Alias: (*start, ziel)
	\end{itemize}
	\item approximiert Speichergraph: \begin{itemize}
		\item Maximal eine abgehende Kante pro Knoten
		\item Zusammenfassung mehrerer Speicherstellen, auf die Variable zeigen kann, zu einer Speicherstelle
	\end{itemize}
\end{itemize}\begin{enumerate}
	\item Einführung eines Knotens im Speichergraph pro Variable, wobei Kanten Zeiger repräsentieren
	\item Fluss-ignorierendes, lineares Abarbeiten aller Anweisungen: \begin{itemize}
		\item $a = \&b$: Kante zwischen $a$ und $b$ einfügen; sofern bereits Kante zwischen $a$ und $x$ existiert, rekursives Verschmelzen von $x$ und $b$
		\item $a = b$:\begin{itemize}
			\item $b$ ist Zeiger: Verschmelzen der Ziele von $a$ und $b$, anschließend zeigen beide auf diesen Knoten
			\item $b$ ist kein Zeiger bzw. noch nicht erkannt: Annotiere $b$ mit $(a:b)$ (Falls später Zeigerziel $y$ von $b$ entdeckt wird, muss Kante von $a$ nach $y$ ergänzt werden)
		\end{itemize}
		\item $a = *b$: \begin{itemize}
			\item $b$, $*b$ haben bereits ausgehende Kanten: Kante zwischen $a$ und $**b$ ergänzen
			\item sonst: analog zu $a = b$ mit adäquaten Annotationen (TODO: Übung)
		\end{itemize}
		\item $*a = b$: \begin{itemize}
			\item $a$, $*a$ mit ausgehenden Kanten: rekursives Verschmelzen von $*b$ und $**a$
			\item sonst: TODO (Übung)
		\end{itemize}
		\item $a = b \oplus c$ mit $\oplus$ binärer Operation: \begin{itemize}
			\item $a$, $b$, $c$ keine Zeiger: Annotation von $b$ und $c$ mit $(a:b)$ bzw. $(a:c)$
			\item $b$ oder $c$ Zeiger: Kante von $a$ nach $*b$ hinzufügen, $c$ mit $(a:c)$ annotieren
		\end{itemize}
		\item $x = p(y_1, \textellipsis, y_n)$: \begin{itemize}
			\item ggf. Speichergraph für $p$ berechnen
			\item Zuweisungsregeln für $x$ und alle $y_i$ verwenden
		\end{itemize}
		\item Funktionszeiger: Bei Verschmelzen auf Typen achten
	\end{itemize}
\end{enumerate}

\section{Schleifen}
\subsection{Schleifeninvariante Anweisungen}
\begin{itemize}
	\item schleifeninvariante Instruktion: alle Operanden $v$ sind \begin{itemize}
		\item konstant oder
		\item nur außerhalb der Schleife berechnet oder
		\item innerhalb der Schleife in \emph{einer} schleifeninvarianten Instruktion berechnet
	\end{itemize}
	\item Auffinden schleifeninvarianter Instruktionen: \begin{enumerate}
		\item Identifikation natürlicher Schleifen
		\item Berechnung der erreichenden Definitionen
		\item Konstantenfaltung
		\item Markierung aller konstanten Ausdrücke und Variablen, sowie alle Markierung, deren erreichende Definitionen außerhalb der Schleife liegen, als schleifeninvariant
		\item Solange neue Markierungen auftreten: alle Instruktionen/Variablen als schleifeninvariant markieren, wenn \begin{itemize}
			\item sie konstant sind oder
			\item wenn alle erreichenden Definitionen außerhalb der Schleife liegen oder
			\item wenn genau eine erreichende Definition existiert und diese als schleifeninvariant markiert ist
		\end{itemize}
	\end{enumerate}
	\item Herausziehen von schleifeninvarianten (Teil-)Ausdrücken vor den Schleifenkopf unter Beachtung von Seiteneffekten/Fehlern immer möglich
	\item Auswahl von herausziehbaren Zuweisungen: \begin{enumerate}
		\item Berechnung der Dominanz, erreichenden Definitionen und Anwendung von Konstantenfaltung
		\item Berechnung der invarianten Instruktionen
		\item Bestimmung der Schleifenausgänge, also Knoten, die KFG-Nachfolger außerhalb der natürlichen Schleife besitzen
		\item Alle Anforderungen an Zuweisungen müssen für Herausziehbarkeit gelten:\begin{itemize}
			\item schleifeninvariant
			\item in Grundblock, der alle Schleifenausgänge dominiert und alle die Variable nutzenden Blöcke strikt dominiert
			\item einzige Zuweisung zu Variable in der ganzen Schleife
		\end{itemize}
		\item Herausziehen vor den Schleifenkopf in Breitensuchreihenfolge zur Bewahrung der Datenabhängigkeiten zwischen herausgezogenen Zuweisungen
	\end{enumerate}
	\item Sonderfall while-Schleife: Schleifenausgang wird von keinem anderen Grundblock in der Schleife dominiert, also keine herausziehbaren Zuweisungen in der Schleife $\rightarrow$ erst Umbau zu do-while-Schleife
	\item Optimierung bei invariantem Test: Generierung einer eigenen Schleife für jeden Fall
\end{itemize}

\subsection{Induktionsvariablen}
\begin{itemize}
	\item Induktionsvariable: Variable, die bei jeder Schleifeniteration um konstanten Wert inkrementiert oder dekrementiert wird
	\item Einfache Induktionsvariable: Variable $x$, die nur durch $x = x \pm c$ mit schleifeninvariantem $c$ verändert wird
	\item Abhängige Induktionsvariable: Variable $y$, die in der Schleife durch $y = a \cdot x \pm b$ mit schleifeninvarianten $a$ und $b$ als lineare Funktion aus Induktionsvariable $x$ berechnet wird
	\item Berechnung der Familie einer einfachen Induktionsvariable $x$: Menge der Induktionsvariablen $y$, die mit linearer Funktion $y = c_1 \cdot x \pm c_2$ von $x$ mit schleifeninvarianten $c_1$ und $c_2$ abhängen: \begin{itemize}
		\item Zuweisung der Form $y = c_1 \cdot x \pm c_2$
		\item Zuweisung der Form $y = c_1 \cdot z \pm c_2$, wobei $z \in \mathrm{Familie}(x)$ und \begin{itemize}
			\item keine Veränderung von $x$ zwischen Zuweisung zu $z$ und Zuweisung zu $y$
			\item keine von außerhalb der Schleife erreichende Definition von $z$ erreicht Zuweisung zu $y$
		\end{itemize}
	\end{itemize}
	\item Berechnungen der Tripel $(x, c_1, c_2)$ für alle Induktionsvariablen $y$ einer Schleife:\begin{enumerate}
		\item Berechnung von Schleifeninvarianz und erreichenden Definitionen
		\item Bestimmung aller einfachen Induktionsvariablen durch Code-Inspektion (\enquote{Pattern Matching})
		\item Bestimmung aller Variablen $y$ mit einziger (oder identischen) Zuweisung der Form $y = x \pm c$ oder $y = c \cdot x$ mit $x$ Induktionsvariable und $c$ schleifeninvariant:\begin{itemize}
			\item $x$ ist einfache Induktionsvariable:
			\begin{equation*}
				\mathrm{Tripel}(y) = \begin{cases*}
					(x, 1, c) & falls $y = x + c$ oder $y = c + x$\\
					(x, 1, -c)& falls $y = x - c$\\
					(x, c, 0)& sonst ($y = x \cdot c$ oder $y = c \cdot x$)
				\end{cases*}
			\end{equation*}
			\item $x$ ist abhängige Induktionsvariable mit Tupel $(u, d_1, d_2)$:
			\begin{equation*}
				\mathrm{Tripel}(y) = \begin{cases*}
					(u, d_1, d_2 + c) & falls $y = x + c$ oder $y = c + x$\\
					(u, d_1, d_2 - c) & falls $y = x - c$\\
					(u, d_1 \cdot c, d_2 \cdot c_2) & sonst ($y = c \cdot x$ oder $y = x \cdot c$)
				\end{cases*}
			\end{equation*}
		\end{itemize}
	\end{enumerate}
	\item Vereinfachung der Berechnungsvorschrift von Schleifenlaufvariablen pro Iteration (Reduktion der Ausdrucksstärke, \enquote{Strength Reduction}) für jede einfache Induktionsvariable $x$: \begin{enumerate}
		\item Für jede von $x$ abhängige Induktionsvariable $y$ mit Tripel $(x, a, b)$:\begin{enumerate}
			\item Einführung neuer Variable $y'$
			\item Ersetzung der Zuweisung zu $y$ durch $y = y'$
			\item Einfügen der Zuweisung $y' = y' \pm (a \cdot c)$ nach jeder Zuweisung $x = x \pm c$
			\item Einfügen der Zuweisung $y' = x\cdot a + b$ vor dem Schleifenkopf
		\end{enumerate}
	\end{enumerate}
	\item Modifikation von bedingten Sprüngen ggf. möglich
	\item Verringerung der Anzahl von Array-Bereichstests ggf. möglich
\end{itemize}

\subsection{Schleifen und Arrays}

\subsection{Schleifentransformationen}

\subsection{Schleifenrestrukturierungen}
\end{document}
