Next: , Previous: Surprising Interpretations of Code, Up: Working Programs



14.4.7 Aliasing Assumed To Work

The -falias-check, -fargument-alias, -fargument-noalias, and -fno-argument-noalias-global options, introduced in version 0.5.20 and g77's version 2.7.2.2.f.2 of gcc, were withdrawn as of g77 version 0.5.23 due to their not being supported by gcc version 2.8.

These options control the assumptions regarding aliasing (overlapping) of writes and reads to main memory (core) made by the gcc back end.

The information below still is useful, but applies to only those versions of g77 that support the alias analysis implied by support for these options.

These options are effective only when compiling with -O (specifying any level other than -O0) or with -falias-check.

The default for Fortran code is -fargument-noalias-global. (The default for C code and code written in other C-based languages is -fargument-alias. These defaults apply regardless of whether you use g77 or gcc to compile your code.)

Note that, on some systems, compiling with -fforce-addr in effect can produce more optimal code when the default aliasing options are in effect (and when optimization is enabled).

If your program is not working when compiled with optimization, it is possible it is violating the Fortran standards (77 and 90) by relying on the ability to “safely” modify variables and arrays that are aliased, via procedure calls, to other variables and arrays, without using EQUIVALENCE to explicitly set up this kind of aliasing.

(The FORTRAN 77 standard's prohibition of this sort of overlap, generally referred to therein as “storage association”, appears in Sections 15.9.3.6. This prohibition allows implementations, such as g77, to, for example, implement the passing of procedures and even values in COMMON via copy operations into local, perhaps more efficiently accessed temporaries at entry to a procedure, and, where appropriate, via copy operations back out to their original locations in memory at exit from that procedure, without having to take into consideration the order in which the local copies are updated by the code, among other things.)

To test this hypothesis, try compiling your program with the -fargument-alias option, which causes the compiler to revert to assumptions essentially the same as made by versions of g77 prior to 0.5.20.

If the program works using this option, that strongly suggests that the bug is in your program. Finding and fixing the bug(s) should result in a program that is more standard-conforming and that can be compiled by g77 in a way that results in a faster executable.

(You might want to try compiling with -fargument-noalias, a kind of half-way point, to see if the problem is limited to aliasing between dummy arguments and COMMON variables—this option assumes that such aliasing is not done, while still allowing aliasing among dummy arguments.)

An example of aliasing that is invalid according to the standards is shown in the following program, which might not produce the expected results when executed:

     I = 1
     CALL FOO(I, I)
     PRINT *, I
     END
     
     SUBROUTINE FOO(J, K)
     J = J + K
     K = J * K
     PRINT *, J, K
     END

The above program attempts to use the temporary aliasing of the J and K arguments in FOO to effect a pathological behavior—the simultaneous changing of the values of both J and K when either one of them is written.

The programmer likely expects the program to print these values:

     2  4
     4

However, since the program is not standard-conforming, an implementation's behavior when running it is undefined, because subroutine FOO modifies at least one of the arguments, and they are aliased with each other. (Even if one of the assignment statements was deleted, the program would still violate these rules. This kind of on-the-fly aliasing is permitted by the standard only when none of the aliased items are defined, or written, while the aliasing is in effect.)

As a practical example, an optimizing compiler might schedule the J = part of the second line of FOO after the reading of J and K for the J * K expression, resulting in the following output:

     2  2
     2

Essentially, compilers are promised (by the standard and, therefore, by programmers who write code they claim to be standard-conforming) that if they cannot detect aliasing via static analysis of a single program unit's EQUIVALENCE and COMMON statements, no such aliasing exists. In such cases, compilers are free to assume that an assignment to one variable will not change the value of another variable, allowing it to avoid generating code to re-read the value of the other variable, to re-schedule reads and writes, and so on, to produce a faster executable.

The same promise holds true for arrays (as seen by the called procedure)—an element of one dummy array cannot be aliased with, or overlap, any element of another dummy array or be in a COMMON area known to the procedure.

(These restrictions apply only when the procedure defines, or writes to, one of the aliased variables or arrays.)

Unfortunately, there is no way to find all possible cases of violations of the prohibitions against aliasing in Fortran code. Static analysis is certainly imperfect, as is run-time analysis, since neither can catch all violations. (Static analysis can catch all likely violations, and some that might never actually happen, while run-time analysis can catch only those violations that actually happen during a particular run. Neither approach can cope with programs mixing Fortran code with routines written in other languages, however.)

Currently, g77 provides neither static nor run-time facilities to detect any cases of this problem, although other products might. Run-time facilities are more likely to be offered by future versions of g77, though patches improving g77 so that it provides either form of detection are welcome.