https://gcc.gnu.org/g:392e0d0281e160b600877d1874a316bc4a9dcc80
commit 392e0d0281e160b600877d1874a316bc4a9dcc80 Author: Mikael Morin <mik...@gcc.gnu.org> Date: Fri Jul 11 15:46:06 2025 +0200 Sauvegarde 2 Diff: --- gcc/fortran/trans-array.cc | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc index 8d619022d9ef..9bdf60b7aeb5 100644 --- a/gcc/fortran/trans-array.cc +++ b/gcc/fortran/trans-array.cc @@ -3474,31 +3474,38 @@ replace_tree_in_expr (tree t, tree expr, tree replacement) them by evaluating the leading part of the data reference to a variable, adding extra code to BLOCK. - To avoid copying large amounts of data we only save pointers in the reference - chain, and as late in the chain as possible. */ + The candidate references for factoring are dereferenced pointers because they + are cheap to copy and array descriptors because they are often the base of + multiple subreferences. */ static void set_factored_descriptor_value (stmtblock_t *block, tree *desc_ptr, tree value) { - /* As the reference is processed from last to first, statements will be - generated in reversed order, so can't be put directly in BLOCK. We use - TMP_BLOCK instead. */ + /* As the reference is processed from outer to inner, variable definitions + will be generated in reversed order, so can't be put directly in BLOCK. + We use TMP_BLOCK instead. */ stmtblock_t tmp_block; tree accumulated_code = NULL_TREE; gfc_init_block (&tmp_block); - tree saveable_ref = nullptr; + tree saveable_ref = NULL_TREE; auto_vec<tree> replacement_roots; replacement_roots.safe_push (value); tree data_ref = value; - tree next_ref = nullptr; - bool seen_component = false; + tree next_ref = NULL_TREE; + + /* If the candidate reference is not followed by a subreference, it can't be + saved to a variable as it may be reallocatable, and we have to keep the + parent reference to be able to store the new pointer value in case of + reallocation. Otherwise it can be saved to a variable. */ + bool maybe_reallocatable = true; + while (true) { - if (seen_component + if (!maybe_reallocatable && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (data_ref))) saveable_ref = data_ref; @@ -3506,23 +3513,18 @@ set_factored_descriptor_value (stmtblock_t *block, tree *desc_ptr, tree value) { next_ref = TREE_OPERAND (data_ref, 0); - /* If there is no component reference after the pointer dereference in - the reference chain, the pointer can't be saved to a variable as - it may be a pointer or allocatable, and we have to keep the parent - reference to be able to update the pointer value. Otherwise the - pointer can be saved to a variable. */ - if (seen_component) + if (!maybe_reallocatable) { /* Don't evaluate the pointer to a variable yet; do it only if the variable would be significantly more simple than the reference it replaces. That is if the reference contains anything - different from a NOP, a COMPONENT or a DECL. */ + different from a NOP, a COMPONENT and a DECL. */ saveable_ref = next_ref; } } else if (TREE_CODE (data_ref) == COMPONENT_REF) { - seen_component = true; + maybe_reallocatable = false; next_ref = TREE_OPERAND (data_ref, 0); } else if (TREE_CODE (data_ref) == NOP_EXPR) @@ -3533,7 +3535,10 @@ set_factored_descriptor_value (stmtblock_t *block, tree *desc_ptr, tree value) break; if (TREE_CODE (data_ref) == ARRAY_REF) - next_ref = TREE_OPERAND (data_ref, 0); + { + maybe_reallocatable = false; + next_ref = TREE_OPERAND (data_ref, 0); + } if (saveable_ref != NULL_TREE) {