https://gcc.gnu.org/g:ffa7329b66ad48d388715248bf7d1ca2620cb767
commit ffa7329b66ad48d388715248bf7d1ca2620cb767 Author: Mikael Morin <mik...@gcc.gnu.org> Date: Sat Feb 8 21:37:49 2025 +0100 Factorisation initialisation dimension descripteur Correction régression realloc_on_assign_12.f90 Diff: --- gcc/fortran/trans-array.cc | 87 +++++++++++++++++++++++++--------------------- 1 file changed, 48 insertions(+), 39 deletions(-) diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc index 03f290736078..fa68d03b1f88 100644 --- a/gcc/fortran/trans-array.cc +++ b/gcc/fortran/trans-array.cc @@ -1474,38 +1474,56 @@ gfc_build_null_descriptor (tree type) } -static tree -set_descriptor_dimension (stmtblock_t *block, tree desc, int dim, - tree lbound, tree ubound, tree stride, tree *offset) +static void +set_bounds_update_offset (stmtblock_t *block, tree desc, int dim, + tree lbound, tree ubound, tree stride, tree lbound_diff, + tree *offset, tree *next_stride, bool stride_unchanged) { - /* Set bounds in descriptor. */ + /* Stabilize values in case the expressions depend on the existing bounds. */ lbound = fold_convert (gfc_array_index_type, lbound); lbound = gfc_evaluate_now (lbound, block); - gfc_conv_descriptor_lbound_set (block, desc, - gfc_rank_cst[dim], lbound); ubound = fold_convert (gfc_array_index_type, ubound); ubound = gfc_evaluate_now (ubound, block); - gfc_conv_descriptor_ubound_set (block, desc, - gfc_rank_cst[dim], ubound); - /* Set stride. */ stride = fold_convert (gfc_array_index_type, stride); stride = gfc_evaluate_now (stride, block); - gfc_conv_descriptor_stride_set (block, desc, - gfc_rank_cst[dim], stride); + + lbound_diff = fold_convert (gfc_array_index_type, lbound_diff); + lbound_diff = gfc_evaluate_now (lbound_diff, block); + + gfc_conv_descriptor_lbound_set (block, desc, + gfc_rank_cst[dim], lbound); + gfc_conv_descriptor_ubound_set (block, desc, + gfc_rank_cst[dim], ubound); + if (!stride_unchanged) + gfc_conv_descriptor_stride_set (block, desc, + gfc_rank_cst[dim], stride); /* Update offset. */ tree tmp = fold_build2_loc (input_location, MULT_EXPR, - gfc_array_index_type, lbound, stride); - *offset = fold_build2_loc (input_location, MINUS_EXPR, - gfc_array_index_type, *offset, tmp); + 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; - /* Return stride for next dimension. */ + /* Set stride for next dimension. */ tmp = gfc_conv_array_extent_dim (lbound, ubound, NULL); - stride = fold_build2_loc (input_location, MULT_EXPR, - gfc_array_index_type, stride, tmp); - return stride; + *next_stride = fold_build2_loc (input_location, MULT_EXPR, + gfc_array_index_type, stride, tmp); +} + + +static void +set_descriptor_dimension (stmtblock_t *block, tree desc, int dim, + tree lbound, tree ubound, tree stride, tree *offset, + tree *next_stride) +{ + set_bounds_update_offset (block, desc, dim, lbound, ubound, stride, lbound, + offset, next_stride, false); } @@ -1514,7 +1532,7 @@ set_descriptor_dimension (stmtblock_t *block, tree desc, int dim, static void conv_shift_descriptor_lbound (stmtblock_t* block, tree from_desc, tree to_desc, int dim, - tree new_lbound, tree offset, bool zero_based) + tree new_lbound, tree *offset, bool zero_based) { new_lbound = fold_convert (gfc_array_index_type, new_lbound); new_lbound = gfc_evaluate_now (new_lbound, block); @@ -1538,18 +1556,9 @@ conv_shift_descriptor_lbound (stmtblock_t* block, tree from_desc, tree to_desc, updating the lbound, as they depend on the lbound expression! */ tree tmp1 = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type, ubound, diff); - gfc_conv_descriptor_ubound_set (block, to_desc, gfc_rank_cst[dim], tmp1); - /* Set lbound to the value we want. */ - gfc_conv_descriptor_lbound_set (block, to_desc, gfc_rank_cst[dim], new_lbound); - tree offs_diff = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type, - diff, stride); - tree tmp2 = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type, - offset, offs_diff); - gfc_add_modify (block, offset, tmp2); - - if (from_desc != to_desc) - gfc_conv_descriptor_stride_set (block, to_desc, gfc_rank_cst[dim], stride); + set_bounds_update_offset (block, to_desc, dim, new_lbound, tmp1, stride, diff, + offset, nullptr, from_desc == to_desc); } @@ -1627,23 +1636,23 @@ conv_shift_descriptor (stmtblock_t *block, tree src, tree dest, int rank, gfc_conv_descriptor_data_set (block, dest, tmp); } - tree offset_var = gfc_create_var (gfc_array_index_type, "offset"); + tree offset = gfc_create_var (gfc_array_index_type, "offset"); tree init_offset; if (info.zero_based_src ()) init_offset = gfc_index_zero_node; else init_offset = gfc_conv_descriptor_offset_get (src); - gfc_add_modify (block, offset_var, init_offset); + gfc_add_modify (block, offset, init_offset); /* Apply a shift of the lbound when supplied. */ for (int dim = 0; dim < rank; ++dim) { tree lower_bound = info.lower_bound (block, dim); - conv_shift_descriptor_lbound (block, src, dest, dim, lower_bound, offset_var, + conv_shift_descriptor_lbound (block, src, dest, dim, lower_bound, &offset, info.zero_based_src ()); } - gfc_conv_descriptor_offset_set (block, dest, offset_var); + gfc_conv_descriptor_offset_set (block, dest, offset); } @@ -1881,8 +1890,8 @@ gfc_conv_remap_descriptor (stmtblock_t *block, tree dest, tree src, } /* Set the bounds as declared for the LHS and calculate strides as well as another offset update accordingly. */ - tree stride = gfc_conv_descriptor_stride_get (src, - gfc_rank_cst[0]); + tree stride = gfc_conv_descriptor_stride_get (src, gfc_rank_cst[0]); + int last_dim = dest_rank - 1; for (int dim = 0; dim < dest_rank; ++dim) { gfc_se lower_se; @@ -1899,9 +1908,9 @@ gfc_conv_remap_descriptor (stmtblock_t *block, tree dest, tree src, gfc_add_block_to_block (block, &lower_se.pre); gfc_add_block_to_block (block, &upper_se.pre); - stride = set_descriptor_dimension (block, dest, dim, - lower_se.expr, upper_se.expr, stride, - &offset); + set_descriptor_dimension (block, dest, dim, lower_se.expr, upper_se.expr, + stride, &offset, + dim < last_dim ? &stride : nullptr); } gfc_conv_descriptor_offset_set (block, dest, offset); }