Go to the previous, next section.

For Nodes

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.

Less than. Repeat as long as the index is strictly less than the upper bound.

Less than or equal. Repeat as long as the index is less than or equal to the upper bound.

Greater than. Repeat as long as the index is strictly greater than the upper bound. Sometimes DO loops go backwards, using a negative step value. For those loops, the comparison operator must also be reversed.

Greater than or equal. Repeat as long as the index is greater than or equal to the upper bound. Again, this may be used when the step value is negative.

These comparisons are only used by the front-end. In FORTRAN, it may not be possible to determine the direction of a loop at compile time. For example, if the step value is not a constant, it could be either positive or negative. These comparison operators indicate that the loop test may be either "greater than or equal" or "less than or equal", depending on the sign of the step value. The expander's cleanup pass converts any 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.

Equal and not equal. These comparisons are only used by the front-end. The expander's cleanup pass dismantles 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)
    ldc 100
    ldc 0
    ldc -1
    str e1 = i
      e1: array e2+0, size(32), index(i), bound(e3)
        e2: ldc <A,0>
          e3: ldc 101

Go to the previous, next section.