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)