Sun Studio 12 Update 1: Fortran User's Guide

2.3.1 General Directives

The various forms of a general Fortran directive are:

C$PRAGMA keyword ( a [ , a ] ) [ , keyword ( a [ , a ] ) ] ,

C$PRAGMA SUN keyword ( a [ , a ] … ) [ , keyword ( a [ , a ] … ) ] ,…

C$PRAGMA SPARC keyword ( a [ , a ] … ) [ , keyword ( a [ , a ] … ) ] ,…

The variable keyword identifies the specific directive. Additional arguments or suboptions may also be allowed. (Some directives require the additional keyword SUN or SPARC, as shown above.)

A general directive has the following syntax:

Observe the following restrictions:

The Fortran compiler recognize the following general directives:

Table 2–2 Summary of General Fortran Directives

C Directive

C$PRAGMA C(list)

Declares a list of names of external functions as C language routines. 

IGNORE_TKR Directive

C$PRAGMA IGNORE_TKR {name {, name} ...}

The compiler ignores the type, kind, and rank of the specified dummy argument names appearing in a generic procedure interface when resolving a specific call. 

UNROLL Directive

C$PRAGMA SUN UNROLL=n

Advises the compiler that the following loop can be unrolled to a length n.

WEAK Directive

C$PRAGMA WEAK(name[=name2])

Declares name to be a weak symbol, or an alias for name2.

OPT Directive

C$PRAGMA SUN OPT=n

Set optimization level for a subprogram to n.

PIPELOOP Directive

C$PRAGMA SUN PIPELOOP=n

Assert dependency in the following loop exists between iterations n apart.

PREFETCH Directives

C$PRAGMA SUN_PREFETCH_READ_ONCE(name)C$PRAGMA SUN_PREFETCH_READ_MANY(name)C$PRAGMA SUN_PREFETCH_WRITE_ONCE(name)C$PRAGMA SUN_PREFETCH_WRITE_MANY(name)

Request compiler generate prefetch instructions for references to name. (Requires -xprefetch option, which is enabled by default. Prefetch directives can be disabled by compiling with —xprefetch=no. Target architecture must also support prefetch instructions, and the compiler optimization level must be greater than —xO2.)

ASSUME Directives

C$PRAGMA [BEGIN} ASSUME (expression [,probability])

C$PRAGMA END ASSUME

Make assertions about conditions at certain points in the program that the compiler can assume are true. 

2.3.1.1 The C Directive

The C() directive specifies that its arguments are external functions.It is equivalent to an EXTERNAL declaration except that unlike ordinary external names, the Fortran compiler will not append an underscore to these argument names. See the C-Fortran Interface chapter in the Fortran Programming Guide for more details.

The C() directive for a particular function should appear before the first reference to that function in each subprogram that contains such a reference.

Example - compiling ABC and XYZ for C:


       EXTERNAL ABC, XYZ
C$PRAGMA C(ABC, XYZ)

2.3.1.2 The IGNORE_TKR Directive

This directive causes the compiler to ignore the type, kind, and rank of the specified dummy argument names appearing in a generic procedure interface when resolving a specific call.

For example, in the procedure interface below, the directive specifies that SRC can be any data type, but LEN can be either KIND=4 or KIND=8.The interface block defines two specific procedures for a generic procedure name.This example is shown in Fortran 95 free format.


INTERFACE BLCKX

SUBROUTINE BLCK_32(LEN,SRC)
  REAL SRC(1)
!$PRAGMA IGNORE_TKR SRC
  INTEGER (KIND=4) LEN
END SUBROUTINE

SUBROUTINE BLCK_64(LEN,SRC)
  REAL SRC(1)
!$PRAGMA IGNORE_TKR SRC
  INTEGER (KIND=8) LEN
END SUBROUTINE

END INTERFACE

The subroutine call:

INTEGER L
REAL S(100)
CALL BLCKX(L,S)

The call to BLCKX will call BLCK_32 when compiled normally, and BLCK_64 when compiled with -xtypemap=integer:64. The actual type of S does not determine which routine to call. This greatly simplifies writing generic interfaces for wrappers that call specific library routines based on argument type, kind, or rank.

Note that dummy arguments for assumed-shape arrays, Fortran pointers, or allocatable arrays cannot be specified on the directive. If no names are specified, the directive applies to all dummy arguments to the procedure, except dummy arguments that are assumed-shape arrays, Fortran pointers, or allocatable arrays.

2.3.1.3 The UNROLL Directive

The UNROLL directive requires that you specify SUN after C$PRAGMA.

The C$PRAGMA SUN UNROLL=n directive instructs the compiler to unroll the following loop n times during its optimization pass. (The compiler will unroll a loop only when its analysis regards such unrolling as appropriate.)

n is a positive integer. The choices are:

If any loops are actually unrolled, the executable file becomes larger. For further information, see the Fortran Programming Guide chapter on performance and optimization.

Example - unrolling loops two times:


C$PRAGMA SUN UNROLL=2

2.3.1.4 The WEAK Directive

The WEAK directive defines a symbol to have less precedence than an earlier definition of the same symbol. This pragma is used mainly in sources files for building libraries. The linker does not produce an error message if it is unable to resolve a weak symbol.


C$PRAGMA WEAK (name1 [=name2])

WEAK (name1) defines name1 to be a weak symbol. The linker does not produce an error message if it does not find a definition for name1.

WEAK (name1=name2) defines name1 to be a weak symbol and an alias for name2.

If your program calls but does not define name1, the linker uses the definition from the library. However, if your program defines its own version of name1, then the program’s definition is used and the weak global definition of name1 in the library is not used. If the program directly calls name2, the definition from library is used; a duplicate definition of name2 causes an error. See the Solaris Linker and Libraries Guide for more information.

2.3.1.5 The OPT Directive

The OPT directive requires that you specify SUN after C$PRAGMA.

The OPT directive sets the optimization level for a subprogram, overriding the level specified on the compilation command line. The directive must appear immediately before the target subprogram, and only applies to that subprogram. For example:


C$PRAGMA SUN OPT=2
        SUBROUTINE smart(a,b,c,d,e)
        ...etc

When the above is compiled with an f95 command that specifies -O4, the directive will override this level and compile the subroutine at -O2. Unless there is another directive following this routine, the next subprogram will be compiled at -O4.

The routine must also be compiled with the -xmaxopt[=n] option for the directive to be recognized. This compiler option specifies a maximum optimization value for PRAGMA OPT directives: if a PRAGMA OPT specifies an optimization level greater than the -xmaxopt level, the -xmaxopt level is used.

2.3.1.6 The PIPELOOP[=n] Directive

The PIPELOOP=n directive requires that you specify SUN after C$PRAGMA.

This directive must appear immediately before a DO loop. n is a positive integer constant, or zero, and asserts to the optimizer a dependence between loop iterations. A value of zero indicates that the loop has no inter-iteration (loop-carried) dependencies and can be freely pipelined by the optimizer. A positive n value implies that the I-th iteration of the loop has a dependency on the (I-n)-th iteration, and can be pipelined at best for only n iterations at a time. (Default if n is not specified is 0)


C    We know that the value of K is such that there can be no
C    cross-iteration dependencies (E.g. K>N)
C$PRAGMA SUN PIPELOOP=0
      DO I=1,N
       A(I)=A(I+K) + D(I)
       B(I)=B(I) + A(I)
      END DO

For more information on optimization, see the Fortran Programming Guide.

2.3.1.7 The PREFETCH Directives

The -xprefetch option flag, 3.4.157 –xprefetch[=a[,a]], enables a set of PREFETCH directives that advise the compiler to generate prefetch instructions for the specified data element on processors that support prefetch.


C$PRAGMA SUN_PREFETCH_READ_ONCE(name)
C$PRAGMA SUN_PREFETCH_READ_MANY(name)
C$PRAGMA SUN_PREFETCH_WRITE_ONCE(name)
C$PRAGMA SUN_PREFETCH_WRITE_MANY(name)

See also the C User’s Guide, or the SPARC Architecture Manual, Version 9 for further information about prefetch instructions.

2.3.1.8 The ASSUME Directives

The ASSUME directive gives the compiler hints about conditions at certain points in the program. These assertions can help the compiler to guide its optimization strategies. The programmer can also use these directives to check the validity of the program during execution. There are two formats for ASSUME.

The syntax of the “point assertion” ASSUME is


C$PRAGMA ASSUME (expression [,probability])

Alternatively, the “range assertion” ASSUME is:


C$PRAGMA BEGIN ASSUME [expression [, probability)
     block of statements
C$PRAGMA END ASSUME

Use the point assertion form to state a condition that the compiler can assume at that point in the program. Use the range assertion form to state a condition that holds over the enclosed range of statements. The BEGIN and END pairs in a range assertion must be properly nested.

The required expression is a boolean expression that can be evaluated at that point in the program that does not involve user-defined operators or function calls except for those listed below.

The optional probability value is a real number from 0.0 to 1.0, or an integer 0 or 1, giving the probability of the expression being true. A probability of 0.0 (or 0) means never true, and 1.0 (or 1) means always true. If not specified, the expression is considered to be true with a high probability, but not a certainty. An assertion with a probability other than exactly 0 or 1 is a non-certain assertion. Similarly, an assertion with a probability expressed exactly as 0 or 1 is a certain assertion.

For example, if the programmer knows that the length of a DO loop is always greater than 10,000, giving this hint to the compiler can enable it to produce better code. The following loop will generally run faster with the ASSUME pragma than without it.


C$PRAGMA BEGIN ASSUME(__tripcount().GE.10000,1) !! a big loop
        do i = j, n
           a(i) = a(j) + 1
        end do
C$PRAGMA END ASSUME

Two intrinsic functions are available for use specifically in the expression clause of the ASSUME directive. (Note that their names are prefixed by two underscores.)

__branchexp()

Use in point assertions placed immediately before a branching statement with a boolean controlling expression. It yields the same result as the boolean expression controlling the branching statement. 

__tripcount()

Yields the trip count of the loop immediately following or enclosed by the directive. When used in a point assertion, the statement following the directive must be the first line of a DO. When used in a range assertion, it applies to the outermost enclosed loop.

This list of special intrinsics might expand in future releases.

Use with the -xassume_control compiler option. (See 3.4.111 –xassume_control[=keywords]) For example, when compiled with -xassume_control=check, the example above would produce a warning if the trip count ever became less than 10,000.

Compiling with -xassume_control=retrospective will generate a summary report at program termination of the truth or falsity of all assertions. See the f95 man page for details on -xassume_control.

Another example:


C$PRAGMA ASSUME(__tripcount.GT.0,1)
       do i=n0, nx

Compiling the above example with -xassume_control=check will issue a runtime warning should the loop not be taken because the trip count is zero or negative.