fortran: Use pointer arithmetic to index arrays [PR102043]
authorMikael Morin <mikael@gcc.gnu.org>
Fri, 22 Apr 2022 20:52:50 +0000 (22:52 +0200)
committerMikael Morin <mikael@gcc.gnu.org>
Fri, 22 Apr 2022 20:52:50 +0000 (22:52 +0200)
commit7964ab6c364c410c34efe7ca2eba797d36525349
tree14d6772bc609d489a89758648820419d0014da7d
parent761dda57482295f9c41fcf87e5defa2ac1959f03
fortran: Use pointer arithmetic to index arrays [PR102043]

The code generated for array references used to be ARRAY_REF trees as
could be expected.  However, the middle-end may conclude from those
trees that the indexes used are non-negative (more precisely not below
the lower bound), which is a wrong assumption in the case of "reversed-
order" arrays.

The problematic arrays are those with a descriptor and having a negative
stride for at least one dimension.  The descriptor data points to the
first element in array order (which is not the first in memory order in
that case), and the negative stride(s) makes walking the array backwards
(towards lower memory addresses), and we can access elements with
negative index wrt data pointer.

With this change, pointer arithmetic is generated by default for array
references, unless we are in a case where negative indexes can’t happen
(array descriptor’s dim element, substrings, explicit shape,
allocatable, or assumed shape contiguous).  A new flag is added to
choose between array indexing and pointer arithmetic, and it’s set
if the context can tell array indexing is safe (descriptor dim
element, substring, temporary array), or a new method is called
to decide on whether the flag should be set for one given array
expression.

PR fortran/102043

gcc/fortran/ChangeLog:

* trans.h (gfc_build_array_ref): Add non_negative_offset
argument.
* trans.cc (gfc_build_array_ref): Ditto. Use pointer arithmetic
if non_negative_offset is false.
* trans-expr.cc (gfc_conv_substring): Set flag in the call to
gfc_build_array_ref.
* trans-array.cc (gfc_get_cfi_dim_item,
gfc_conv_descriptor_dimension): Same.
(build_array_ref): Decide on whether to set the flag and update
the call.
(gfc_conv_scalarized_array_ref): Same.  New argument tmp_array.
(gfc_conv_tmp_array_ref): Update call to
gfc_conv_scalarized_ref.
(non_negative_strides_array_p): New function.

gcc/testsuite/ChangeLog:

* gfortran.dg/array_reference_3.f90: New.
* gfortran.dg/negative_stride_1.f90: New.
* gfortran.dg/vector_subscript_8.f90: New.
* gfortran.dg/vector_subscript_9.f90: New.
* gfortran.dg/c_loc_test_22.f90: Update dump patterns.
* gfortran.dg/finalize_10.f90: Same.

Co-Authored-By: Richard Biener <rguenther@suse.de>
gcc/fortran/trans-array.cc
gcc/fortran/trans-expr.cc
gcc/fortran/trans.cc
gcc/fortran/trans.h
gcc/testsuite/gfortran.dg/array_reference_3.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/c_loc_test_22.f90
gcc/testsuite/gfortran.dg/finalize_10.f90
gcc/testsuite/gfortran.dg/negative_stride_1.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/vector_subscript_8.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/vector_subscript_9.f90 [new file with mode: 0644]