Node: Aliasing Assumed To Work, Next: Output Assumed To Flush, Previous: Surprising Interpretations of Code, Up: Working Programs
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.