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;

Reply via email to