|
@@ -16,7 +16,6 @@
|
|
|
|
|
|
|
|
\begin{document}
|
|
\begin{document}
|
|
|
\maketitle
|
|
\maketitle
|
|
|
-\pagebreak
|
|
|
|
|
\tableofcontents
|
|
\tableofcontents
|
|
|
\pagebreak
|
|
\pagebreak
|
|
|
|
|
|
|
@@ -38,7 +37,7 @@ the keywords in to an action.
|
|
|
|
|
|
|
|
There are two general types of of optimizations of the assembly code, global
|
|
There are two general types of of optimizations of the assembly code, global
|
|
|
optimizations and optimizations on a so-called basic block. These optimizations
|
|
optimizations and optimizations on a so-called basic block. These optimizations
|
|
|
-will be discussed seperatly
|
|
|
|
|
|
|
+will be discussed separately
|
|
|
|
|
|
|
|
\subsection{Global optimizations}
|
|
\subsection{Global optimizations}
|
|
|
|
|
|
|
@@ -70,8 +69,8 @@ for a piece of code not containing any branches or jumps.
|
|
|
|
|
|
|
|
To create a basic block, you need to define what is the leader of a basic
|
|
To create a basic block, you need to define what is the leader of a basic
|
|
|
block. We call a statement a leader if it is either a jump/branch statement, or
|
|
block. We call a statement a leader if it is either a jump/branch statement, or
|
|
|
-the target of such a statement. Then a basic block runs from one leader
|
|
|
|
|
-(not including this leader) until the next leader (including this leader). !!!!
|
|
|
|
|
|
|
+the target of such a statement. Then a basic block runs from one leader until
|
|
|
|
|
+the next leader.
|
|
|
|
|
|
|
|
There are quite a few optimizations we perform on these basic blocks, so we
|
|
There are quite a few optimizations we perform on these basic blocks, so we
|
|
|
will describe the types of optimizations here in stead of each optimization.
|
|
will describe the types of optimizations here in stead of each optimization.
|
|
@@ -108,12 +107,12 @@ We search from the end of the block up for instructions that are eligible for
|
|
|
CSE. If we find one, we check further up in the code for the same instruction,
|
|
CSE. If we find one, we check further up in the code for the same instruction,
|
|
|
and add that to a temporary storage list. This is done until the beginning of
|
|
and add that to a temporary storage list. This is done until the beginning of
|
|
|
the block or until one of the arguments of this expression is assigned. Now all
|
|
the block or until one of the arguments of this expression is assigned. Now all
|
|
|
-occurences of this expression can be replaced by a move of a new variable that
|
|
|
|
|
-is generated above the first occurence, which contains the value of the
|
|
|
|
|
|
|
+occurrences of this expression can be replaced by a move of a new variable that
|
|
|
|
|
+is generated above the first occurrence, which contains the value of the
|
|
|
expression.
|
|
expression.
|
|
|
|
|
|
|
|
This is a less efficient method, but because the basic blocks are in general
|
|
This is a less efficient method, but because the basic blocks are in general
|
|
|
-not very large and the exectution time of the optimizer is not a primary
|
|
|
|
|
|
|
+not very large and the execution time of the optimizer is not a primary
|
|
|
concern, this is not a big problem.
|
|
concern, this is not a big problem.
|
|
|
|
|
|
|
|
\section{Implementation}
|
|
\section{Implementation}
|
|
@@ -130,23 +129,51 @@ The program has three steps, parsing the Assembly code into a datastructure we
|
|
|
can use, the so-called Intermediate Representation, performing optimizations on
|
|
can use, the so-called Intermediate Representation, performing optimizations on
|
|
|
this IR and writing the IR back to Assembly.
|
|
this IR and writing the IR back to Assembly.
|
|
|
|
|
|
|
|
-\subsection{Parsing with PLY}
|
|
|
|
|
|
|
+\subsection{Parsing}
|
|
|
|
|
|
|
|
|
|
+The parsing is done with PLY, which allows us to perform Lex-Yacc tasks in
|
|
|
|
|
+Python by using a Lex-Yacc like syntax. This way there is no need to combine
|
|
|
|
|
+languages like we should do otherwise since Lex and Yacc are coupled with C.
|
|
|
|
|
|
|
|
|
|
+The decision was made to not recognize exactly every possible instruction in
|
|
|
|
|
+the parser, but only if something is for example a command, a comment or a gcc
|
|
|
|
|
+directive. We then transform per line to a object called a Statement. A
|
|
|
|
|
+statement has a type, a name and optionally a list of arguments. These
|
|
|
|
|
+statements together form a statement list, which is placed in another object
|
|
|
|
|
+called a Block. In the beginning there is one block for the entire program, but
|
|
|
|
|
+after global optimizations this will be separated in several blocks that are
|
|
|
|
|
+the basic blocks.
|
|
|
|
|
|
|
|
\subsection{Optimizations}
|
|
\subsection{Optimizations}
|
|
|
|
|
|
|
|
|
|
+The optimizations are done in two different steps. First the global
|
|
|
|
|
+optimizations are performed, which are only the optimizations on branch-jump
|
|
|
|
|
+constructions. This is done repeatedly until there are no more changes.
|
|
|
|
|
+
|
|
|
|
|
+After all possible global optimizations are done, the program is seperated into
|
|
|
|
|
+basic blocks. The algorithm to do this is described earlier, and means all
|
|
|
|
|
+jump and branch instructions are called leaders, as are their targets. A basic
|
|
|
|
|
+block then goes from leader to leader.
|
|
|
|
|
|
|
|
|
|
+After the division in basic blocks, optimizations are performed on each of
|
|
|
|
|
+these basic blocks. This is also done repeatedly, since some times several
|
|
|
|
|
+steps can be done to optimize something.
|
|
|
|
|
|
|
|
\subsection{Writing}
|
|
\subsection{Writing}
|
|
|
|
|
|
|
|
|
|
+Once all the optimizations have been done, the IR needs to be rewritten into
|
|
|
|
|
+Assembly code, so the xgcc crosscompiler can make binary code out of it.
|
|
|
|
|
|
|
|
|
|
+The writer expects a list of statements, so first the blocks have to be
|
|
|
|
|
+concatenated again into a list. After this is done, the list is passed on to
|
|
|
|
|
+the writer, which writes the instructions back to Assembly and saves the file
|
|
|
|
|
+so we can let xgcc compile it.
|
|
|
|
|
|
|
|
\section{Results}
|
|
\section{Results}
|
|
|
|
|
|
|
|
\subsection{pi.c}
|
|
\subsection{pi.c}
|
|
|
|
|
|
|
|
-\subsection{arcron.c}
|
|
|
|
|
|
|
+\subsection{acron.c}
|
|
|
|
|
|
|
|
\subsection{whet.c}
|
|
\subsection{whet.c}
|
|
|
|
|
|
|
@@ -158,7 +185,7 @@ this IR and writing the IR back to Assembly.
|
|
|
|
|
|
|
|
\appendix
|
|
\appendix
|
|
|
|
|
|
|
|
-\section{Total list of optimizations}
|
|
|
|
|
|
|
+\section{List of all optimizations}
|
|
|
|
|
|
|
|
\label{opt}
|
|
\label{opt}
|
|
|
|
|
|
|
@@ -202,6 +229,7 @@ lw ...,0($regA)
|
|
|
\textbf{Advanced basic block optimizations}
|
|
\textbf{Advanced basic block optimizations}
|
|
|
|
|
|
|
|
\begin{verbatim}
|
|
\begin{verbatim}
|
|
|
|
|
+# Common subexpression elimination
|
|
|
addu $regA, $regB, 4 addu $regD, $regB, 4
|
|
addu $regA, $regB, 4 addu $regD, $regB, 4
|
|
|
... move $regA, $regD
|
|
... move $regA, $regD
|
|
|
Code not writing $regB -> ...
|
|
Code not writing $regB -> ...
|