Many of our compiler passes are designed to work with Fortran DO
loops because they are relatively easy to analyze. A DO
loop has
a single index variable that is incremented or decremented on every
iteration and varies from an initial to a final value. SUIF uses
tree_for
nodes to represent well-structured DO
loops. The
exact conditions that a loop must meet to be represented as a
tree_for
in SUIF are described below. The expander's cleanup
pass, which is run immediately after the front-end, converts
tree_for
nodes that violate any of these conditions into
tree_loop
nodes (see section Loop Nodes). Even though they are
primarily intended for Fortran code, tree_for
nodes may also be
used for C loops that meet the same conditions.
The index variable of a tree_for
can be accessed using the
index
method and set using the set_index
method. The
index variable must be a scalar variable that is defined in the scope of
the tree_for
node. It may not be modified anywhere within the
loop body. This applies across procedures as well. If the loop body
contains a call to another procedure that modifies the index variable,
then the loop cannot be represented by a tree_for
node.
Moreover, if you are using Fortran form, the index variable may not be a
call-by-reference parameter.
See section Features for Compiling Fortran.
The range of values for the index variable is specified by three
operand
fields. See section Operands. The lower and upper bounds and
the step value can be accessed by the lb_op
, ub_op
, and
step_op
methods. The set_lb_op
, set_ub_op
, and
set_step_op
methods are provided to change them. These operands
are expressions that are evaluated once at the beginning of the loop.
The index variable is initially assigned the lower bound value and then
incremented by the step value on every iteration until it reaches the
upper bound value; the code to do this is automatically created when the
tree_for
is expanded to low-SUIF code.
Most users will always use tree_for
nodes in conjunction with
expression trees. Flat lists of instructions are typically used only in
the library and with back-end passes where the tree_for
nodes
have been dismantled. It is possible to use tree_for
nodes
without expression trees, but the bounds and step values cannot be
treated as operands. In fact, even with expression trees those operands
are actually stored on tree node lists. If necessary, these lists can
be accessed directly using the lb_list
, ub_list
, and
step_list
methods. Each list is required to contain a single
expression with a dummy copy instruction at the root. The destination
of the dummy copy must be a null operand. Methods are provided in the
tree node list class to extract the operands from the tree node lists
(see section Tree Node Lists).
The tree_for
must also specify the comparison operator used to
determine when the index variable has reached the upper bound value.
The possible comparison operators are members of the
tree_for_test
enumerated type. The test
and
set_test
methods are used to access and modify the comparison
operator for a tree_for
node. The tree_for_test
enumeration includes quite a few comparison operators, but some of them
are only used by the front-end. Both signed and unsigned versions are
available for most of the comparison operators, as indicated by the
letters "S
" and "U
" in their names.
FOR_SLT
FOR_ULT
FOR_SLTE
FOR_ULTE
FOR_SGT
FOR_UGT
DO
loops go backwards, using a negative
step value. For those loops, the comparison operator must also be
reversed.
FOR_SGTE
FOR_UGTE
FOR_SGELE
FOR_UGELE
tree_for
nodes with these tests to two
tree_for
nodes and a tree_if
node to decide between them.
Thus, these comparison operators should never be encountered in most
SUIF code.
FOR_EQ
FOR_NEQ
tree_for
nodes that use
these comparisons.
The body of a tree_for
loop is stored in a tree node list. The
methods to get and set the loop body are body
and
set_body
, respectively. The body
list contains only the
instructions corresponding to the body of the loop in the source
program. The instructions to compare the index variable with the upper
bound, increment it, and branch back to the beginning of the body are
not included as part of the body; they are created when the
tree_for
is expanded to low-SUIF code.
Besides the loop body, a tree_for
node has an additional tree
node list called the landing_pad
. The code in the landing pad
is executed if and only if the loop body is executed at least one
time, but the landing_pad
is executed only once, unlike the
body which is usually executed many times. The landing_pad
is
executed immediately before the first time through the loop body. The
landing pad thus provides a place to move loop-invariant code.
Two labels are associated with a tree_for
: contlab
and
brklab
. A "continue" statement in the loop body requires a
jump over the rest of the body to the code that increments the index and
continues with the next iteration. This can be implemented with a jump
to the contlab
label, which is implicitly located at the end of
the body
list. Similarly, a "break" statement in the loop is
translated to a jump to the brklab
label which is located
immediately after the loop. These two labels must be defined in the
scope of the tree_for
node, but the label instructions that mark
their locations are not inserted into the tree node lists until the
tree_for
node is expanded into low-SUIF form.
In summary, the semantics of a tree_for
node are as follows. The
lower bound, upper bound, and step operands are evaluated once at the
beginning of the loop (2). The lower bound is compared to the upper bound. If
the test fails, the loop does not execute. Otherwise, the lower bound
is assigned to the index variable, and any code in the landing pad list
is executed. After that, the body is executed repeatedly and the index
variable is incremented by the step value on every iteration, until the
index variable fails the test with the upper bound value.
As an example, the following C code could be translated into the SUIF code shown in a simplified form below:
for (i = 100; i >= 0; i--) { A[i] = i; }
FOR (Index=i Test=SGTE Cont=L:__L1 Brk=L:__L2) FOR LB ldc 100 FOR UB ldc 0 FOR STEP ldc -1 FOR LANDING PAD FOR BODY str e1 = i e1: array e2+0, size(32), index(i), bound(e3) e2: ldc <A,0> e3: ldc 101 FOR END