https://gcc.gnu.org/g:1a2e61f1eecca94abb410a3a951ca48ee0090b52

commit 1a2e61f1eecca94abb410a3a951ca48ee0090b52
Author: Mikael Morin <mik...@gcc.gnu.org>
Date:   Thu May 8 10:51:26 2025 +0200

    Correction régression parloops-exit-first-loop-alt.f95

Diff:
---
 gcc/fortran/trans-array.cc | 52 ++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 48 insertions(+), 4 deletions(-)

diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc
index 27c9adcdcd8c..5827362cbd5a 100644
--- a/gcc/fortran/trans-array.cc
+++ b/gcc/fortran/trans-array.cc
@@ -3561,9 +3561,12 @@ conv_array_index (gfc_se * se, gfc_ss * ss, int dim, int 
i, gfc_array_ref * ar)
 
 
 static tree
-build_ptr_array_ref (tree data, tree offset)
+build_array_ref (tree array, tree offset, bool use_array_ref)
 {
-  tree ptr = data;
+  if (use_array_ref)
+    return gfc_build_array_ref (array, offset, true);
+ 
+  tree ptr = gfc_conv_array_data (array);
   gcc_assert (TREE_CODE (TREE_TYPE (ptr)) == POINTER_TYPE);
   if (TREE_CODE (TREE_TYPE (TREE_TYPE (ptr))) == ARRAY_TYPE)
     {
@@ -3649,6 +3652,36 @@ add_to_offset (tree *cst_offset, tree *offset, tree t)
 }
 
 
+bool
+array_ref_safe_p (tree array, tree *elt_size)
+{
+  if (!non_negative_strides_array_p (array))
+    return false;
+
+  STRIP_NOPS (array);
+  if (TREE_CODE (array) == COMPONENT_REF)
+    {
+      tree parent = TREE_OPERAND (array, 0);
+      if (GFC_CLASS_TYPE_P (TREE_TYPE (parent)))
+       return false;
+
+      STRIP_NOPS (parent);
+      if (GFC_CLASS_TYPE_P (TREE_TYPE (parent)))
+       return false;
+    }
+
+  tree elt_type = gfc_get_element_type (TREE_TYPE (array));
+  if (TYPE_SIZE_UNIT (elt_type) == NULL_TREE
+      || !INTEGER_CST_P (TYPE_SIZE_UNIT (elt_type)))
+    return false;
+
+  if (elt_size)
+    *elt_size = TYPE_SIZE_UNIT (elt_type);
+
+  return true;
+}
+
+
 /* Build an array reference.  se->expr already holds the array descriptor.
    This should be either a variable, indirect variable reference or component
    reference.  For arrays which do not have a descriptor, se->expr will be
@@ -3717,8 +3750,16 @@ gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, 
gfc_expr *expr,
       && ar->as->type != AS_DEFERRED)
     decl = sym->backend_decl;
 
+  tree elt_size;
+  bool use_array_ref = array_ref_safe_p (decl, &elt_size);
+
+  tree off = gfc_conv_array_offset (decl);
+  if (use_array_ref)
+    off = fold_build2_loc (input_location, EXACT_DIV_EXPR,
+                          gfc_array_index_type, off, elt_size);
+
   cst_offset = offset = gfc_index_zero_node;
-  add_to_offset (&cst_offset, &offset, gfc_conv_array_offset (decl));
+  add_to_offset (&cst_offset, &offset, off);
 
   /* Calculate the offsets from all the dimensions.  Make sure to associate
      the final offset so that we form a chain of loop invariant summands.  */
@@ -3787,6 +3828,9 @@ gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, 
gfc_expr *expr,
 
       /* Multiply the index by the stride.  */
       tree spacing = gfc_conv_array_spacing (decl, n);
+      if (use_array_ref)
+       spacing = fold_build2_loc (input_location, EXACT_DIV_EXPR,
+                                  gfc_array_index_type, spacing, elt_size);
       tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
                             indexse.expr, spacing);
  
@@ -3800,7 +3844,7 @@ gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, 
gfc_expr *expr,
     offset = fold_build2_loc (input_location, PLUS_EXPR,
                              gfc_array_index_type, offset, cst_offset);
 
-  se->expr = build_ptr_array_ref (gfc_conv_array_data (decl), offset);
+  se->expr = build_array_ref (decl, offset, use_array_ref);
 }

Reply via email to