Scalar Optimization Directives

Scalar optimization directives control aspects of code generation, register storage, and other scalar operations.

Scalar optimization directives control aspects of code generation, register storage, and other scalar operations.

[NO]COLLAPSE

!DIR$ COLLAPSE (loop-number1, loop-number2 [,loop-number3] ...)
loop-number
Specify a value greater than or equal to 0 for the primary cache.
!DIR$ NOCOLLAPSE
Scope: Local

When the collapse directive is applied to a loop nest, the loop numbers of the participating loops must be listed in order of increasing access stride. Loop numbers range from 1 to the nesting level of the most deeply nested loop. The directive enables the compiler to assume appropriate conformity between trip counts. The compiler diagnoses misuse at compile time (when able); or, if -h dir_check is specified, at run time.

The nocollapse directive disqualifies the immediately following loop from collapsing with any other loop. Collapse is almost always desirable, so use this directive sparingly. Loop collapse is a special form of loop coalesce. Any perfect loop nest may be coalesced into a single loop, with explicit rediscovery of the intermediate values of original loop control variables. The rediscovery cost, which generally involves integer division, is quite high. Therefore, coalesce is rarely suitable for vectorization. It may be beneficial for multithreading. By definition, loop collapse occurs when loop coalesce may be done without the rediscovery overhead. To meet this requirement, all memory accesses must have uniform stride.

[NO]INTERCHANGE

!DIR$ interchange(loop_number1, loop_number2[, loop_number3] ...)
loop_number
Number from 1 to nesting depth of the most deeply nested loop
!DIR$ nointerchange
Scope: Local

The interchange control directives specify whether or not the order of the following two or more, perfectly nested loops should be interchanged. These directives apply to the subsequent loops.

The interchange directive specifies two or more loop numbers, ranging from 1 to the nesting depth of the most deeply nested loop, specified in any order. The compiler reorders perfectly nested loops. If they are not perfectly nested, unexpected results may occur.

The nointerchange directive inhibits loop interchange on the loop that immediately follows the directive.

NOSIDEEFFECTS

!DIR$ NOSIDEEFFECTS f , f ...
f
Symbolic name of a subprogram that the user is sure has no side effects. f must not be the name of a dummy procedure, module procedure, or internal procedure.

The NOSIDEEFFECTS directive allows the compiler to keep information in registers across a single call to subprogram without reloading the information from memory after returning from the subprogram. The directive is not needed for intrinsic functions.

NOSIDEEFFECTS declares that a called subprogram does not redefine any variables that meet the following conditions:
  • Local to the calling program
  • Passed as arguments to the subprogram
  • Accessible to the calling subprogram through host association
  • Declared in a common block or module
  • Accessible through USE association

A procedure declared NOSIDEEFFECTS should not define variables in a common block or module shared by a program unit in the calling chain. All arguments should have the INTENT(IN) attribute; that is, the procedure must not modify its arguments. If these conditions are not met, results are unpredictable.

The NOSIDEEFFECTS directive must appear in the specification part of a program unit and must appear before the first executable statement.

The compiler may move invocations of a NOSIDEEFFECTS subprogram from the body of a DO loop to the loop preamble if the arguments to that function are invariant in the loop. This may affect the results of the program, particularly if the NOSIDEEFFECTS subprogram calls functions such as the random number generator or the real-time clock.

The effects of the NOSIDEEFFECTS directive are similar to those that can be obtained by specifying the PURE prefix on a function or a subroutine declaration. For more information about the PURE prefix, refer to the Fortran Standard.

SUPPRESS

!DIR$ SUPPRESS var , var ...
var
Variable that is to be stored to memory. If no variables are listed, all variables in the program unit are stored. If more than one variable is specified, use a comma to separate vars.

The SUPPRESS directive suppresses scalar optimization for all variables or only for those specified at the point where the directive appears. This often prevents or adversely affects vectorization of any loop that contains SUPPRESS.

At the point at which !DIR$ SUPPRESS appears in the source code, variables in registers are stored to memory (to be read out at their next reference), and expressions containing any of the affected variables are recomputed at their next reference after !DIR$ SUPPRESS. The effect on optimization is equivalent to that of an external subroutine call with an argument list that includes the variables specified by !DIR$ SUPPRESS (or, if no variable list is included, all variables in the program unit).

SUPPRESS takes effect only if it is on an execution path. Optimization proceeds normally if the directive path is not executed because of a GOTO or IF.

      SUBROUTINE SUB (L)
      LOGICAL L
      A = 1.0          ! A is local
      IF (L) THEN
!DIR$ SUPPRESS         ! Has no effect if L is false
        CALL ROUTINE()
      ELSE
        PRINT *, A
      END IF
      END

In this example, optimization replaces the reference to A in the PRINT statement with the constant 1.0, even though !DIR$ SUPPRESS appears between A=1.0 and the PRINT statement. The IF statement can cause the execution path to bypass !DIR$ SUPPRESS. If SUPPRESS appears before the IF statement, A in PRINT* is not replaced by the constant 1.0.