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
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
* * *
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.]
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
[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 22.214.171.124 in particular. (An in-depth description of data association/defining/undefining is in Chapter 9)
*** Bug 49733 has been marked as a duplicate of this bug. ***
(In reply to Tobias Burnus from comment #0)
> A similar rule applies to other variables in Fortran
See also PR 60712 regarding restrict and local variables (as opposed to PARAM_DECL) for a simpler case (no function call).
I think we have a duplicate asking about restrict to have an effect on
(In reply to Richard Biener from comment #3)
> I think we have a duplicate asking about restrict to have an effect on
> function calls.
Could be PR tree-optimization/81008.
Any progress in this direction? Should we revisit PR 67202
(maybe do this in trans-*), or maybe even it?