Many compiler features are implemented as either command line options or directives. The features implemented as command line options are set at compile time and applied to all files in the compilation. The features implemented through directives are set within your Fortran source code, and they apply to portions of your source code.
This chapter introduces the compiler directive set and describes the general directives. The sections in this chapter are as follows:
Each directive begins with a prefix. The prefix needed for each directive is shown in the directive's description. The following directive prefixes are used:
The prefix used also depends on which Fortran source form you are using, as follows:
Because both fixed source form and free source form accept directives that start with the exclamation point (!), that is the initial character used in all directive syntax descriptions in this manual.
This is the specific directive's syntax. The syntax usually consists of the directive name. Some directives accept arguments. A directive's arguments, if any, are shown in the description for the directive itself.
The following sections describe the general format for directives and explain how directives are continued across source code lines.
|Note: The multiprocessing directives supported in previous MIPSpro Fortran 90 releases are outmoded, and so are the !$PAR, C$PAR, !$, and C$ directive prefixes. This technology is outmoded, but it is still supported for older codes that require this functionality. You are encouraged to modify your code using the OpenMP directives described in Chapter 4, “OpenMP Fortran API Multiprocessing Directives”.|
Some compiler features can be activated on the command line and through compiler directives. The difference is that a command line setting applies to all files in the compilation, but a directive applies to only a program unit or to another specific part of a source file.
Generally, and by default, directives override command line options. There are exceptions to this rule, however. The exceptions, if any, are noted in the introductory text to each directive group.
If a directive appears within a program unit, it applies only to that program unit. Within a program unit, many directives apply only to the loops that they immediately precede.
If a directive appears outside a program unit (for example, prior to program code in a file) it applies to the entire file.
The descriptions for the individual directives indicate the range of the directive.
It is sometimes necessary to continue a directive across one or more source code lines. The continuation character used and its placement within the directive line depends on the type of directive you are using. The introductory text for each directive group indicates the continuation character that is appropriate for that group.
For all directives in this chapter, the prefix for a directive line that is a continuation line is !*$*&.
The loop nest optimization (LNO) directives control loop nest optimizations. By default, directives override command line options. To reverse this, and have command line options override the LNO directives, specify -LNO:ignore_pragmas . To continue a directive, the continuation line must begin with !*$*&.
The LNO directives are described in detail on the lno(5) man page. The following list summarizes the available directives:
The fusion control directives specify whether the compiler should perform loop fusion on the loops that immediately follow these directives. Loop iterations may be peeled as needed during loop fusion. The limit of this peeling is 5, or the number specified by the -LNO:fusion_peeling_limit command line option.
The PREFETCH directive controls the MIPS IV prefetch instruction. Using this directive can increase performance in program units that are likely to encounter cache misses during execution. This directive applies only to the program unit in which it appears.
When the directive is specified, the compiler estimates the memory references that will be cache misses, inserts prefetches for the misses, and schedules the prefetches ahead of their corresponding references. You can specify different levels of prefetching aggressiveness for the primary and secondary cache.
The PREFETCH_REF directive requests prefetching for a specific memory reference. This directive applies only to the loop nest that includes references to array, and the directive must immediately precede the loop nest.
When this directive is specified, all references to array in the subsequent loop nest are ignored by the automatic prefetcher (if enabled).
The following directives control symbol storage:
The ALIGN_SYMBOL and FILL_SYMBOL directives control the way symbols are stored.
The ALIGN_SYMBOL directive aligns the start of symbol at a specified alignment boundary.
The FILL_SYMBOL directive pads symbol with additional storage so that the symbol is assured not to overlap (even partially) with any other data item within the storage of the specified size. The additional padding required is divided between each end of the specified variable. For example, a FILL_SYMBOL(X,L1CACHELINE) directive guarantees that X does not suffer from false sharing for the primary cache line.
The formats for these directives are as follows:
!*$* ALIGN_SYMBOL (symbol [, storage]) !*$* FILL_SYMBOL (symbol [, storage])
Specify the name of a symbol. symbol can be a common block variable or a module name. symbol cannot be a component of a derived type, an array element, a common block, or blank common.
Specify the storage size. Specify one of the following values for storage:
For common block variables, these directives are required at each declaration of the common block. Because the directives modify the allocated storage and its alignment for the named symbol, inconsistent directives can lead to undefined results.
The ALIGN_SYMBOL directive has no effect on fixed-size local symbols, such as simple scalars or arrays of known size (for example symbols declared as REAL(N) or REAL(A(3))). The directive continues to be effective for automatic arrays (stack-allocated arrays of dynamically determined size).
You cannot specify an ALIGN_SYMBOL directive and a FILL_SYMBOL directive for the same symbol .
! X IS A COMMON BLOCK VARIABLE COMMON X! INTEGER(KIND=4) X !*$* ALIGN_SYMBOL (X, 32) ! X WILL START AT A 32-BYTE BOUNDARY. ! WARNING: THE LAYOUT OF THE COMMON BLOCK WILL BE AFFECTED !*$* ALIGN_SYMBOL (X, 2) ! ERROR: CANNOT REQUEST AN ALIGNMENT LOWER THAN THE NATURAL ! ALIGNMENT OF THE SYMBOL. REAL(KIND=8) Y ! Y IS A COMMON BLOCK OR LOCAL VARIABLE !*$* FILL_SYMBOL (Y, L2CACHELINE) ! ALLOCATE EXTRA STORAGE BOTH BEFORE AND AFTER Y SO THAT ! Y IS WITHIN AN L2CACHELINE (128 BYTES) ALL BY ITSELF. ! THIS CAN BE USEFUL TO AVOID FALSE-SHARING BETWEEN MULTIPLE ! PROCESSORS FOR THE CACHE LINE CONTAINING Y.
The FLUSH directive identifies synchronization points at which thread-visible variables are written back to memory. This directive must appear at the precise point in the code at which the synchronization is required.
|Note: This directive has the same effect as the FLUSH directive described in the OpenMP Fortran API.|
Thread-visible variables include the following data items:
Globally visible variables (common blocks and modules).
Local variables that do not have the SAVE attribute but have had their address taken and saved or have had their address passed to another subprogram.
Local variables that do not have the SAVE attribute that are declared shared in a parallel region within the subprogram.
All pointer dereferences.
This directive has the following format:
!*$* FLUSH [(var[, var] ...)]
The compiler can reference global data by using the global pointer and an offset value. Using the global pointer (gp) is more efficient than constructing the address at each occurence, but because the offset size is limited to 16 bits, only a limited set of elements can be referenced using the global pointer.
The compiler places global data in gp-relative or non-gp-relative sections, but you can use the SECTION_GP and SECTION_NON_GP directives to specify the variables to go within the gp-relative section and the variables that need to be addressed explicitly.
The formats for these directives are as follows:
!*$* SECTION_GP (symbol [, symbol] ...) !*$* SECTION_NON_GP (symbol [, symbol] ...)
Enter one or more symbols. Separate multiple symbols with commas. Valid symbols are common block names, variables specified on SAVE statements, and module names. If a module name is specified, all storage in the module is affected. If a common block name is specified, it must be of the following form: /name/ .
|Note: Neither inlining nor IPA are enabled by default. By default, the directives in this section, if present in your source code, are ignored. To enable the directives and turn on inlining and IPA, specify the -INLINE: option or the -IPA: option on your f90(1) command line. For more information on the command line interaction with these features, see the f90 (1) or ipa(5) man page.|
Inlining is the process of replacing a procedure reference with a copy of the procedure's code. This eliminates procedure call overhead and exposes the relationships between the procedure code, the return value, and the surrounding code. The INLINE and NOINLINE directives allow you to specify procedures that should be inlined.
Interprocedural analysis (IPA) is a compiler feature that includes inlining, common block array padding, constant propagation, dead procedure elimination, dead variable elimination, and global name optimizations. For detailed information on the IPA feature, see the ipa(5) man page. The IPA and NOIPA directives allow you to control IPA.
The formats of these directives are as follows:
!*$* INLINE location [(name [,name] ...)] !*$* NOINLINE location [(name [,name] ...)] !*$* IPA location [(name [,name] ...)] !*$* NOIPA location [(name [,name] ...)]
Specify one of the following for location:
For the inlining directives, each name specification represents one or more routines to be inlined. If no routines are named, all routines in the program are inlined.
For the IPA directives, each name specification represents one or more routines to undergo IPA. If no routines are named, all routines in the program undergo IPA.
Consider the following code fragment:
DO I = 1,N !*$* INLINE HERE (BETA) CALL BETA(I,1) ENDDO CALL BETA(N,2)
Using the specifier ROUTINE rather than HERE in this example would inline both calls to BETA. Note that -INLINE:=ON must be specified on the f90(1) command line when this code is compiled in order for the inlining directive to be recognized.