]> git.ipfire.org Git - thirdparty/gcc.git/commit
fortran: Delay evaluation of array bounds after reallocation
authorMikael Morin <mikael@gcc.gnu.org>
Tue, 15 Jul 2025 07:58:35 +0000 (09:58 +0200)
committerMikael Morin <mikael@gcc.gnu.org>
Tue, 15 Jul 2025 07:58:35 +0000 (09:58 +0200)
commitac8e536526393580bc9a4339bab2f8603eff8a47
tree27dc6e9b557b4b0415265fa14a5e14c9c31ef565
parentade677dbb747dce1103a9f80070f7b0c329b865d
fortran: Delay evaluation of array bounds after reallocation

Delay the evaluation of bounds, offset, etc after the reallocation,
for the scalarization of allocatable arrays on the left hand side of
assignments.

Before this change, the code preceding the scalarization loop is like:

    D.4757 = ref2.offset;
    D.4759 = ref2.dim[0].ubound;
    D.4762 = ref2.dim[0].lbound;
    {
      if (ref2.data == 0B) goto realloc;
      if (ref2.dim[0].lbound + 4 != ref2.dim[0].ubound) goto realloc;
      goto L.10;
      realloc:
      ... change offset and bounds ...
      D.4757 = ref2.offset;
      D.4762 = NON_LVALUE_EXPR <ref2.dim[0].lbound>;
      ... reallocation ...
      L.10:;
    }
    while (1)
      {
... scalarized code ...

so the bounds etc are evaluated first to variables, and the reallocation
code takes care to update the variables during the reallocation.  This
is problematic because the variables' initialization references the
array bounds, which for unallocated arrays are uninitialized at the
evaluation point.  This used to (correctly) cause uninitialized warnings
(see PR fortran/108889), and a workaround for variables was found, that
initializes the bounds of arrays variables to some value beforehand if
they are unallocated.  For allocatable components, there is no warning
but the problem remains, some uninitialized values are used, even if
discarded later.

After this change the code becomes:

    {
      if (ref2.data == 0B) goto realloc;
      if (ref2.dim[0].lbound + 4 != ref2.dim[0].ubound) goto realloc;
      goto L.10;
      realloc:;
      ... change offset and bounds ...
      ... reallocation ...
      L.10:;
    }
    D.4762 = ref2.offset;
    D.4763 = ref2.dim[0].lbound;
    D.4764 = ref2.dim[0].ubound;
    while (1)
      {
... scalarized code

so the scalarizer avoids storing the values to variables at the time it
evaluates them, if the array is reallocatable on assignment.  Instead,
it keeps expressions with references to the array descriptor fields,
expressions that remain valid through reallocation.  After the
reallocation code has been generated, the expressions stored by the
scalarizer are evaluated in place to variables.

The decision to delay evaluation is based on the existing field
is_alloc_lhs, which requires a few tweaks to be alway correct wrt to
what its name suggests.  Namely it should be set even if the assignment
right hand side is an intrinsic function, and it should not be set if
the right hand side is a scalar and neither if the -fno-realloc-lhs flag
is passed to the compiler.

gcc/fortran/ChangeLog:

* trans-array.cc (gfc_conv_ss_descriptor): Don't evaluate
offset and data to a variable if is_alloc_lhs is set.  Move the
existing evaluation decision condition for data...
(save_descriptor_data): ... here as a new predicate.
(evaluate_bound): Add argument save_value.  Omit the evaluation
of the value to a variable if that argument isn't set.
(gfc_conv_expr_descriptor): Update caller.
(gfc_conv_section_startstride): Update caller.  Set save_value
if is_alloc_lhs is not set.  Omit the evaluation of stride to a
variable if save_value isn't set.
(gfc_set_delta): Omit the evaluation of delta to a variable
if is_alloc_lhs is set.
(gfc_is_reallocatable_lhs): Return false if flag_realloc_lhs
isn't set.
(gfc_alloc_allocatable_for_assignment): Don't update
the variables that may be stored in saved_offset, delta, and
data.  Call instead...
(update_reallocated_descriptor): ... this new procedure.
* trans-expr.cc (gfc_trans_assignment_1): Don't omit setting the
is_alloc_lhs flag if the right hand side is an intrinsic
function.  Clear the flag if the right hand side is scalar.
gcc/fortran/trans-array.cc
gcc/fortran/trans-expr.cc