https://gcc.gnu.org/g:01ef2728d8d9051ae9ee7dca947b6d904a23fcde
commit 01ef2728d8d9051ae9ee7dca947b6d904a23fcde Author: Mikael Morin <mik...@gcc.gnu.org> Date: Fri Jul 11 11:54:17 2025 +0200 Sauvegarde 1 Diff: --- gcc/fortran/trans-array.cc | 81 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 65 insertions(+), 16 deletions(-) diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc index f3bef32e4017..8d619022d9ef 100644 --- a/gcc/fortran/trans-array.cc +++ b/gcc/fortran/trans-array.cc @@ -3437,6 +3437,38 @@ save_descriptor_data (tree descr, tree data) } +typedef struct +{ + tree expr, repl; +} +replacement_t; + + +static tree +replace_expr (tree *tp, int *walk_subtree, void *data) +{ + replacement_t *repl = (replacement_t *) data; + if (*tp == repl->expr) + { + *tp = repl->repl; + *walk_subtree = 0; + } + + return NULL_TREE; +} + + +static void +replace_tree_in_expr (tree t, tree expr, tree replacement) +{ + replacement_t repl; + repl.expr = t; + repl.repl = replacement; + + walk_tree (&expr, replace_expr, &repl, nullptr); +} + + /* Save the descriptor reference VALUE to storage pointed by DESC_PTR. As there may be a lot of code using subreferences of the descriptor, try to factor them by evaluating the leading part of the data reference to a variable, @@ -3445,25 +3477,35 @@ save_descriptor_data (tree descr, tree data) To avoid copying large amounts of data we only save pointers in the reference chain, and as late in the chain as possible. */ -void +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 - generate in reversed order, so can't be put directly in BLOCK. We use + 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 *ptr_ref = nullptr; + tree saveable_ref = nullptr; + + auto_vec<tree> replacement_roots; + replacement_roots.safe_push (value); tree data_ref = value; + tree next_ref = nullptr; bool seen_component = false; while (true) { + if (seen_component + && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (data_ref))) + saveable_ref = data_ref; + if (TREE_CODE (data_ref) == INDIRECT_REF) { + 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 @@ -3475,38 +3517,45 @@ set_factored_descriptor_value (stmtblock_t *block, tree *desc_ptr, tree value) 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. */ - ptr_ref = &TREE_OPERAND (data_ref, 0); + saveable_ref = next_ref; } - - data_ref = TREE_OPERAND (data_ref, 0); } else if (TREE_CODE (data_ref) == COMPONENT_REF) { seen_component = true; - data_ref = TREE_OPERAND (data_ref, 0); + next_ref = TREE_OPERAND (data_ref, 0); } else if (TREE_CODE (data_ref) == NOP_EXPR) - data_ref = TREE_OPERAND (data_ref, 0); + next_ref = TREE_OPERAND (data_ref, 0); else { if (DECL_P (data_ref)) break; - if (ptr_ref != nullptr) + if (TREE_CODE (data_ref) == ARRAY_REF) + next_ref = TREE_OPERAND (data_ref, 0); + + if (saveable_ref != NULL_TREE) { - /* We have seen a pointer before, and its reference appears to be - worth saving. Do it now. */ - tree ptr = *ptr_ref; - *ptr_ref = gfc_evaluate_now (ptr, &tmp_block); + /* We have seen a reference worth saving. Do it now. */ + tree var = gfc_evaluate_now (saveable_ref, &tmp_block); gfc_add_expr_to_block (&tmp_block, accumulated_code); accumulated_code = gfc_finish_block (&tmp_block); + + unsigned i; + tree repl_root; + FOR_EACH_VEC_ELT (replacement_roots, i, repl_root) + replace_tree_in_expr (saveable_ref, repl_root, var); + + replacement_roots.safe_push (saveable_ref); + saveable_ref = NULL_TREE; } - if (TREE_CODE (data_ref) == ARRAY_REF) - data_ref = TREE_OPERAND (data_ref, 0); - else + if (TREE_CODE (data_ref) != ARRAY_REF) break; } + + data_ref = next_ref; } *desc_ptr = value;