This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [patch, fortran] Load scalar intent-in variables at the beginning of procedures
Hi Richard,
On 11/21/19 1:16 PM, Richard Biener wrote:
OK, so I found it, it's handled via SSA_NAME_POINTS_TO_READONLY_MEMORY
which is initialized during the rewrite into SSA form from the
information given by the "fn spec" attribute […] so when the frontend
sets "fn spec" from the intent it should already work.
Which I can confirm for the following made-up example:
real function foo(n)
implicit none (type)
integer, intent(in) :: n
integer :: i
foo = 0.5
if (n /= 0) return
call bar()
do i = 1, n
foo = foo + sin(foo)
end do
end
The optimized dump shows the following, i.e. GCC nicely optimizes both the loop and the 'sin' call away:
foo (integer(kind=4) & restrict n)
{
integer(kind=4) _1;
<bb 2> [local count: 241635843]:
_1 = *n_9(D);
if (_1 != 0)
goto <bb 4>; [51.12%]
else
goto <bb 3>; [48.88%]
<bb 3> [local count: 118111600]:
bar ();
<bb 4> [local count: 241635844]:
return 5.0e-1;
}
I think this optimization permits some crucial optimizations.
I have not fully followed the later versions of the patch whether
they exploit some additional language semantics to permit optimizations
even without intent(in), but the initial discussion started with intent(in).
But the examples I saw above didn't use INTENT(IN) for the scalar
parameters.
I concur that a well-written program should make use of intent(in) where
sensible.
There are cases, which could be optimized likewise – but based on the
case that the pointer address cannot escape instead of just assuming
that the argument cannot change. – The question is how to convey this to
the middle end.
I wonder whether there is a 'fn attr' which can tell that the first
argument of 'print_i' does not cause the address of 'i' escape. If so,
one could mark all procedure arguments such – unless they have the
pointer, target or asynchronous attribute or are coarrays. [Probably
needs some fine tuning.]
In this example, variable values do change, but only in a controlled way
('print_i' could change it, 'bar' cannot). The semantic is also mainly a
property of the (local) variable (or dummy argument) declaration and not
of the functions which are called – although, if 'i' has no target
attribute, print_i's argument cannot have neither – hence, one could
generated a function interface
real function foo(i, y)
implicit none (type)
integer :: i
real :: y
foo = 0.0
call print_i(i)
i = 5
call bar() ! < this prevents optimizing the sin(y) away
if (i == 5) return
foo = sin(y)
end
Fortran semantics implies that 'i' can only change after the 'i = 5' if:
'i' has the TARGET (or POINTER) attribute. Or it is possible if 'i' has
the ASYNCHRONOUS or VOLATILE attribute – or it is a coarray (where a
remote image can modify the local value).
For asynchronous, it would be something like "call read_i(i); call
wait()" which is structurally the same as above.
TARGET: "An object without the TARGET attribute shall not have a pointer
associated with it."
VOLATILE: "may be referenced, defined, or become undefined, by
means20not specified by the program"
ASYNCHRONOUS: "An entity with the ASYNCHRONOUS attribute is a variable,
and may be subject to asynchronous input/output or asynchronous
communication."
Tobias