https://gcc.gnu.org/g:6801bc9fd42d2c81be1483e56dfed84c9a797746

commit 6801bc9fd42d2c81be1483e56dfed84c9a797746
Author: Mikael Morin <mik...@gcc.gnu.org>
Date:   Mon Feb 17 18:49:30 2025 +0100

    Correction régression forall_13

Diff:
---
 gcc/fortran/trans-array.cc     | 86 ++++++++++++++++++++++++++----------------
 gcc/fortran/trans-array.h      |  3 +-
 gcc/fortran/trans-expr.cc      |  5 ++-
 gcc/fortran/trans-intrinsic.cc |  6 ++-
 gcc/fortran/trans-stmt.cc      |  2 +-
 gcc/fortran/trans.h            |  1 +
 6 files changed, 64 insertions(+), 39 deletions(-)

diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc
index a5c14886511c..8e1fef6b301f 100644
--- a/gcc/fortran/trans-array.cc
+++ b/gcc/fortran/trans-array.cc
@@ -1910,17 +1910,20 @@ set_bounds_update_offset (stmtblock_t *block, tree 
desc, int dim,
     return;
 
   /* Update offset.  */
-  tree tmp = fold_build2_loc (input_location, MULT_EXPR,
-                             gfc_array_index_type, lbound_diff, stride);
-  tmp = fold_build2_loc (input_location, MINUS_EXPR,
-                        gfc_array_index_type, *offset, tmp);
-  *offset = gfc_evaluate_now (tmp, block);
+  if (!integer_zerop (lbound_diff))
+    {
+      tree tmp = fold_build2_loc (input_location, MULT_EXPR,
+                                 gfc_array_index_type, lbound_diff, stride);
+      tmp = fold_build2_loc (input_location, MINUS_EXPR,
+                            gfc_array_index_type, *offset, tmp);
+      *offset = gfc_evaluate_now (tmp, block);
+    }
 
   if (!next_stride)
     return;
 
   /* Set stride for next dimension.  */
-  tmp = gfc_conv_array_extent_dim (lbound, ubound, NULL);
+  tree tmp = gfc_conv_array_extent_dim (lbound, ubound, NULL);
   *next_stride = fold_build2_loc (input_location, MULT_EXPR,
                                  gfc_array_index_type, stride, tmp);
 }
@@ -3666,9 +3669,11 @@ get_class_info_from_ss (stmtblock_t * pre, gfc_ss *ss, 
tree *eltype,
 static void
 set_temporary_descriptor (stmtblock_t *block, tree desc, tree class_src,
                          tree elemsize, tree data_ptr,
+                         tree lbound[GFC_MAX_DIMENSIONS],
                          tree ubound[GFC_MAX_DIMENSIONS],
                          tree stride[GFC_MAX_DIMENSIONS], int rank,
-                         bool callee_allocated, bool rank_changer)
+                         bool callee_allocated, bool rank_changer,
+                         bool shift_bounds)
 {
   int n;
 
@@ -3694,13 +3699,15 @@ set_temporary_descriptor (stmtblock_t *block, tree 
desc, tree class_src,
       gfc_conv_descriptor_rank_set (block, desc, rank);
     }
 
+  tree offset = gfc_index_zero_node;
   if (!callee_allocated)
     {
       for (n = 0; n < rank; n++)
        {
          /* Store the stride and bound components in the descriptor.  */
-         set_descriptor_dimension (block, desc, n, gfc_index_zero_node, 
ubound[n],
-                                   stride[n], nullptr, nullptr);
+         tree this_lbound = shift_bounds ? gfc_index_zero_node : lbound[n];
+         set_descriptor_dimension (block, desc, n, this_lbound, ubound[n],
+                                   stride[n], &offset, nullptr);
        }
     }
 
@@ -3710,7 +3717,7 @@ set_temporary_descriptor (stmtblock_t *block, tree desc, 
tree class_src,
 
   /* The offset is zero because we create temporaries with a zero
      lower bound.  */
-  gfc_conv_descriptor_offset_set (block, desc, gfc_index_zero_node);
+  gfc_conv_descriptor_offset_set (block, desc, offset);
 }
 
 
@@ -3735,7 +3742,8 @@ set_temporary_descriptor (stmtblock_t *block, tree desc, 
tree class_src,
 tree
 gfc_trans_create_temp_array (stmtblock_t * pre, stmtblock_t * post, gfc_ss * 
ss,
                             tree eltype, tree initial, bool dynamic,
-                            bool dealloc, bool callee_alloc, locus * where)
+                            bool dealloc, bool callee_alloc, locus * where,
+                            bool shift_bounds)
 {
   gfc_loopinfo *loop;
   gfc_ss *s;
@@ -3822,19 +3830,22 @@ gfc_trans_create_temp_array (stmtblock_t * pre, 
stmtblock_t * post, gfc_ss * ss,
        {
          dim = s->dim[n];
 
-         /* Callee allocated arrays may not have a known bound yet.  */
-         if (loop->to[n])
-           loop->to[n] = gfc_evaluate_now (
-                       fold_build2_loc (input_location, MINUS_EXPR,
-                                        gfc_array_index_type,
-                                        loop->to[n], loop->from[n]),
-                       pre);
-         loop->from[n] = gfc_index_zero_node;
-
-         /* We have just changed the loop bounds, we must clear the
-            corresponding specloop, so that delta calculation is not skipped
-            later in gfc_set_delta.  */
-         loop->specloop[n] = NULL;
+         if (shift_bounds)
+           {
+             /* Callee allocated arrays may not have a known bound yet.  */
+             if (loop->to[n])
+               loop->to[n] = gfc_evaluate_now (
+                           fold_build2_loc (input_location, MINUS_EXPR,
+                                            gfc_array_index_type,
+                                            loop->to[n], loop->from[n]),
+                           pre);
+             loop->from[n] = gfc_index_zero_node;
+
+             /* We have just changed the loop bounds, we must clear the
+                corresponding specloop, so that delta calculation is not 
skipped
+                later in gfc_set_delta.  */
+             loop->specloop[n] = NULL;
+           }
 
          /* We are constructing the temporary's descriptor based on the loop
             dimensions.  As the dimensions may be accessed in arbitrary order
@@ -3995,13 +4006,18 @@ gfc_trans_create_temp_array (stmtblock_t * pre, 
stmtblock_t * post, gfc_ss * ss,
        {
          stride[n] = size;
 
-         tmp = fold_build2_loc (input_location, PLUS_EXPR,
-                                gfc_array_index_type,
-                                to[n], gfc_index_one_node);
+         tree extent = to[n];
+         if (!shift_bounds && !integer_zerop (from[n]))
+           extent = fold_build2_loc (input_location, MINUS_EXPR,
+                                     gfc_array_index_type, to[n], from[n]);
+     
+         extent = fold_build2_loc (input_location, PLUS_EXPR,
+                                   gfc_array_index_type,
+                                   extent, gfc_index_one_node);
 
          /* Check whether the size for this dimension is negative.  */
          cond = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
-                                 tmp, gfc_index_zero_node);
+                                 extent, gfc_index_zero_node);
          cond = gfc_evaluate_now (cond, pre);
 
          if (n == 0)
@@ -4011,7 +4027,7 @@ gfc_trans_create_temp_array (stmtblock_t * pre, 
stmtblock_t * post, gfc_ss * ss,
                                       logical_type_node, or_expr, cond);
 
          size = fold_build2_loc (input_location, MULT_EXPR,
-                                 gfc_array_index_type, size, tmp);
+                                 gfc_array_index_type, size, extent);
          size = gfc_evaluate_now (size, pre);
        }
     }
@@ -4039,9 +4055,9 @@ gfc_trans_create_temp_array (stmtblock_t * pre, 
stmtblock_t * post, gfc_ss * ss,
                                                    dealloc);
 
   set_temporary_descriptor (pre, desc, class_expr, elemsize, data_ptr,
-                           to, stride, total_dim,
+                           from, to, stride, total_dim,
                            size == NULL_TREE || callee_alloc,
-                           rank_changer);
+                           rank_changer, shift_bounds);
 
   while (ss->parent)
     ss = ss->parent;
@@ -5319,7 +5335,8 @@ trans_array_constructor (gfc_ss * ss, locus * where)
     }
 
   gfc_trans_create_temp_array (&outer_loop->pre, &outer_loop->post, ss, type,
-                              NULL_TREE, dynamic, true, false, where);
+                              NULL_TREE, dynamic, true, false, where,
+                              true);
 
   desc = ss_info->data.array.descriptor;
   offset = gfc_index_zero_node;
@@ -8215,6 +8232,8 @@ gfc_conv_loop_setup (gfc_loopinfo * loop, locus * where)
       gcc_assert (tmp_ss_info->type == GFC_SS_TEMP);
       gcc_assert (loop->parent == NULL);
 
+      bool preserve_bounds = tmp_ss_info->data.temp.preserve_bounds;
+
       /* Make absolutely sure that this is a complete type.  */
       if (tmp_ss_info->string_length)
        tmp_ss_info->data.temp.type
@@ -8229,7 +8248,8 @@ gfc_conv_loop_setup (gfc_loopinfo * loop, locus * where)
       gcc_assert (tmp_ss->dimen != 0);
 
       gfc_trans_create_temp_array (&loop->pre, &loop->post, tmp_ss, tmp,
-                                  NULL_TREE, false, true, false, where);
+                                  NULL_TREE, false, true, false, where,
+                                  !preserve_bounds);
     }
 
   /* For array parameters we don't have loop variables, so don't calculate the
diff --git a/gcc/fortran/trans-array.h b/gcc/fortran/trans-array.h
index 357bd64fb766..e0aa60b2e9b2 100644
--- a/gcc/fortran/trans-array.h
+++ b/gcc/fortran/trans-array.h
@@ -30,7 +30,8 @@ void gfc_set_loop_bounds_from_array_spec 
(gfc_interface_mapping *,
 
 /* Generate code to create a temporary array.  */
 tree gfc_trans_create_temp_array (stmtblock_t *, stmtblock_t *, gfc_ss *,
-                                 tree, tree, bool, bool, bool, locus *);
+                                 tree, tree, bool, bool, bool, locus *,
+                                 bool shift_bounds);
 
 /* Generate function entry code for allocation of compiler allocated array
    variables.  */
diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index 153b6f4d2800..0c7547d7a5b6 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -5450,6 +5450,7 @@ gfc_conv_subref_array_arg (gfc_se *se, gfc_expr * expr, 
int g77,
                                              ? expr->ts.u.cl->backend_decl
                                              : NULL),
                                  loop.dimen);
+  loop.temp_ss->info->data.temp.preserve_bounds = 1;
 
   parmse->string_length = loop.temp_ss->info->string_length;
 
@@ -8390,7 +8391,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
          gfc_trans_create_temp_array (&se->pre, &se->post, se->ss,
                                       tmp, NULL_TREE, false,
                                       !comp->attr.pointer, callee_alloc,
-                                      &se->ss->info->expr->where);
+                                      &se->ss->info->expr->where, true);
 
          /* Pass the temporary as the first argument.  */
          result = info->descriptor;
@@ -8426,7 +8427,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
          gfc_trans_create_temp_array (&se->pre, &se->post, se->ss,
                                       tmp, NULL_TREE, false,
                                       !sym->attr.pointer, callee_alloc,
-                                      &se->ss->info->expr->where);
+                                      &se->ss->info->expr->where, true);
 
          /* Pass the temporary as the first argument.  */
          result = info->descriptor;
diff --git a/gcc/fortran/trans-intrinsic.cc b/gcc/fortran/trans-intrinsic.cc
index 5bd023192cb1..b2fc6d4869a3 100644
--- a/gcc/fortran/trans-intrinsic.cc
+++ b/gcc/fortran/trans-intrinsic.cc
@@ -1283,7 +1283,8 @@ gfc_conv_intrinsic_caf_get (gfc_se *se, gfc_expr *expr, 
tree lhs,
       /* Create temporary.  */
       may_realloc = gfc_trans_create_temp_array (&se->pre, &se->post, se->ss,
                                                 type, NULL_TREE, false, false,
-                                                false, &array_expr->where)
+                                                false, &array_expr->where,
+                                                true)
                    == NULL_TREE;
       res_var = se->ss->info->data.array.descriptor;
       if (array_expr->ts.type == BT_CHARACTER)
@@ -8760,7 +8761,8 @@ gfc_conv_intrinsic_transfer (gfc_se * se, gfc_expr * expr)
   /* Build a destination descriptor, using the pointer, source, as the
      data field.  */
   gfc_trans_create_temp_array (&se->pre, &se->post, se->ss, mold_type,
-                              NULL_TREE, false, true, false, &expr->where);
+                              NULL_TREE, false, true, false, &expr->where,
+                              true);
 
   /* Cast the pointer to the result.  */
   tmp = gfc_conv_descriptor_data_get (info->descriptor);
diff --git a/gcc/fortran/trans-stmt.cc b/gcc/fortran/trans-stmt.cc
index 2a6cd00be5cc..9ef699ee29dd 100644
--- a/gcc/fortran/trans-stmt.cc
+++ b/gcc/fortran/trans-stmt.cc
@@ -325,7 +325,7 @@ gfc_conv_elemental_dependencies (gfc_se * se, gfc_se * 
loopse,
          gfc_init_block (&temp_post);
          tmp = gfc_trans_create_temp_array (&se->pre, &temp_post, tmp_ss,
                                             temptype, initial, false, true,
-                                            false, &arg->expr->where);
+                                            false, &arg->expr->where, true);
          gfc_add_modify (&se->pre, size, tmp);
          tmp = fold_convert (pvoid_type_node, tmp_ss->info->data.array.data);
          gfc_add_modify (&se->pre, data, tmp);
diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h
index 28f81578e591..17a882d16dd2 100644
--- a/gcc/fortran/trans.h
+++ b/gcc/fortran/trans.h
@@ -286,6 +286,7 @@ typedef struct gfc_ss_info
     struct
     {
       tree type;
+      unsigned preserve_bounds:1;
     }
     temp;

Reply via email to