RFH: Impose code-movement restrictions and value assumption (for ASYNCHRONOUS/Coarrays)

Tobias Burnus burnus@net-b.de
Thu Jul 14 10:40:00 GMT 2011


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



More information about the Gcc mailing list