https://gcc.gnu.org/g:39701cd22bf18c4172edb14e6ae502705b4da46c

commit 39701cd22bf18c4172edb14e6ae502705b4da46c
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 |  8 ++--
 gcc/fortran/trans-stmt.cc      |  2 +-
 gcc/fortran/trans.h            |  1 +
 6 files changed, 65 insertions(+), 40 deletions(-)

diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc
index 9fe54c76e0d8..600f28b37962 100644
--- a/gcc/fortran/trans-array.cc
+++ b/gcc/fortran/trans-array.cc
@@ -1908,17 +1908,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);
 }
@@ -3652,9 +3655,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;
 
@@ -3680,13 +3685,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);
        }
     }
 
@@ -3696,7 +3703,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);
 }
 
 
@@ -3721,7 +3728,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;
@@ -3808,19 +3816,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
@@ -3981,13 +3992,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)
@@ -3997,7 +4013,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);
        }
     }
@@ -4025,9 +4041,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;
@@ -5308,7 +5324,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;
@@ -8195,6 +8212,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
@@ -8209,7 +8228,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 1a42a78f66a1..5cb073a56b2e 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -5445,6 +5445,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;
 
@@ -8386,7 +8387,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;
@@ -8422,7 +8423,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 40aea99924be..15528d407d9d 100644
--- a/gcc/fortran/trans-intrinsic.cc
+++ b/gcc/fortran/trans-intrinsic.cc
@@ -1858,7 +1858,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)
@@ -2094,7 +2095,7 @@ conv_caf_send (gfc_code *code) {
          gfc_trans_create_temp_array (&lhs_se.pre, &lhs_se.post,
                                       lss_for_tmparray, lhs_type, NULL_TREE,
                                       false, true, false,
-                                      &lhs_expr->where);
+                                      &lhs_expr->where, true);
          tmparr_desc = lss_for_tmparray->info->data.array.descriptor;
          gfc_start_scalarized_body (&loop, &body);
          gfc_init_se (&se, NULL);
@@ -9338,7 +9339,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 71e911f8c9ee..53237a34f0ba 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 9f58036eb09b..955ac9aa113e 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