|
@@ -3607,6 +3607,47 @@ In the last step of the algorithm, we color \code{x} with $1$.
|
|
|
\end{tikzpicture}
|
|
|
\]
|
|
|
|
|
|
+\begin{wrapfigure}[25]{r}[1.0in]{0.6\textwidth}
|
|
|
+ \small
|
|
|
+ \begin{tcolorbox}[title=Priority Queue]
|
|
|
+ A \emph{priority queue} is a collection of items in which the
|
|
|
+ removal of items is governed by priority. In a ``min'' queue,
|
|
|
+ lower priority items are removed first. An implementation is in
|
|
|
+ \code{priority\_queue.rkt} of the support code. \index{priority
|
|
|
+ queue} \index{minimum priority queue}
|
|
|
+ \begin{description}
|
|
|
+ \item[$\LP\code{make-pqueue}\,\itm{cmp}\RP$] constructs an empty
|
|
|
+ priority queue that uses the $\itm{cmp}$ predicate to determine
|
|
|
+ whether its first argument has lower or equal priority to its
|
|
|
+ second argument.
|
|
|
+ \item[$\LP\code{pqueue-count}\,\itm{queue}\RP$] returns the number of
|
|
|
+ items in the queue.
|
|
|
+ \item[$\LP\code{pqueue-push!}\,\itm{queue}\,\itm{item}\RP$] inserts
|
|
|
+ the item into the queue and returns a handle for the item in the
|
|
|
+ queue.
|
|
|
+ \item[$\LP\code{pqueue-pop!}\,\itm{queue}\RP$] returns the item with
|
|
|
+ the lowest priority.
|
|
|
+ \item[$\LP\code{pqueue-decrease-key!}\,\itm{queue}\,\itm{handle}\RP$]
|
|
|
+ notifies the queue that the priority has decreased for the item
|
|
|
+ associated with the given handle.
|
|
|
+ \end{description}
|
|
|
+\end{tcolorbox}
|
|
|
+\end{wrapfigure}
|
|
|
+
|
|
|
+We recommend creating an auxiliary function named \code{color-graph}
|
|
|
+that takes an interference graph and a list of all the variables in
|
|
|
+the program. This function should return a mapping of variables to
|
|
|
+their colors (represented as natural numbers). By creating this helper
|
|
|
+function, you will be able to reuse it in Chapter~\ref{ch:functions}
|
|
|
+when we add support for functions.
|
|
|
+
|
|
|
+To prioritize the processing of highly saturated nodes inside the
|
|
|
+\code{color-graph} function, we recommend using the priority queue
|
|
|
+data structure (see the side bar on the right). In addition, you will
|
|
|
+need to maintain a mapping from variables to their ``handles'' in the
|
|
|
+priority queue so that you can notify the priority queue when their
|
|
|
+saturation changes.
|
|
|
+
|
|
|
With the coloring complete, we finalize the assignment of variables to
|
|
|
registers and stack locations. We map the first $k$ colors to the $k$
|
|
|
registers and the rest of the colors to stack locations. Suppose for
|
|
@@ -3619,15 +3660,18 @@ locations.
|
|
|
Composing this mapping with the coloring, we arrive at the following
|
|
|
assignment of variables to locations.
|
|
|
\begin{gather*}
|
|
|
- \{ \ttm{v} \mapsto \key{\%rcx}, \,
|
|
|
+ \{ \ttm{v} \mapsto \key{-8(\%rbp)}, \,
|
|
|
\ttm{w} \mapsto \key{\%rcx}, \,
|
|
|
\ttm{x} \mapsto \key{-8(\%rbp)}, \,
|
|
|
\ttm{y} \mapsto \key{-16(\%rbp)}, \\
|
|
|
\ttm{z} \mapsto \key{-8(\%rbp)}, \,
|
|
|
\ttm{t} \mapsto \key{\%rcx} \}
|
|
|
\end{gather*}
|
|
|
-Applying this assignment to our running example, on the left, yields
|
|
|
-the program on the right.
|
|
|
+
|
|
|
+Adapt the code from the \code{assign-homes} pass
|
|
|
+(Section~\ref{sec:assign-r1}) to replace the variables with their
|
|
|
+assigned location. Applying the above assignment to our running
|
|
|
+example, on the left, yields the program on the right.
|
|
|
% why frame size of 32? -JGS
|
|
|
\begin{center}
|
|
|
\begin{minipage}{0.3\textwidth}
|
|
@@ -3649,9 +3693,9 @@ jmp conclusion
|
|
|
$\Rightarrow\qquad$
|
|
|
\begin{minipage}{0.45\textwidth}
|
|
|
\begin{lstlisting}
|
|
|
-movq $1, %rcx
|
|
|
+movq $1, -8(%rbp)
|
|
|
movq $42, %rcx
|
|
|
-movq %rcx, -8(%rbp)
|
|
|
+movq -8(%rbp), -8(%rbp)
|
|
|
addq $7, -8(%rbp)
|
|
|
movq -8(%rbp), -16(%rbp)
|
|
|
movq -8(%rbp), -8(%rbp)
|
|
@@ -3665,72 +3709,84 @@ jmp conclusion
|
|
|
\end{minipage}
|
|
|
\end{center}
|
|
|
|
|
|
+\begin{exercise}\normalfont
|
|
|
+%
|
|
|
+Implement the compiler pass \code{allocate-registers}.
|
|
|
+%
|
|
|
+Create five programs that exercise all of the register allocation
|
|
|
+algorithm, including spilling variables to the stack.
|
|
|
+%
|
|
|
+Replace \code{assign-homes} in the list of \code{passes} in the
|
|
|
+\code{run-tests.rkt} script with the three new passes:
|
|
|
+\code{uncover-live}, \code{build-interference}, and
|
|
|
+\code{allocate-registers}.
|
|
|
+%
|
|
|
+Temporarily remove the \code{print-x86} pass from the list of passes
|
|
|
+and the call to \code{compiler-tests}.
|
|
|
+%
|
|
|
+Run the script to test the register allocator.
|
|
|
+\end{exercise}
|
|
|
|
|
|
|
|
|
-The resulting program is almost an x86 program. The remaining step is
|
|
|
-the patch instructions pass. In this example, the trivial move of
|
|
|
-\code{-8(\%rbp)} to itself is deleted and the addition of
|
|
|
-\code{-8(\%rbp)} to \key{-16(\%rbp)} is fixed by going through
|
|
|
-\code{rax} as follows.
|
|
|
+\section{Patch Instructions}
|
|
|
+\label{sec:patch-instructions}
|
|
|
+
|
|
|
+The remaining step in the compilation to x86 is to ensure that the
|
|
|
+instructions have at most one argument that is a memory access.
|
|
|
+In the running example, the instruction \code{movq -8(\%rbp), -16(\%rbp)}
|
|
|
+is problematic. The fix is to first move \code{-8(\%rbp)}
|
|
|
+into \code{rax} and then move \code{rax} into \code{-16(\%rbp)}.
|
|
|
+%
|
|
|
+The two moves from \code{-8(\%rbp)} to \code{-8(\%rbp)} are also
|
|
|
+problematic, but they can be fixed by simply deleting them. In
|
|
|
+general, we recommend deleting all the trivial moves whose source and
|
|
|
+destination are the same location.
|
|
|
+%
|
|
|
+The following is the output of \code{patch-instructions} on the
|
|
|
+running example.
|
|
|
+\begin{center}
|
|
|
+ \begin{minipage}{0.4\textwidth}
|
|
|
+\begin{lstlisting}
|
|
|
+movq $1, -8(%rbp)
|
|
|
+movq $42, %rcx
|
|
|
+movq -8(%rbp), -8(%rbp)
|
|
|
+addq $7, -8(%rbp)
|
|
|
+movq -8(%rbp), -16(%rbp)
|
|
|
+movq -8(%rbp), -8(%rbp)
|
|
|
+addq %rcx, -8(%rbp)
|
|
|
+movq -16(%rbp), %rcx
|
|
|
+negq %rcx
|
|
|
+movq -8(%rbp), %rax
|
|
|
+addq %rcx, %rax
|
|
|
+jmp conclusion
|
|
|
+\end{lstlisting}
|
|
|
+\end{minipage}
|
|
|
+$\Rightarrow\qquad$
|
|
|
+\begin{minipage}{0.45\textwidth}
|
|
|
\begin{lstlisting}
|
|
|
+movq $1, -8(%rbp)
|
|
|
+movq $42, %rcx
|
|
|
+addq $7, -8(%rbp)
|
|
|
+movq -8(%rbp), %rax
|
|
|
+movq %rax, -16(%rbp)
|
|
|
+addq %rcx, -8(%rbp)
|
|
|
+movq -16(%rbp), %rcx
|
|
|
+negq %rcx
|
|
|
movq -8(%rbp), %rax
|
|
|
-addq %rax, -16(%rbp)
|
|
|
+addq %rcx, %rax
|
|
|
+jmp conclusion
|
|
|
\end{lstlisting}
|
|
|
-
|
|
|
-We recommend creating a helper function named \code{color-graph} that
|
|
|
-takes an interference graph and a list of all the variables in the
|
|
|
-program. This function should return a mapping of variables to their
|
|
|
-colors (represented as natural numbers). By creating this helper
|
|
|
-function, you will be able to reuse it in Chapter~\ref{ch:functions}
|
|
|
-when you add support for functions. To prioritize the processing of
|
|
|
-highly saturated nodes inside your \code{color-graph} function, we
|
|
|
-recommend using the priority queue data structure (see the side bar on
|
|
|
-the right). Note that you will also need to maintain a mapping from
|
|
|
-variables to their ``handles'' in the priority queue so that you can
|
|
|
-notify the priority queue when their saturation changes.
|
|
|
-
|
|
|
-\begin{wrapfigure}[23]{r}[1.0in]{0.6\textwidth}
|
|
|
- \small
|
|
|
- \begin{tcolorbox}[title=Priority Queue]
|
|
|
- A \emph{priority queue} is a collection of items in which the
|
|
|
- removal of items is governed by priority. In a ``min'' queue,
|
|
|
- lower priority items are removed first. An implementation is in
|
|
|
- \code{priority\_queue.rkt} of the support code. \index{priority
|
|
|
- queue} \index{minimum priority queue}
|
|
|
- \begin{description}
|
|
|
- \item[$\LP\code{make-pqueue}\,\itm{cmp}\RP$] constructs an empty
|
|
|
- priority queue that uses the $\itm{cmp}$ predicate to determine
|
|
|
- whether its first argument has lower or equal priority to its
|
|
|
- second argument.
|
|
|
- \item[$\LP\code{pqueue-count}\,\itm{queue}\RP$] returns the number of
|
|
|
- items in the queue.
|
|
|
- \item[$\LP\code{pqueue-push!}\,\itm{queue}\,\itm{item}\RP$] inserts
|
|
|
- the item into the queue and returns a handle for the item in the
|
|
|
- queue.
|
|
|
- \item[$\LP\code{pqueue-pop!}\,\itm{queue}\RP$] returns the item with
|
|
|
- the lowest priority.
|
|
|
- \item[$\LP\code{pqueue-decrease-key!}\,\itm{queue}\,\itm{handle}\RP$]
|
|
|
- notifies the queue that the priority has decreased for the item
|
|
|
- associated with the given handle.
|
|
|
- \end{description}
|
|
|
-\end{tcolorbox}
|
|
|
-\end{wrapfigure}
|
|
|
-
|
|
|
-Once you have obtained the coloring from \code{color-graph}, you can
|
|
|
-assign the variables to registers or stack locations and then reuse
|
|
|
-code from the \code{assign-homes} pass from
|
|
|
-Section~\ref{sec:assign-r1} to replace the variables with their
|
|
|
-assigned location.
|
|
|
+\end{minipage}
|
|
|
+\end{center}
|
|
|
|
|
|
\begin{exercise}\normalfont
|
|
|
- Implement the compiler pass \code{allocate-registers}, which should
|
|
|
- come after the \code{build-interference} pass. The three new passes
|
|
|
- described in this chapter replace the \code{assign-homes} pass of
|
|
|
- Section~\ref{sec:assign-r1}.
|
|
|
-%
|
|
|
- Test your updated compiler by creating new example programs that
|
|
|
- exercise all of the register allocation algorithm, such as forcing
|
|
|
- variables to be spilled to the stack.
|
|
|
+%
|
|
|
+Implement the \code{patch-instructions} compiler pass.
|
|
|
+%
|
|
|
+Insert it after \code{allocate-registers} in the list of \code{passes}
|
|
|
+in the \code{run-tests.rkt} script.
|
|
|
+%
|
|
|
+Run the script to test the \code{patch-instructions} pass.
|
|
|
\end{exercise}
|
|
|
|
|
|
|
|
@@ -3790,6 +3846,16 @@ shown in Figure~\ref{fig:reg-alloc-passes}.
|
|
|
\label{fig:reg-alloc-passes}
|
|
|
\end{figure}
|
|
|
|
|
|
+\begin{exercise}\normalfont
|
|
|
+Update the \code{print-x86} pass as described in this section.
|
|
|
+%
|
|
|
+In the \code{run-tests.rkt} script, reinstate \code{print-x86} in the
|
|
|
+list of passes and the call to \code{compiler-tests}.
|
|
|
+%
|
|
|
+Run the script to test the complete compiler for \LangVar{} that
|
|
|
+performs register allocation.
|
|
|
+\end{exercise}
|
|
|
+
|
|
|
\section{Challenge: Move Biasing}
|
|
|
\label{sec:move-biasing}
|
|
|
\index{move biasing}
|