|
@@ -7737,6 +7737,62 @@ def explicate_control(p):
|
|
\fi}
|
|
\fi}
|
|
|
|
|
|
|
|
|
|
|
|
+{\if\edition\racketEd
|
|
|
|
+%
|
|
|
|
+The \code{explicate\_tail} and \code{explicate\_assign} functions need
|
|
|
|
+additional cases for Boolean constants and \key{if}. The cases for
|
|
|
|
+\code{if} should recursively compile the two branches using either
|
|
|
|
+\code{explicate\_tail} or \code{explicate\_assign}, respectively. The
|
|
|
|
+cases should then invoke \code{explicate\_pred} on the condition
|
|
|
|
+expression, passing in the generated code for the two branches. For
|
|
|
|
+example, consider the following program with an \code{if} in tail
|
|
|
|
+position.
|
|
|
|
+\begin{lstlisting}
|
|
|
|
+(let ([x (read)])
|
|
|
|
+ (if (eq? x 0) 42 777))
|
|
|
|
+\end{lstlisting}
|
|
|
|
+The two branches are recursively compiled to \code{(Return 42)} and
|
|
|
|
+\code{(Return 777)}. We then invoke \code{explicate\_pred} on the
|
|
|
|
+condition \code{(eq? x 0)} and the two return statements, which is
|
|
|
|
+used as the result for \code{explicate\_tail}.
|
|
|
|
+\begin{lstlisting}
|
|
|
|
+ (if (eq? x 0) 42 777)
|
|
|
|
+ |$\Rightarrow$| (explicate_pred `(Prim eq? ((Var x) (Int 0)))
|
|
|
|
+ `(Return 42) `(Return 777))
|
|
|
|
+\end{lstlisting}
|
|
|
|
+Next let us consider a program with an \code{if} on the right-hand
|
|
|
|
+side of a \code{let}.
|
|
|
|
+\begin{lstlisting}
|
|
|
|
+(let ([y (read)])
|
|
|
|
+ (let ([x (if (eq? y 0) 40 777)])
|
|
|
|
+ (+ x 2)))
|
|
|
|
+\end{lstlisting}
|
|
|
|
+Note that the body of the inner \code{let} will have already been
|
|
|
|
+compiled to \code{(Return (+ x 2))} and passed as the \code{cont}
|
|
|
|
+parameter of \code{explicate\_assign}. We'll need to use \code{cont}
|
|
|
|
+to recursively process both branches of the \code{if}, so we generate
|
|
|
|
+the following block using an auxiliary function named \code{create\_block}.
|
|
|
|
+\begin{lstlisting}
|
|
|
|
+block_6:
|
|
|
|
+ return (+ x 2)
|
|
|
|
+\end{lstlisting}
|
|
|
|
+and use \code{(Goto 'block\_6)} as the \code{cont} argument for
|
|
|
|
+compiling the branches. So the two branches compile to
|
|
|
|
+\begin{lstlisting}
|
|
|
|
+x = 40;
|
|
|
|
+goto block_6;
|
|
|
|
+\end{lstlisting}
|
|
|
|
+and
|
|
|
|
+\begin{lstlisting}
|
|
|
|
+x = 777;
|
|
|
|
+goto block_6;
|
|
|
|
+\end{lstlisting}
|
|
|
|
+We then invoke \code{explicate\_pred} on the condition \code{(eq? y
|
|
|
|
+ 0)} and the above code for the branches, which is used as the result
|
|
|
|
+for \code{explicate\_tail}.
|
|
|
|
+
|
|
|
|
+\fi}
|
|
|
|
+
|
|
{\if\edition\racketEd
|
|
{\if\edition\racketEd
|
|
\begin{figure}[tbp]
|
|
\begin{figure}[tbp]
|
|
\begin{lstlisting}
|
|
\begin{lstlisting}
|
|
@@ -7746,8 +7802,8 @@ def explicate_control(p):
|
|
[(Let x rhs body) ___]
|
|
[(Let x rhs body) ___]
|
|
[(Prim 'not (list e)) ___]
|
|
[(Prim 'not (list e)) ___]
|
|
[(Prim op es) #:when (or (eq? op 'eq?) (eq? op '<))
|
|
[(Prim op es) #:when (or (eq? op 'eq?) (eq? op '<))
|
|
- (IfStmt (Prim op arg*) (force (block->goto thn))
|
|
|
|
- (force (block->goto els)))]
|
|
|
|
|
|
+ (IfStmt (Prim op arg*) (create_block thn)
|
|
|
|
+ (create_block els))]
|
|
[(Bool b) (if b thn els)]
|
|
[(Bool b) (if b thn els)]
|
|
[(If cnd^ thn^ els^) ___]
|
|
[(If cnd^ thn^ els^) ___]
|
|
[else (error "explicate_pred unhandled case" cnd)]))
|
|
[else (error "explicate_pred unhandled case" cnd)]))
|
|
@@ -7758,11 +7814,13 @@ def explicate_control(p):
|
|
\fi}
|
|
\fi}
|
|
|
|
|
|
\racket{The skeleton for the \code{explicate\_pred} function is given
|
|
\racket{The skeleton for the \code{explicate\_pred} function is given
|
|
- in Figure~\ref{fig:explicate-pred}. It has a case for every
|
|
|
|
- expression that can have type \code{Boolean}. We detail a few cases
|
|
|
|
- here and leave the rest for the reader. The input to this function
|
|
|
|
- is an expression and two blocks, \code{thn} and \code{els}, for the
|
|
|
|
- two branches of the enclosing \key{if}.}
|
|
|
|
|
|
+ in Figure~\ref{fig:explicate-pred}. It takes three parameters:
|
|
|
|
+ 1) \code{cnd}, the condition expression of the \code{if},
|
|
|
|
+ 2) \code{thn}, the code generated by explicate for the ``then'' branch,
|
|
|
|
+ and 3) \code{els}, the code generated by
|
|
|
|
+ explicate for the ``else'' branch. The \code{explicate\_pred}
|
|
|
|
+ function should match on \code{cnd} with a case for
|
|
|
|
+ every kind of expression that can have type \code{Boolean}.}
|
|
%
|
|
%
|
|
\python{The \code{explicate\_pred} function has four parameters: 1)
|
|
\python{The \code{explicate\_pred} function has four parameters: 1)
|
|
the condition expession, 2) the generated statements for the
|
|
the condition expession, 2) the generated statements for the
|
|
@@ -7770,18 +7828,72 @@ def explicate_control(p):
|
|
branch, and 4) the dictionary of basic blocks. The
|
|
branch, and 4) the dictionary of basic blocks. The
|
|
\code{explicate\_pred} function returns a list of \LangCIf{}
|
|
\code{explicate\_pred} function returns a list of \LangCIf{}
|
|
statements and it may add to the dictionary of basic blocks.}
|
|
statements and it may add to the dictionary of basic blocks.}
|
|
-%
|
|
|
|
|
|
+
|
|
Consider the case for comparison operators. We translate the
|
|
Consider the case for comparison operators. We translate the
|
|
comparison to an \code{if} statement whose branches are \code{goto}
|
|
comparison to an \code{if} statement whose branches are \code{goto}
|
|
-statements created by applying \code{create\_block} to the \code{thn}
|
|
|
|
-and \code{els} branches.
|
|
|
|
|
|
+statements created by applying \code{create\_block} to the code
|
|
|
|
+generated for the \code{thn} and \code{els} branches. Let us
|
|
|
|
+illustrate this translation with an example. Returning
|
|
|
|
+to the program with an \code{if} expression in tail position,
|
|
|
|
+we invoke \code{explicate\_pred} on its condition \code{(eq? x 0)}
|
|
|
|
+which happens to be a comparison operator.
|
|
|
|
+\begin{lstlisting}
|
|
|
|
+(let ([x (read)])
|
|
|
|
+ (if (eq? x 0) 42 777))
|
|
|
|
+\end{lstlisting}
|
|
|
|
+The two branches \code{42} and \code{777} were already compiled to \code{return}
|
|
|
|
+statements, from which we now create the following blocks.
|
|
|
|
+\begin{center}
|
|
|
|
+\begin{minipage}{\textwidth}
|
|
|
|
+\begin{lstlisting}
|
|
|
|
+block_1:
|
|
|
|
+ return 42;
|
|
|
|
+block_2:
|
|
|
|
+ return 777;
|
|
|
|
+\end{lstlisting}
|
|
|
|
+ \end{minipage}
|
|
|
|
+\end{center}
|
|
%
|
|
%
|
|
|
|
+So \code{explicate\_pred} compiles the comparison \code{(eq? x 0)}
|
|
|
|
+to the following \code{if} statement.
|
|
|
|
+%
|
|
|
|
+\begin{center}
|
|
|
|
+\begin{minipage}{\textwidth}
|
|
|
|
+\begin{lstlisting}
|
|
|
|
+if (eq? x 0)
|
|
|
|
+ goto block_1;
|
|
|
|
+else
|
|
|
|
+ goto block_2;
|
|
|
|
+\end{lstlisting}
|
|
|
|
+\end{minipage}
|
|
|
|
+\end{center}
|
|
|
|
+
|
|
Next consider the case for Boolean constants. We perform a kind of
|
|
Next consider the case for Boolean constants. We perform a kind of
|
|
partial evaluation\index{subject}{partial evaluation} and output
|
|
partial evaluation\index{subject}{partial evaluation} and output
|
|
either the \code{thn} or \code{els} branch depending on whether the
|
|
either the \code{thn} or \code{els} branch depending on whether the
|
|
-constant is \TRUE{} or \FALSE{}. This case demonstrates that we
|
|
|
|
-sometimes discard the \code{thn} or \code{els} blocks that are input
|
|
|
|
-to \code{explicate\_pred}.
|
|
|
|
|
|
+constant is \TRUE{} or \FALSE{}. Let us illustrate this with the
|
|
|
|
+following program.
|
|
|
|
+\begin{center}
|
|
|
|
+\begin{minipage}{\textwidth}
|
|
|
|
+\begin{lstlisting}
|
|
|
|
+(if #t 42 777)
|
|
|
|
+\end{lstlisting}
|
|
|
|
+\end{minipage}
|
|
|
|
+\end{center}
|
|
|
|
+%
|
|
|
|
+Again, the two branches \code{42} and \code{777} were compiled to
|
|
|
|
+\code{return} statements, so \code{explicate\_pred} compiles the
|
|
|
|
+constant \code{\#t} to the code for the ``then'' branch.
|
|
|
|
+\begin{center}
|
|
|
|
+\begin{minipage}{\textwidth}
|
|
|
|
+\begin{lstlisting}
|
|
|
|
+return 42;
|
|
|
|
+\end{lstlisting}
|
|
|
|
+\end{minipage}
|
|
|
|
+\end{center}
|
|
|
|
+%
|
|
|
|
+This case demonstrates that we sometimes discard the \code{thn} or
|
|
|
|
+\code{els} blocks that are input to \code{explicate\_pred}.
|
|
|
|
|
|
The case for \key{if} expressions in \code{explicate\_pred} is
|
|
The case for \key{if} expressions in \code{explicate\_pred} is
|
|
particularly illuminating because it deals with the challenges we
|
|
particularly illuminating because it deals with the challenges we
|
|
@@ -7826,8 +7938,8 @@ the dictionary of basic blocks, labeling it as the ``start'' block.
|
|
|
|
|
|
%% Getting back to the case for \code{if} in \code{explicate\_pred}, we
|
|
%% Getting back to the case for \code{if} in \code{explicate\_pred}, we
|
|
%% make the recursive calls to \code{explicate\_pred} on the ``then'' and
|
|
%% make the recursive calls to \code{explicate\_pred} on the ``then'' and
|
|
-%% ``else'' branches with the arguments \code{(block->goto} $B_1$\code{)}
|
|
|
|
-%% and \code{(block->goto} $B_2$\code{)}. Let $B_3$ and $B_4$ be the
|
|
|
|
|
|
+%% ``else'' branches with the arguments \code{(create_block} $B_1$\code{)}
|
|
|
|
+%% and \code{(create_block} $B_2$\code{)}. Let $B_3$ and $B_4$ be the
|
|
%% results from the two recursive calls. We complete the case for
|
|
%% results from the two recursive calls. We complete the case for
|
|
%% \code{if} by recursively apply \code{explicate\_pred} to the condition
|
|
%% \code{if} by recursively apply \code{explicate\_pred} to the condition
|
|
%% of the \code{if} with the promised blocks $B_3$ and $B_4$ to obtain
|
|
%% of the \code{if} with the promised blocks $B_3$ and $B_4$ to obtain
|
|
@@ -7838,14 +7950,6 @@ the dictionary of basic blocks, labeling it as the ``start'' block.
|
|
%% B_5
|
|
%% B_5
|
|
%% \]
|
|
%% \]
|
|
|
|
|
|
-\racket{The \code{explicate\_tail} and \code{explicate\_assign}
|
|
|
|
- functions need additional cases for Boolean constants and \key{if}.
|
|
|
|
- In the cases for \code{if}, the two branches inherit the current
|
|
|
|
- context, so in \code{explicate\_tail} they are in tail position and
|
|
|
|
- in \code{explicate\_assign} they are in assignment position. The
|
|
|
|
- \code{cont} parameter of \code{explicate\_assign} is used in both
|
|
|
|
- recursive calls, so make sure to use \code{block->goto} on it.}
|
|
|
|
-
|
|
|
|
%% In the case for \code{if} in \code{explicate\_tail}, the two branches
|
|
%% In the case for \code{if} in \code{explicate\_tail}, the two branches
|
|
%% inherit the current context, so they are in tail position. Thus, the
|
|
%% inherit the current context, so they are in tail position. Thus, the
|
|
%% recursive calls on the ``then'' and ``else'' branch should be calls to
|
|
%% recursive calls on the ``then'' and ``else'' branch should be calls to
|
|
@@ -7853,7 +7957,7 @@ the dictionary of basic blocks, labeling it as the ``start'' block.
|
|
%% %
|
|
%% %
|
|
%% We need to pass $B_0$ as the accumulator argument for both of these
|
|
%% We need to pass $B_0$ as the accumulator argument for both of these
|
|
%% recursive calls, but we need to be careful not to duplicate $B_0$.
|
|
%% recursive calls, but we need to be careful not to duplicate $B_0$.
|
|
-%% Thus, we first apply \code{block->goto} to $B_0$ so that it gets added
|
|
|
|
|
|
+%% Thus, we first apply \code{create_block} to $B_0$ so that it gets added
|
|
%% to the control-flow graph and obtain a promised goto $G_0$.
|
|
%% to the control-flow graph and obtain a promised goto $G_0$.
|
|
%% %
|
|
%% %
|
|
%% Let $B_1$ be the result of \code{explicate\_tail} on the ``then''
|
|
%% Let $B_1$ be the result of \code{explicate\_tail} on the ``then''
|
|
@@ -7877,7 +7981,7 @@ the dictionary of basic blocks, labeling it as the ``start'' block.
|
|
%% variable $x$ and then the control continues to some promised block
|
|
%% variable $x$ and then the control continues to some promised block
|
|
%% $B_1$. The code that we generate for both the ``then'' and ``else''
|
|
%% $B_1$. The code that we generate for both the ``then'' and ``else''
|
|
%% branches needs to continue to $B_1$, so to avoid duplicating $B_1$ we
|
|
%% branches needs to continue to $B_1$, so to avoid duplicating $B_1$ we
|
|
-%% apply \code{block->goto} to it and obtain a promised goto $G_1$. The
|
|
|
|
|
|
+%% apply \code{create_block} to it and obtain a promised goto $G_1$. The
|
|
%% branches of the \key{if} inherit the current context, so they are in
|
|
%% branches of the \key{if} inherit the current context, so they are in
|
|
%% assignment positions. Let $B_2$ be the result of applying
|
|
%% assignment positions. Let $B_2$ be the result of applying
|
|
%% \code{explicate\_assign} to the ``then'' branch, variable $x$, and
|
|
%% \code{explicate\_assign} to the ``then'' branch, variable $x$, and
|
|
@@ -7917,7 +8021,7 @@ Here was see that our algorithm sometimes inserts unnecessary blocks:
|
|
and \code{block\_5} is just a \code{goto} to \code{block\_3}.
|
|
and \code{block\_5} is just a \code{goto} to \code{block\_3}.
|
|
It would be better to skip blocks \code{block\_4} and \code{block\_5}
|
|
It would be better to skip blocks \code{block\_4} and \code{block\_5}
|
|
and go directly to \code{block\_2} and \code{block\_3},
|
|
and go directly to \code{block\_2} and \code{block\_3},
|
|
-which we investigate doing in Section~\ref{sec:opt-jumps}.
|
|
|
|
|
|
+which we investigate in Section~\ref{sec:opt-jumps}.
|
|
Getting back to the example, \code{block\_2} and \code{block\_3},
|
|
Getting back to the example, \code{block\_2} and \code{block\_3},
|
|
corresponds to the two branches of the outer \key{if}, i.e.,
|
|
corresponds to the two branches of the outer \key{if}, i.e.,
|
|
\racket{\code{(+ y 2)}}\python{\code{y + 2}} and
|
|
\racket{\code{(+ y 2)}}\python{\code{y + 2}} and
|
|
@@ -7947,22 +8051,35 @@ The story for \code{block\_9} is similar to that of \code{block\_8}.
|
|
$\Rightarrow$
|
|
$\Rightarrow$
|
|
&
|
|
&
|
|
\begin{minipage}{0.55\textwidth}
|
|
\begin{minipage}{0.55\textwidth}
|
|
- TODO: replace with non-optimized version. -Jeremy
|
|
|
|
\begin{lstlisting}
|
|
\begin{lstlisting}
|
|
start:
|
|
start:
|
|
x = (read);
|
|
x = (read);
|
|
y = (read);
|
|
y = (read);
|
|
- if (< x 1) goto block40;
|
|
|
|
- else goto block41;
|
|
|
|
-block40:
|
|
|
|
- if (eq? x 0) goto block38;
|
|
|
|
- else goto block39;
|
|
|
|
-block41:
|
|
|
|
- if (eq? x 2) goto block38;
|
|
|
|
- else goto block39;
|
|
|
|
-block38:
|
|
|
|
|
|
+ if (< x 1)
|
|
|
|
+ goto block_8;
|
|
|
|
+ else
|
|
|
|
+ goto block_9;
|
|
|
|
+block_8:
|
|
|
|
+ if (eq? x 0)
|
|
|
|
+ goto block_4;
|
|
|
|
+ else
|
|
|
|
+ goto block_5;
|
|
|
|
+block_9:
|
|
|
|
+ if (eq? x 2)
|
|
|
|
+ goto block_6;
|
|
|
|
+ else
|
|
|
|
+ goto block_7;
|
|
|
|
+block_4:
|
|
|
|
+ goto block_2;
|
|
|
|
+block_5:
|
|
|
|
+ goto block_3;
|
|
|
|
+block_6:
|
|
|
|
+ goto block_2;
|
|
|
|
+block_7:
|
|
|
|
+ goto block_3;
|
|
|
|
+block_2:
|
|
return (+ y 2);
|
|
return (+ y 2);
|
|
-block39:
|
|
|
|
|
|
+block_3:
|
|
return (+ y 10);
|
|
return (+ y 10);
|
|
\end{lstlisting}
|
|
\end{lstlisting}
|
|
\end{minipage}
|
|
\end{minipage}
|
|
@@ -8728,7 +8845,7 @@ block.
|
|
%
|
|
%
|
|
{\if\edition\racketEd
|
|
{\if\edition\racketEd
|
|
%
|
|
%
|
|
-The following auxiliary function named \code{block->goto} accomplishes
|
|
|
|
|
|
+The following auxiliary function named \code{create\_block} accomplishes
|
|
this task. It begins with \code{delay} to create a promise. When
|
|
this task. It begins with \code{delay} to create a promise. When
|
|
forced, this promise will force the original promise. If that returns
|
|
forced, this promise will force the original promise. If that returns
|
|
a \code{goto} (because the block was already added to the control-flow
|
|
a \code{goto} (because the block was already added to the control-flow
|
|
@@ -8737,7 +8854,7 @@ the control-flow graph with another auxiliary function named
|
|
\code{add-node}. That function returns the label for the new block,
|
|
\code{add-node}. That function returns the label for the new block,
|
|
which we use to create a \code{goto}.
|
|
which we use to create a \code{goto}.
|
|
\begin{lstlisting}
|
|
\begin{lstlisting}
|
|
-(define (block->goto block)
|
|
|
|
|
|
+(define (create_block block)
|
|
(delay
|
|
(delay
|
|
(define b (force block))
|
|
(define b (force block))
|
|
(match b
|
|
(match b
|