At 06:05 PM 3/7/98 -0500, [log in to unmask] wrote:
[snip]
>
>SUBROUTINE EXAMPLE(X,Y,Z)
>REAL, INTENT(INOUT) :: X, Y
>REAL, INTENT(OUT) :: Z
>Z = F(X,Y)
>... ! BODY to be discussed below
>END SUBROUTINE EXAMPLE
>
>where EXAMPLE is invoked as follows
>
>CALL EXAMPLE(A, A, B)
>
>and B is not aliased with A. If the remainder of the body has either of the
>forms
>
>X = Y
>Y = X
>
>or
>
>X = Z
>Y = Z
>
>I believe the result of the call is not defined under a strict reading of the
>Fortran standard, but will yield the expected results in practice. However,
>if the remainder of the body has the form
Correct, it is not defined by the standard, and also might NOT yield the
expected results. Depends a little on what occurred before these statements
If there was a statement like
ZZZZZ = Y
and no references to X then the compiler might realize that it already had the
address for Y in a register and generate code like
load address of Z
load address of X
load Z
store Z into Y (using address from ZZZZZ line)
store Z into X
This potentially saves a few cycles since the store into Y can be issued
while the address of X is coming from memory.
[snip]
>
>A way to reason about what might be expected from the output of a Fortran
>compiler is to realize that the standard nominally allows two simple forms of
>argument passing (I believe it allows more complex forms). These two forms
>are nominally termed pass by reference and copy-in/copy out. Under pass by
>reference all arguments are automatically updated in the context of the
>calling procedure when it is modified, so that a modification of an argument
>immediately modifies any of its aliases. Under copy-in/copy-out, all
>arguments are thought of as copied in at the start of the call, modified
>independently, and then are copied out, so that a modification of an argument
>does not immediately modify any of its aliases. A necessary (but possibly not
>sufficient) condition for a procedure to be defined under the semantics of
>Fortran, is that it give the same result for its arguments if either pass by
>reference or copy-in/copy-out is used in an implementation.
>
I think it is more complicated. The standard is also optimizer friendly.
It allows the compiler to take advantage of the fact that arguments can't
overlap and to generate "efficient" code.
1) Loads can be issued out of order. A sequence like
A = B
C = 1.0/D
is likely to load D and start the time consuming divide before doing the
load for B.
2) Stores don't have to be issued immediatly
A = 3.14
... lots of uses, but no stores, of A
A = 2.718
...
end
The compiler doesn't necessarily have to store 3.14 into A at all, it can
keep the value in a register (assuming it can see everything and understand
it all). The actual store of 2.718 into A from a register can be deferred
until there is a gap in the instruction scheduling sequence. So definitions
don't necessarily affect the aliases in a predictable way.
3) the "copy out" doesn't have to go from left to right in the argument
list. Backwards (down the stack?) might be natural for some cache
organizations. Or even pseudo random if some values are in registers and
some have to be fetched from the copied-in memory for the copyout.
I think the conclusion is "don't do this", it will do what you expect on
many machines/compilers, but will bite you when you change something
that looks innocent.
Dick Hendrickson
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|