On Thu, Nov 21, 2019 at 2:16 PM Tobias Burnus <tob...@codesourcery.com> wrote:
>
> 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).

So I think what you'd need to do is make 'i' marked as TYPE_RESTRICT
then.  I think we don't yet handle it but it means that bar() may not
modify 'i' but via 'i' (but it doesn't get 'i' as a parameter).

> 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."

I think for GIMPLE everything not obviously on the stack is ASYNCHRONOUS.

Richard.

> Tobias
>

Reply via email to