On 07/14/2011 11:21 AM, Richard Guenther wrote:
That Fortran passes everything by reference is really really not helping
optimizers.
I think it also does not harm optimizers. The problem is just that
optimizers are not tuned for it - but for C with later (C99?) attached
qualifiers.
Whether one has
int func(int arg) {
do_something_with_arg
return arg;
}
or
subroutine func(arg) ! arg passed by reference
integer :: arg
shouldn't make any difference for optimizers. The value can only change
by either directly modifying "arg" or by calling a procedure with it as
explicit actual argument, which modifies it.
In Fortran, any tricks like modifying "arg" via a global variable (which
shares the memory location with "arg") are invalid. It is not even
allowed to read the value of the global variable (having the same memory
address as "arg"), if the value of "arg" is modified in "func" - not
even before it is modified.
If one wants to play those tricks, "arg" needs to have at least the
TARGET attribute (i.e. some pointer may point to it) - or even the
POINTER attribute, for which nearly anything goes.
Some of the restrictions are compile-time checkable, i.e. if you try to
pass a non-target, non-pointer variable as actual argument to a
pointer-dummy argument, you will get a compile-time error.
For others, it's the users responsibility. For instance, you may pass a
non-TARGET variable to a function taking a TARGET as dummy argument, but
as soon as that function returns, all pointers to the dummy become
undefined.
The advantage of Fortran is that it not only applies to basic types like
"int" but also to character strings, arrays - and to "allocatables".
Allocatables have to be allocated before one can use them, allowing one
to change the array size or (for deferred-length strings) the string
length. Still, they share the same semantics, i.e. no aliasing unless
there is TARGET or (for non-ALLOCATABLEs) a POINTER attribute.
(Side remark: allocatables [unless SAVE, i.e. in static memory] are
automatically freed, when one leaves their "scoping unit", e.g. for a
variable local to a function, when one leaves that function. That's
Fortran's way of garbage collection. If one does not want it, one has to
use pointers.)
In that sense, the lack of a qualifier in C, which matches Fortran, is
"really really not helping optimizers". ;-)
It's also not helping that my Fortran FU is weak
so I'm not able to produce testcases that will immediately show
issues with (proposed) middle-end representations.
Yes, that's indeed a problem, though I don't see how one can best solve
it. I can only offer to help with questions, finding the relevant
sections in the standard, and helping to interpret them.
For what it is worth, in the Fortran 2008 standard, one finds regarding
this issue (cf. PR 49733) more at:
* "12.5.2.13 Restrictions on entities associated with dummy arguments"
Namely, rules when a dummy argument may be changed behind the scenes,
including when the standard guarantees that the actual and the dummy
argument actually point to the same memory.
That also forbids that one passes twice the same variable as actual
argument, if one modifies either argument. (Unless one has a pointer -
or a TARGET (+ some additional restrictions).)
The additional restrictions are there to avoid issues, when
copy-in/copy-out happens. In some cases Fortran has to make a copy - and
pass the copy instead of the (address of the) actual argument, e.g. if
the dummy argument wants to have a contiguous array but the actual
argument has strides.
* "16.5.2.5 Events that cause the association status of pointers to
become undefined"
For instance, the issue mentioned above: One has a pointer to some
object which has locally a target attribute - or exists only locally -
then the pointer becomes undefined, if one returns from that function.
There are some more relevant spots in the standard, e.g. those where
pointer and target is defined. Or the place, where argument passing is
handled, cf. "12.5.2 Actual arguments, dummy arguments, and argument
association".
For instance an actual argument may only passed to a pointer dummy
argument, if it is a pointer - or if the dummy argument has the target
attribute and the dummy argument is INTENT(IN); the first avoids alias
issues and the second ensures that one does not modify the memory
address to which the argument points to. Cf. "12.5.2.7 Pointer dummy
variables" for the latter.
Tobias