https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92628

            Bug ID: 92628
           Summary: Make use of TYPE_RESTRICT for function-call
                    pointer-escape analysis – especially for Fortran
           Product: gcc
           Version: 10.0
            Status: UNCONFIRMED
          Keywords: missed-optimization
          Severity: normal
          Priority: P3
         Component: middle-end
          Assignee: unassigned at gcc dot gnu.org
          Reporter: burnus at gcc dot gnu.org
  Target Milestone: ---

As discussed, TYPE_RESTRICT should also be used for of pointer-escape analysis.

In Fortran, assume the following program. When honoring the Fortran semantics –
passed to the ME via the TYPE_RESTRICT for 'n' – the loop can be optimized
away:

  subroutine test(n)  ! n is passed by reference
    integer :: n, i
    n = 0
    call do_something() ! ME assumes that callee might modify 'n'
    ! the following loop could be optimized way as still  n == 0
    do i = 1, n
      call bar()
    end do
  end subroutine

A full test case and a *patch* to actually *set* TYPE_RESTRICT in the Fortran
FE can be found at https://gcc.gnu.org/ml/fortran/2019-11/msg00127.html

Some more discussion and references to the Fortran standard can be found at
https://gcc.gnu.org/ml/fortran/2019-11/msg00126.html

 * * *

A similar rule applies to other variables in Fortran (in principle also to
static variables). Example - the same but not using a PARM_DECL:
[Will surely require changes to the FE and not only to the ME.]

subroutine foo()
    integer :: n, i ! Both local variables
    call my_print(n)  ! n passed by reference, regarded as pointer escape
    n = 0
    call bar() ! ME assumes that the callee might modify 'n'
    ! the following loop could be optimized way as  n == 0
    do i = 1, n
      call bar()
    end d
end

[The Fortran programs become nicer by providing an 'interface', i.e. an
explicit function declaration (cf. test case in the link above). But in terms
of the pointer-escape analysis, this has no effect.]

 * * *

Fortran standard wise

Within the language, a pointer escape is only possible by associating a pointer
to a variable – which is only permitted for variables with POINTER or TARGET
attribute.
This can be locally removed (e.g. passing a TARGET variable as argument to a
function whose dummy argument declaration does not have it. Then, within that
function one can assume no aliasing is done [restriction on the programmer].)

Additionally, ASYNCHRONOUS ("call start_do(var); … ; call wait()") (implies
default ME behavior, i.e. pointer address escapes) and VOLATILE have an effect.
– As well as concurrency (coarrays, asynchronous I/O, thread parallelization,
e.g. via OpenMP or OpenACC).

For a non-pointer, non-target variable, there remains one way to get two
identifiers pointing to the same memory: Passing it as argument to a function
(multiple times – or once and accessing it directly from the other scope).
In order to avoid problems here, Fortran requires (from the programmer) that
those variables are either only accessed for reading – or that only one
identifier is used for modification and all others are not not used for read
access (neither before nor after the modification).

See https://gcc.gnu.org/ml/fortran/2019-11/msg00126.html for some language
quotes.

Otherwise, see Fortran 2018, https://j3-fortran.org/doc/year/18/18-007r1.pdf
for the definitions of TARGET, POINTER, ASYNCHRONOUS and VOLATILE.
For argument association, see Section 15.5.2 in general and 15.5.2.13 in
particular. (An in-depth description of data association/defining/undefining is
in Chapter 9)

Reply via email to