소스 검색

added sidebar about priority queues

Jeremy Siek 4 년 전
부모
커밋
ad29d59c41
1개의 변경된 파일111개의 추가작업 그리고 60개의 파일을 삭제
  1. 111 60
      book.tex

+ 111 - 60
book.tex

@@ -2579,7 +2579,7 @@ start:
     jmp conclusion
 \end{lstlisting}
 \end{minipage}
-\caption{An example program for register allocation.}
+\caption{A running example program for register allocation.}
 \label{fig:reg-eg}
 \end{figure}
 
@@ -2790,7 +2790,7 @@ line 2 is never used. The variable \code{b} is read on line 5 and
 there is an intervening write to \code{b} on line 4, so the read on
 line 5 receives the value written on line 4, not line 2.
 
-\begin{wrapfigure}[20]{l}[1.0in]{0.6\textwidth}
+\begin{wrapfigure}[18]{l}[1.0in]{0.6\textwidth}
   \small
   \begin{tcolorbox}[title=\href{https://docs.racket-lang.org/reference/sets.html}{The Racket Set Package}]
     A \emph{set} is an unordered collection of elements without duplicates.
@@ -2916,7 +2916,7 @@ shown between each instruction to make the figure easy to read.
     negq t
                        |$\{\ttm{t},\ttm{z}\}$|    
     movq z, %rax
-                       |$\{\ttm{t}\}$|    
+                       |$\{\ttm{rax},\ttm{t}\}$|    
     addq t, %rax
                        |$\{\}$|
     jmp conclusion
@@ -3048,18 +3048,18 @@ Next we skip forward to the instruction \lstinline{movq x, y}.
 \begin{figure}[tbp]
 \begin{quote}
 \begin{tabular}{ll}
-\lstinline{movq $1, v}& no interference by rule 3,\\
-\lstinline{movq $42, w}& $\ttm{w}$ interferes with $\ttm{v}$ by rule 3,\\
-\lstinline{movq v, x}& $\ttm{x}$ interferes with $\ttm{w}$ by rule 3,\\
-\lstinline{addq $7, x}& $\ttm{x}$ interferes with $\ttm{w}$ by rule 1,\\
-\lstinline{movq x, y}& $\ttm{y}$ interferes with $\ttm{w}$ but not $\ttm{x}$ by rule 3,\\
-\lstinline{movq x, z}& $\ttm{z}$ interferes with $\ttm{w}$ and $\ttm{y}$ by rule 3,\\
-\lstinline{addq w, z}& $\ttm{z}$ interferes with $\ttm{y}$ by rule 1, \\
-\lstinline{movq y, t}& $\ttm{t}$ interferes with $\ttm{z}$ by rule 3, \\
-\lstinline{negq t}& $\ttm{t}$ interferes with $\ttm{z}$ by rule 1, \\
-\lstinline{movq z, %rax}   & no interference (ignore rax), \\
-\lstinline{addq t, %rax} & no interference (ignore rax). \\
-  \lstinline{jmp conclusion}& no interference.
+\lstinline{movq $1, v}& no interference by rule 1\\
+\lstinline{movq $42, w}& $\ttm{w}$ interferes with $\ttm{v}$ by rule 1\\
+\lstinline{movq v, x}& $\ttm{x}$ interferes with $\ttm{w}$ by rule 1\\
+\lstinline{addq $7, x}& $\ttm{x}$ interferes with $\ttm{w}$ by rule 2\\
+\lstinline{movq x, y}& $\ttm{y}$ interferes with $\ttm{w}$ but not $\ttm{x}$ by rule 1\\
+\lstinline{movq x, z}& $\ttm{z}$ interferes with $\ttm{w}$ and $\ttm{y}$ by rule 1\\
+\lstinline{addq w, z}& $\ttm{z}$ interferes with $\ttm{y}$ by rule 2 \\
+\lstinline{movq y, t}& $\ttm{t}$ interferes with $\ttm{z}$ by rule 1 \\
+\lstinline{negq t}& $\ttm{t}$ interferes with $\ttm{z}$ by rule 2 \\
+\lstinline{movq z, %rax}   & $\ttm{rax}$ interferes with $\ttm{t}$ by rule 1 \\
+\lstinline{addq t, %rax} & no interference by rule 2 \\
+  \lstinline{jmp conclusion}& no interference by rule 2
 \end{tabular}
 \end{quote}
 \caption{Interference results for the running example.}
@@ -3073,6 +3073,7 @@ Figure~\ref{fig:interfere}.
 \large
 \[
 \begin{tikzpicture}[baseline=(current  bounding  box.center)]
+\node (rax) at (0,0) {$\ttm{rax}$};
 \node (t1) at (0,2) {$\ttm{t}$};
 \node (z) at (3,2)  {$\ttm{z}$};
 \node (x) at (6,2)  {$\ttm{x}$};
@@ -3081,6 +3082,7 @@ Figure~\ref{fig:interfere}.
 \node (v) at (9,0)  {$\ttm{v}$};
 
 
+\draw (t1) to (rax);
 \draw (t1) to (z);
 \draw (z) to (y);
 \draw (z) to (w);
@@ -3221,9 +3223,12 @@ algorithm for register allocation based on saturation and the
 most-constrained-first heuristic. It is roughly equivalent to the
 DSATUR algorithm of \cite{Brelaz:1979eu} (also known as saturation
 degree ordering~\citep{Gebremedhin:1999fk,Omari:2006uq}).  Just as in
-Sudoku, the algorithm represents colors with integers. The first $k$
-colors corresponding to the $k$ registers in a given machine and the
-rest of the integers corresponding to stack locations.
+Sudoku, the algorithm represents colors with integers. The integers
+$0$ through $k-1$ correspond to the $k$ registers that we use for
+register allocation. The integers $k$ and larger correspond to stack
+locations. The registers that are not used for register allocation,
+such as \code{rax}, are assigned to negative integers. In particular,
+we assign $-1$ to \code{rax}.
 
 \begin{figure}[btp]
   \centering
@@ -3232,7 +3237,7 @@ Algorithm: DSATUR
 Input: a graph |$G$|
 Output: an assignment |$\mathrm{color}[v]$| for each vertex |$v \in G$|
 
-|$W \gets \mathit{vertices}(G)$|
+|$W \gets \mathrm{vertices}(G)$|
 while |$W \neq \emptyset$| do
     pick a vertex |$u$| from |$W$| with the highest saturation,
         breaking ties randomly
@@ -3246,18 +3251,24 @@ while |$W \neq \emptyset$| do
 
 With this algorithm in hand, let us return to the running example and
 consider how to color the interference graph in
-Figure~\ref{fig:interfere}. Initially, all of the vertices are not yet
-colored and they are unsaturated, so we annotate each of them with a
-dash for their color and an empty set for the saturation.
+Figure~\ref{fig:interfere}.
+%
+We color the vertices for registers with their own color. For example,
+\code{rax} is assigned the color $-1$.  We then update the saturation
+for their neighboring vertices.  In this case, the saturation for
+\code{t} includes $-1$.  The remaining vertices are not yet colored,
+so they annotated with a dash, and their saturation sets are empty.
 \[
 \begin{tikzpicture}[baseline=(current  bounding  box.center)]
-\node (t1) at (0,2) {$\ttm{t}:-,\{\}$};
+\node (rax) at (0,0) {$\ttm{rax}:-1,\{\}$};
+\node (t1) at (0,2) {$\ttm{t}:-,\{-1\}$};
 \node (z) at (3,2)  {$\ttm{z}:-,\{\}$};
 \node (x) at (6,2)  {$\ttm{x}:-,\{\}$};
 \node (y) at (3,0)  {$\ttm{y}:-,\{\}$};
 \node (w) at (6,0)  {$\ttm{w}:-,\{\}$};
 \node (v) at (9,0)  {$\ttm{v}:-,\{\}$};
 
+\draw (t1) to (rax);
 \draw (t1) to (z);
 \draw (z) to (y);
 \draw (z) to (w);
@@ -3266,19 +3277,21 @@ dash for their color and an empty set for the saturation.
 \draw (v) to (w);
 \end{tikzpicture}
 \]
-The algorithm says to select a maximally saturated vertex and color it
-$0$. In this case we have a 6-way tie, so we arbitrarily pick
-$\ttm{t}$. We then mark color $0$ as no longer available for $\ttm{z}$
-because it interferes with $\ttm{t}$.
+The algorithm says to select a maximally saturated vertex. So we pick
+$\ttm{t}$ and color it with the first available integer, which is
+$0$. We mark $0$ as no longer available for $\ttm{z}$ and $\ttm{rax}$
+because they interfere with $\ttm{t}$.
 \[
 \begin{tikzpicture}[baseline=(current  bounding  box.center)]
-\node (t1) at (0,2) {$\ttm{t}:0,\{\}$};
+\node (rax) at (0,0) {$\ttm{rax}:-1,\{0\}$};
+\node (t1) at (0,2) {$\ttm{t}:0,\{-1\}$};
 \node (z) at (3,2)  {$\ttm{z}:-,\{0\}$};
 \node (x) at (6,2)  {$\ttm{x}:-,\{\}$};
 \node (y) at (3,0)  {$\ttm{y}:-,\{\}$};
 \node (w) at (6,0)  {$\ttm{w}:-,\{\}$};
 \node (v) at (9,0)  {$\ttm{v}:-,\{\}$};
 
+\draw (t1) to (rax);
 \draw (t1) to (z);
 \draw (z) to (y);
 \draw (z) to (w);
@@ -3287,18 +3300,21 @@ because it interferes with $\ttm{t}$.
 \draw (v) to (w);
 \end{tikzpicture}
 \]
-Next we repeat the process, selecting another maximally saturated
-vertex, which is \code{z}, and color it with the first available number,
-which is $1$.
+We repeat the process, selecting another maximally saturated
+vertex, which is \code{z}, and color it with the first available
+number, which is $1$. We add $1$ to the saturations for the
+neighboring vertices \code{t}, \code{y}, and \code{w}.
 \[
 \begin{tikzpicture}[baseline=(current  bounding  box.center)]
-\node (t1) at (0,2) {$\ttm{t}:0,\{1\}$};
+\node (rax) at (0,0) {$\ttm{rax}:-1,\{0\}$};
+\node (t1) at (0,2) {$\ttm{t}:0,\{-1,1\}$};
 \node (z) at (3,2)  {$\ttm{z}:1,\{0\}$};
 \node (x) at (6,2)  {$\ttm{x}:-,\{\}$};
 \node (y) at (3,0)  {$\ttm{y}:-,\{1\}$};
 \node (w) at (6,0)  {$\ttm{w}:-,\{1\}$};
 \node (v) at (9,0)  {$\ttm{v}:-,\{\}$};
 
+\draw (t1) to (rax);
 \draw (t1) to (z);
 \draw (z) to (y);
 \draw (z) to (w);
@@ -3311,13 +3327,15 @@ The most saturated vertices are now \code{w} and \code{y}. We color
 \code{w} with the first available color, which is $0$.
 \[
 \begin{tikzpicture}[baseline=(current  bounding  box.center)]
-\node (t1) at (0,2) {$\ttm{t}:0,\{1\}$};
+\node (rax) at (0,0) {$\ttm{rax}:-1,\{0\}$};
+\node (t1) at (0,2) {$\ttm{t}:0,\{-1,1\}$};
 \node (z) at (3,2)  {$\ttm{z}:1,\{0\}$};
 \node (x) at (6,2)  {$\ttm{x}:-,\{0\}$};
 \node (y) at (3,0)  {$\ttm{y}:-,\{0,1\}$};
 \node (w) at (6,0)  {$\ttm{w}:0,\{1\}$};
 \node (v) at (9,0)  {$\ttm{v}:-,\{0\}$};
 
+\draw (t1) to (rax);
 \draw (t1) to (z);
 \draw (z) to (y);
 \draw (z) to (w);
@@ -3332,13 +3350,15 @@ with $2$.  We cannot choose $0$ or $1$ because those numbers are in
 and \code{z}, whose colors are $0$ and $1$ respectively.
 \[
 \begin{tikzpicture}[baseline=(current  bounding  box.center)]
-\node (t1) at (0,2) {$\ttm{t}:0,\{1\}$};
+\node (rax) at (0,0) {$\ttm{rax}:-1,\{0\}$};
+\node (t1) at (0,2) {$\ttm{t}:0,\{-1,1\}$};
 \node (z) at (3,2)  {$\ttm{z}:1,\{0,2\}$};
 \node (x) at (6,2)  {$\ttm{x}:-,\{0\}$};
 \node (y) at (3,0)  {$\ttm{y}:2,\{0,1\}$};
 \node (w) at (6,0)  {$\ttm{w}:0,\{1,2\}$};
 \node (v) at (9,0)  {$\ttm{v}:-,\{0\}$};
 
+\draw (t1) to (rax);
 \draw (t1) to (z);
 \draw (z) to (y);
 \draw (z) to (w);
@@ -3350,13 +3370,15 @@ and \code{z}, whose colors are $0$ and $1$ respectively.
 Now \code{x} and \code{v} are the most saturated, so we color \code{v} it $1$.
 \[
 \begin{tikzpicture}[baseline=(current  bounding  box.center)]
-\node (t1) at (0,2) {$\ttm{t}:0,\{1\}$};
+\node (rax) at (0,0) {$\ttm{rax}:-1,\{0\}$};
+\node (t1) at (0,2) {$\ttm{t}:0,\{-1,1\}$};
 \node (z) at (3,2)  {$\ttm{z}:1,\{0,2\}$};
 \node (x) at (6,2)  {$\ttm{x}:-,\{0\}$};
 \node (y) at (3,0)  {$\ttm{y}:2,\{0,1\}$};
 \node (w) at (6,0)  {$\ttm{w}:0,\{1,2\}$};
 \node (v) at (9,0)  {$\ttm{v}:1,\{0\}$};
 
+\draw (t1) to (rax);
 \draw (t1) to (z);
 \draw (z) to (y);
 \draw (z) to (w);
@@ -3368,13 +3390,15 @@ Now \code{x} and \code{v} are the most saturated, so we color \code{v} it $1$.
 In the last step of the algorithm, we color \code{x} with $1$.
 \[
 \begin{tikzpicture}[baseline=(current  bounding  box.center)]
-\node (t1) at (0,2) {$\ttm{t}:0,\{1,\}$};
+\node (rax) at (0,0) {$\ttm{rax}:-1,\{0\}$};
+\node (t1) at (0,2) {$\ttm{t}:0,\{-1,1,\}$};
 \node (z) at (3,2)  {$\ttm{z}:1,\{0,2\}$};
 \node (x) at (6,2)  {$\ttm{x}:1,\{0\}$};
 \node (y) at (3,0)  {$\ttm{y}:2,\{0,1\}$};
 \node (w) at (6,0)  {$\ttm{w}:0,\{1,2\}$};
 \node (v) at (9,0)  {$\ttm{v}:1,\{0\}$};
 
+\draw (t1) to (rax);
 \draw (t1) to (z);
 \draw (z) to (y);
 \draw (z) to (w);
@@ -3385,11 +3409,11 @@ In the last step of the algorithm, we color \code{x} with $1$.
 \]
 
 With the coloring complete, we finalize the assignment of variables to
-registers and stack locations. Recall that if we have $k$ registers,
-we map the first $k$ colors to registers and the rest to stack
-locations.  Suppose for the moment that we have just one register to
-use for register allocation, \key{rcx}. Then the following is the
-mapping of colors to registers and stack allocations.
+registers and stack locations. Recall that if we have $k$ registers to
+use for allocation, we map the first $k$ colors to registers and the
+rest to stack locations.  Suppose for the moment that we have just one
+register to use for register allocation, \key{rcx}. Then the following
+is the mapping of colors to registers and stack allocations.
 \[
   \{ 0 \mapsto \key{\%rcx}, \; 1 \mapsto \key{-8(\%rbp)}, \; 2 \mapsto \key{-16(\%rbp)} \}
 \]
@@ -3485,31 +3509,58 @@ shown in Figure~\ref{fig:reg-alloc-passes}.
 \label{fig:reg-alloc-passes}
 \end{figure}
 
+\begin{wrapfigure}[24]{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$]
+    notifices the queue the the priority has decreased for the item
+    associated with the given handle.
+  \end{description}
+\end{tcolorbox}
+\end{wrapfigure}
+
+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 process 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.
+
+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.
+
 \begin{exercise}\normalfont
-  Implement the pass \code{allocate-registers}, which should come
+  Implement the compiler pass \code{allocate-registers}, which should come
   after the \code{build-interference} pass. The three new passes,
   \code{uncover-live}, \code{build-interference}, and
   \code{allocate-registers} replace the \code{assign-homes} pass of
   Section~\ref{sec:assign-r1}.
   
-  We recommend that you create 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. The support code includes an implementation of the
-  priority queue data structure in the file
-  \code{priority\_queue.rkt}, which might come in handy for
-  prioritizing highly saturated nodes inside your \code{color-graph}
-  function.
-
-  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.
-  
   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.