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); }