Selaa lähdekoodia

optimize jumps

Jeremy Siek 4 vuotta sitten
vanhempi
commit
f716636d48
1 muutettua tiedostoa jossa 174 lisäystä ja 129 poistoa
  1. 174 129
      book.tex

+ 174 - 129
book.tex

@@ -3252,7 +3252,7 @@ calculating the size of the frame. Also, don't forget that the size of
 the frame needs to be a multiple of 16 bytes.
 
 
-\section{Challenge: Move Biasing$^{*}$}
+\section{Challenge: Move Biasing}
 \label{sec:move-biasing}
 
 This section describes an optional enhancement to register allocation
@@ -4481,12 +4481,12 @@ start:
     cmpq $1, tmp7951
     je block7952
     jmp block7953
-block7952:
-    movq $42, %rax
-    jmp conclusion
 block7953:
     movq $0, %rax
     jmp conclusion
+block7952:
+    movq $42, %rax
+    jmp conclusion
 \end{lstlisting}
 \end{minipage}
 &
@@ -4499,12 +4499,12 @@ start:
 	cmpq	$1, %rcx
 	je block7952
 	jmp block7953
-block7952:
-	movq	$42, %rax
-	jmp conclusion
 block7953:
 	movq	$0, %rax
 	jmp conclusion
+block7952:
+	movq	$42, %rax
+	jmp conclusion
 
 	.globl main
 main:
@@ -4570,137 +4570,182 @@ conclusion:
 Figure~\ref{fig:R2-passes} lists all the passes needed for the
 compilation of $R_2$.
 
-\section{Challenge: Optimize Jumps$^{*}$}
-\label{sec:opt-jumps}
-
-UNDER CONSTRUCTION
 
+\section{Challenge: Optimize Jumps}
+\label{sec:opt-jumps}
 
-%% \section{Challenge: Optimizing Conditions$^{*}$}
-%% \label{sec:opt-if}
-
-%% A close inspection of the x86 code generated in
-%% Figure~\ref{fig:if-example-x86} reveals some redundant computation
-%% regarding the condition of the \key{if}. We compare \key{rcx} to $1$
-%% twice using \key{cmpq} as follows.
+Recall that in the example output of \code{explicate-control} in
+Figure~\ref{fig:explicate-control-s1-38}, \code{block57} through
+\code{block60} are trivial blocks, they do nothing but jump to another
+block. The first goal of this challenge assignment is to remove those
+blocks. Figure~\ref{fig:optimize-jumps} repeats the result of
+\code{explicate-control} on the left and shows the result of bypassing
+the trivial blocks on the right. Let us focus on \code{block61}.  The
+\code{then} branch jumps to \code{block57}, which in turn jumps to
+\code{block55}. The optimized code on the right of
+Figure~\ref{fig:optimize-jumps} bypasses \code{block57}, with the
+\code{then} branch jumping directly to \code{block55}. The story is
+similar for the \code{else} branch, as well as for the two branchs in
+\code{block62}. After the jumps in \code{block61} and \code{block62}
+have been optimized in this way, there are no longer any jumps to
+blocks \code{block57} through \code{block60}, so they can be removed.
 
-%% % Wierd LaTeX bug if I remove the following. -Jeremy
-%% % Does it have to do with page breaks?
-%% \begin{lstlisting}
-%% \end{lstlisting}
+\begin{figure}[tbp]
+\begin{tabular}{lll}
+\begin{minipage}{0.4\textwidth}
+\begin{lstlisting}
+block62:
+    tmp54 = (read);
+    if (eq? tmp54 2) then
+       goto block59;
+    else
+       goto block60;
+block61:
+    tmp53 = (read);
+    if (eq? tmp53 0) then
+       goto block57;
+    else
+       goto block58;
+block60:
+    goto block56;
+block59:
+    goto block55;
+block58:
+    goto block56;
+block57:
+    goto block55;
+block56:
+    return (+ 700 77);
+block55:
+    return (+ 10 32);
+start:
+    tmp52 = (read);
+    if (eq? tmp52 1) then
+       goto block61;
+    else
+       goto block62;
+\end{lstlisting}
+\end{minipage}
+&
+$\Rightarrow$
+&
+\begin{minipage}{0.55\textwidth}
+\begin{lstlisting}
+block62:
+    tmp54 = (read);
+    if (eq? tmp54 2) then
+       goto block55;
+    else
+       goto block56;
+block61:
+    tmp53 = (read);
+    if (eq? tmp53 0) then
+       goto block55;
+    else
+       goto block56;
+block56:
+    return (+ 700 77);
+block55:
+    return (+ 10 32);
+start:
+    tmp52 = (read);
+    if (eq? tmp52 1) then
+       goto block61;
+    else
+       goto block62;
+\end{lstlisting}
+\end{minipage}
+\end{tabular}
+\caption{Optimize jumps by removing trivial blocks.}
+\label{fig:optimize-jumps}
+\end{figure}
 
-%% \begin{lstlisting}
-%% 	cmpq	$1, %rcx
-%% 	sete	%al
-%% 	movzbq	%al, %rcx
-%% 	cmpq	$1, %rcx
-%% 	je then21288
-%% \end{lstlisting}
+The name of this pass is \code{optimize-jumps}.  We recommend
+implementing this pass in two phases. The first phrase builds a hash
+table that maps labels to possibly improved labels. The second phase
+changes the target of each \code{goto} to use the improved label.  If
+the label is for a trivial block, then the hash table should map the
+label to the first non-trivial block that can be reached from this
+label by jumping through trivial blocks.  If the label is for a
+non-trivial block, then the hash table should map the label to itself;
+we do not want to change jumps to non-trivial blocks.
+
+The first phase can be accomplished by constructing an empty hash
+table, call it \code{short-cut}, and then iterating over the control
+flow graph. Each time you encouter a block that is just a \code{goto},
+then update the hash table, mapping the block's source to the target
+of the \code{goto}. Also, the hash table may already have mapped some
+labels to the block's source, to you must iterate through the hash
+table and update all of those so that they instead map to the target
+of the \code{goto}.
+
+For the second phase, we recommend iterating through the $\Tail$ of
+each block in the program, updating the target of every \code{goto}
+according to the mapping in \code{short-cut}.
 
+\begin{exercise}\normalfont
+  Implement the \code{optimize-jumps} pass and check that it remove
+  trivial blocks in a few example programs. Then check that your
+  compiler still passes all of your tests.
+\end{exercise}
 
-%% The reason for this non-optimal code has to do with the \code{flatten}
-%% pass earlier in this Chapter. We recommended flattening the condition
-%% to an $\Arg$ and then comparing with \code{\#t}. But if the condition
-%% is already an \code{eq?} test, then we would like to use that
-%% directly. In fact, for many of the expressions of Boolean type, we can
-%% generate more optimized code. For example, if the condition is
-%% \code{\#t} or \code{\#f}, we do not need to generate an \code{if} at
-%% all. If the condition is a \code{let}, we can optimize based on the
-%% form of its body. If the condition is a \code{not}, then we can flip
-%% the two branches.
-%% %
-%% \margincomment{\tiny We could do even better by converting to basic
-%%   blocks.\\ --Jeremy}
-%% %
-%% On the other hand, if the condition is a \code{and}
-%% or another \code{if}, we should flatten them into an $\Arg$ to avoid
-%% code duplication.
+There is another opportunity for optimizing jumps that is apparent in
+the example of Figure~\ref{fig:if-example-x86}. The \code{start} block
+end with a jump to \code{block7953} and there are no other jumps to
+\code{block7953} in the rest of the program. In this situation we can
+avoid the runtime overhead of this jump by merging \code{block7953}
+into the preceeding block, in this case the \code{start} block.
+Figure~\ref{fig:remove-jumps} shows the output of
+\code{select-instructions} on the left and the result of this
+optimization on the right.
 
-%% Figure~\ref{fig:opt-if} shows an example program and the result of
-%% applying the above suggested optimizations.
+\begin{figure}[tbp]
+\begin{tabular}{lll}
+\begin{minipage}{0.5\textwidth}
+% s1_20.rkt
+\begin{lstlisting}
+start:
+    callq read_int
+    movq %rax, tmp7951
+    cmpq $1, tmp7951
+    je block7952
+    jmp block7953
+block7953:
+    movq $0, %rax
+    jmp conclusion
+block7952:
+    movq $42, %rax
+    jmp conclusion
+\end{lstlisting}
+\end{minipage}
+&
+$\Rightarrow\qquad$
+\begin{minipage}{0.4\textwidth}
+\begin{lstlisting}
+start:
+    callq read_int
+    movq %rax, tmp7951
+    cmpq $1, tmp7951
+    je block7952
+    movq $0, %rax
+    jmp conclusion
+block7952:
+    movq $42, %rax
+    jmp conclusion
+\end{lstlisting}
+\end{minipage}
+\end{tabular}
+\caption{Merging basic blocks by removing unnecessary jumps.}
+\label{fig:remove-jumps}
+\end{figure}
 
-%% \begin{exercise}\normalfont
-%%   Change the \code{flatten} pass to improve the code that gets
-%%   generated for \code{if} expressions. We recommend writing a helper
-%%   function that recursively traverses the condition of the \code{if}.
-%% \end{exercise}
+\begin{exercise}\normalfont
+  Implement a pass named \code{remove-jumps} that merges basic blocks
+  into their preceeding basic block, when there is only one preceeding
+  block. Check that your pass accomplishes this goal on several test
+  programs and check that your compiler passes all of your tests.
+\end{exercise}
 
-%% \begin{figure}[tbp]
-%% \begin{tabular}{lll}
-%% \begin{minipage}{0.5\textwidth}
-%% \begin{lstlisting}
-%% (program
-%%   (if (let ([x 1])
-%%         (not (eq? x (read))))
-%%     777
-%%     42))
-%% \end{lstlisting}
-%% $\Downarrow$
-%% \begin{lstlisting}
-%% (program (x.1 if.2 tmp.3)
-%%   (type Integer)
-%%   (assign x.1 1)
-%%   (assign tmp.3 (read))
-%%   (if (eq? x.1 tmp.3)
-%%     ((assign if.2 42))
-%%     ((assign if.2 777)))
-%%   (return if.2))
-%% \end{lstlisting}
-%% $\Downarrow$
-%% \begin{lstlisting}
-%% (program (x.1 if.2 tmp.3)
-%%   (type Integer)
-%%   (movq (int 1) (var x.1))
-%%   (callq read_int)
-%%   (movq (reg rax) (var tmp.3))
-%%   (if (eq? (var x.1) (var tmp.3))
-%%     ((movq (int 42) (var if.2)))
-%%     ((movq (int 777) (var if.2))))
-%%   (movq (var if.2) (reg rax)))
-%% \end{lstlisting}
-%% \end{minipage}
-%% &
-%% $\Rightarrow$
-%% \begin{minipage}{0.4\textwidth}
-%% \begin{lstlisting}
-%% 	.globl _main
-%% _main:
-%% 	pushq	%rbp
-%% 	movq	%rsp, %rbp
-%% 	pushq	%r13
-%% 	pushq	%r14
-%% 	pushq	%r12
-%% 	pushq	%rbx
-%% 	subq	$0, %rsp
-
-%% 	movq	$1, %rbx
-%% 	callq	_read_int
-%% 	movq	%rax, %rcx
-%% 	cmpq	%rcx, %rbx
-%% 	je then35989
-%% 	movq	$777, %rbx
-%% 	jmp if_end35990
-%% then35989:
-%% 	movq	$42, %rbx
-%% if_end35990:
-%% 	movq	%rbx, %rax
-
-%% 	movq	%rax, %rdi
-%% 	callq	_print_int
-%% 	movq	$0, %rax
-%% 	addq	$0, %rsp
-%% 	popq	%rbx
-%% 	popq	%r12
-%% 	popq	%r14
-%% 	popq	%r13
-%% 	popq	%rbp
-%% 	retq
-%% \end{lstlisting}
-%% \end{minipage}
-%% \end{tabular}
-%% \caption{Example program with optimized conditionals.}
-%% \label{fig:opt-if}
-%% \end{figure}
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \chapter{Tuples and Garbage Collection}