https://gcc.gnu.org/g:3ef8eb042e3dba9788c4d8ae928859cdb8e596c7

commit 3ef8eb042e3dba9788c4d8ae928859cdb8e596c7
Author: Mikael Morin <mik...@gcc.gnu.org>
Date:   Mon Mar 17 16:56:34 2025 +0100

    Extraction fonction gfc_set_descriptor_for_assign_realloc

Diff:
---
 gcc/cgraphunit.cc               |   1 +
 gcc/fortran/trans-array.cc      | 220 +--------------------------------------
 gcc/fortran/trans-descriptor.cc | 222 ++++++++++++++++++++++++++++++++++++++++
 gcc/fortran/trans-descriptor.h  |   4 +
 4 files changed, 230 insertions(+), 217 deletions(-)

diff --git a/gcc/cgraphunit.cc b/gcc/cgraphunit.cc
index bac17ed378b0..5881ebdcfbd4 100644
--- a/gcc/cgraphunit.cc
+++ b/gcc/cgraphunit.cc
@@ -3289,6 +3289,7 @@ data_value::set_cst_at (unsigned dest_offset, unsigned 
value_width,
   enum value_type orig_type = classify (dest_offset, value_width);
   wide_int dest_mask = wi::shifted_mask (dest_offset, value_width, false,
                                         bit_width);
+  // TODO: invalidate existing address if any
   gcc_assert (orig_type != VAL_ADDRESS);
   if (orig_type != VAL_CONSTANT)
     {
diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc
index 41069947c793..1c62e691d210 100644
--- a/gcc/fortran/trans-array.cc
+++ b/gcc/fortran/trans-array.cc
@@ -10131,76 +10131,6 @@ gfc_check_pdt_dummy (gfc_symbol * der_type, tree decl, 
int rank,
 }
 
 
-/* Returns the value of LBOUND for an expression.  This could be broken out
-   from gfc_conv_intrinsic_bound but this seemed to be simpler.  This is
-   called by gfc_alloc_allocatable_for_assignment.  */
-static tree
-get_std_lbound (gfc_expr *expr, tree desc, int dim, bool assumed_size)
-{
-  tree lbound;
-  tree ubound;
-  tree stride;
-  tree cond, cond1, cond3, cond4;
-  tree tmp;
-  gfc_ref *ref;
-
-  if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
-    {
-      tmp = gfc_rank_cst[dim];
-      lbound = gfc_conv_descriptor_lbound_get (desc, tmp);
-      ubound = gfc_conv_descriptor_ubound_get (desc, tmp);
-      stride = gfc_conv_descriptor_stride_get (desc, tmp);
-      cond1 = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
-                              ubound, lbound);
-      cond3 = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
-                              stride, gfc_index_zero_node);
-      cond3 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
-                              logical_type_node, cond3, cond1);
-      cond4 = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
-                              stride, gfc_index_zero_node);
-      if (assumed_size)
-       cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
-                               tmp, build_int_cst (gfc_array_index_type,
-                                                   expr->rank - 1));
-      else
-       cond = logical_false_node;
-
-      cond1 = fold_build2_loc (input_location, TRUTH_OR_EXPR,
-                              logical_type_node, cond3, cond4);
-      cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
-                             logical_type_node, cond, cond1);
-
-      return fold_build3_loc (input_location, COND_EXPR,
-                             gfc_array_index_type, cond,
-                             lbound, gfc_index_one_node);
-    }
-
-  if (expr->expr_type == EXPR_FUNCTION)
-    {
-      /* A conversion function, so use the argument.  */
-      gcc_assert (expr->value.function.isym
-                 && expr->value.function.isym->conversion);
-      expr = expr->value.function.actual->expr;
-    }
-
-  if (expr->expr_type == EXPR_VARIABLE)
-    {
-      tmp = TREE_TYPE (expr->symtree->n.sym->backend_decl);
-      for (ref = expr->ref; ref; ref = ref->next)
-       {
-         if (ref->type == REF_COMPONENT
-               && ref->u.c.component->as
-               && ref->next
-               && ref->next->u.ar.type == AR_FULL)
-           tmp = TREE_TYPE (ref->u.c.component->backend_decl);
-       }
-      return GFC_TYPE_ARRAY_LBOUND(tmp, dim);
-    }
-
-  return gfc_index_one_node;
-}
-
-
 /* Returns true if an expression represents an lhs that can be reallocated
    on assignment.  */
 
@@ -10399,7 +10329,6 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo 
*loop,
   gfc_array_info *linfo;
   tree realloc_expr;
   tree alloc_expr;
-  tree size1;
   tree size2;
   tree elemsize1;
   tree elemsize2;
@@ -10407,20 +10336,15 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo 
*loop,
   tree cond_null;
   tree cond;
   tree tmp;
-  tree tmp2;
   tree lbound;
   tree ubound;
   tree desc;
-  tree old_desc;
   tree desc2;
-  tree offset;
+  tree old_desc;
   tree jump_label1;
   tree jump_label2;
-  tree lbd;
   tree class_expr2 = NULL_TREE;
   int n;
-  int dim;
-  gfc_array_spec * as;
   bool coarray = (flag_coarray == GFC_FCOARRAY_LIB
                  && gfc_caf_attr (expr1, true).codimension);
   tree token;
@@ -10608,20 +10532,6 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo 
*loop,
                  build_empty_stmt (input_location));
   gfc_add_expr_to_block (&fblock, tmp);
 
-  /* Get arrayspec if expr is a full array.  */
-  if (expr2 && expr2->expr_type == EXPR_FUNCTION
-       && expr2->value.function.isym
-       && expr2->value.function.isym->conversion)
-    {
-      /* For conversion functions, take the arg.  */
-      gfc_expr *arg = expr2->value.function.actual->expr;
-      as = gfc_get_full_arrayspec_from_expr (arg);
-    }
-  else if (expr2)
-    as = gfc_get_full_arrayspec_from_expr (expr2);
-  else
-    as = NULL;
-
   /* If the lhs shape is not the same as the rhs jump to setting the
      bounds and doing the reallocation.......  */
   for (n = 0; n < expr1->rank; n++)
@@ -10687,66 +10597,6 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo 
*loop,
   else
     old_desc = NULL_TREE;
 
-  /* Now modify the lhs descriptor and the associated scalarizer
-     variables. F2003 7.4.1.3: "If variable is or becomes an
-     unallocated allocatable variable, then it is allocated with each
-     deferred type parameter equal to the corresponding type parameters
-     of expr , with the shape of expr , and with each lower bound equal
-     to the corresponding element of LBOUND(expr)."
-     Reuse size1 to keep a dimension-by-dimension track of the
-     stride of the new array.  */
-  size1 = gfc_index_one_node;
-  offset = gfc_index_zero_node;
-
-  for (n = 0; n < expr2->rank; n++)
-    {
-      tmp = gfc_conv_array_extent_dim (loop->from[n], loop->to[n], NULL);
-
-      lbound = gfc_index_one_node;
-      ubound = tmp;
-
-      if (as)
-       {
-         lbd = get_std_lbound (expr2, desc2, n,
-                               as->type == AS_ASSUMED_SIZE);
-         ubound = fold_build2_loc (input_location,
-                                   MINUS_EXPR,
-                                   gfc_array_index_type,
-                                   ubound, lbound);
-         ubound = fold_build2_loc (input_location,
-                                   PLUS_EXPR,
-                                   gfc_array_index_type,
-                                   ubound, lbd);
-         lbound = lbd;
-       }
-
-      gfc_conv_descriptor_lbound_set (&fblock, desc,
-                                     gfc_rank_cst[n],
-                                     lbound);
-      gfc_conv_descriptor_ubound_set (&fblock, desc,
-                                     gfc_rank_cst[n],
-                                     ubound);
-      gfc_conv_descriptor_stride_set (&fblock, desc,
-                                     gfc_rank_cst[n],
-                                     size1);
-      lbound = gfc_conv_descriptor_lbound_get (desc,
-                                              gfc_rank_cst[n]);
-      tmp2 = fold_build2_loc (input_location, MULT_EXPR,
-                             gfc_array_index_type,
-                             lbound, size1);
-      offset = fold_build2_loc (input_location, MINUS_EXPR,
-                               gfc_array_index_type,
-                               offset, tmp2);
-      size1 = fold_build2_loc (input_location, MULT_EXPR,
-                              gfc_array_index_type,
-                              tmp, size1);
-    }
-
-  /* Set the lhs descriptor and scalarizer offsets.  For rank > 1,
-     the array offset is saved and the info.offset is used for a
-     running offset.  Use the saved_offset instead.  */
-  gfc_conv_descriptor_offset_set (&fblock, desc, offset);
-
   /* Take into account _len of unlimited polymorphic entities, so that span
      for array descriptors and allocation sizes are computed correctly.  */
   if (UNLIMITED_POLY (expr2))
@@ -10760,9 +10610,6 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo 
*loop,
                                   fold_convert (gfc_array_index_type, len));
     }
 
-  if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
-    gfc_conv_descriptor_span_set (&fblock, desc, elemsize2);
-
   size2 = fold_build2_loc (input_location, MULT_EXPR,
                           gfc_array_index_type,
                           elemsize2, size2);
@@ -10771,69 +10618,8 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo 
*loop,
                           size2, size_one_node);
   size2 = gfc_evaluate_now (size2, &fblock);
 
-  /* For deferred character length, the 'size' field of the dtype might
-     have changed so set the dtype.  */
-  if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc))
-      && expr1->ts.type == BT_CHARACTER && expr1->ts.deferred)
-    {
-      tree type;
-      if (expr2->ts.u.cl->backend_decl)
-       type = gfc_typenode_for_spec (&expr2->ts);
-      else
-       type = gfc_typenode_for_spec (&expr1->ts);
-
-      tree dtype_value = gfc_get_dtype_rank_type (expr1->rank, type);
-      gfc_conv_descriptor_dtype_set (&fblock, desc, dtype_value);
-    }
-  else if (expr1->ts.type == BT_CLASS)
-    {
-      tree type;
-      if (expr2->ts.type != BT_CLASS)
-       type = gfc_typenode_for_spec (&expr2->ts);
-      else
-       type = gfc_get_character_type_len (1, elemsize2);
-
-      tree dtype_value = gfc_get_dtype_rank_type (expr2->rank, type);
-      gfc_conv_descriptor_dtype_set (&fblock, desc, dtype_value);
-
-      /* Set the _len field as well...  */
-      if (UNLIMITED_POLY (expr1))
-       {
-         tmp = gfc_class_len_get (TREE_OPERAND (desc, 0));
-         if (expr2->ts.type == BT_CHARACTER)
-           gfc_add_modify (&fblock, tmp,
-                           fold_convert (TREE_TYPE (tmp),
-                                         TYPE_SIZE_UNIT (type)));
-         else if (UNLIMITED_POLY (expr2))
-           gfc_add_modify (&fblock, tmp,
-                           gfc_class_len_get (TREE_OPERAND (desc2, 0)));
-         else
-           gfc_add_modify (&fblock, tmp,
-                           build_int_cst (TREE_TYPE (tmp), 0));
-       }
-      /* ...and the vptr.  */
-      tmp = gfc_class_vptr_get (TREE_OPERAND (desc, 0));
-      if (expr2->ts.type == BT_CLASS && !VAR_P (desc2)
-         && TREE_CODE (desc2) == COMPONENT_REF)
-       {
-         tmp2 = gfc_get_class_from_expr (desc2);
-         tmp2 = gfc_class_vptr_get (tmp2);
-       }
-      else if (expr2->ts.type == BT_CLASS && class_expr2 != NULL_TREE)
-       tmp2 = gfc_class_vptr_get (class_expr2);
-      else
-       {
-         tmp2 = gfc_get_symbol_decl (gfc_find_vtab (&expr2->ts));
-         tmp2 = gfc_build_addr_expr (TREE_TYPE (tmp), tmp2);
-       }
-
-      gfc_add_modify (&fblock, tmp, fold_convert (TREE_TYPE (tmp), tmp2));
-    }
-  else if (coarray && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
-    {
-      gfc_conv_descriptor_dtype_set (&fblock, desc,
-                                    gfc_get_dtype (TREE_TYPE (desc)));
-    }
+  gfc_set_descriptor_for_assign_realloc (&fblock, loop, expr1, expr2, desc,
+                                        desc2, elemsize2, class_expr2);
 
   /* Realloc expression.  Note that the scalarizer uses desc.data
      in the array reference - (*desc.data)[<element>].  */
diff --git a/gcc/fortran/trans-descriptor.cc b/gcc/fortran/trans-descriptor.cc
index f6ffc55cccf3..dbc7f043e80f 100644
--- a/gcc/fortran/trans-descriptor.cc
+++ b/gcc/fortran/trans-descriptor.cc
@@ -3578,3 +3578,225 @@ gfc_copy_descriptor (stmtblock_t *block, tree dst, tree 
src, int rank)
 }
 
 
+/* Returns the value of LBOUND for an expression.  This could be broken out
+   from gfc_conv_intrinsic_bound but this seemed to be simpler.  This is
+   called by gfc_alloc_allocatable_for_assignment.  */
+static tree
+get_std_lbound (gfc_expr *expr, tree desc, int dim, bool assumed_size)
+{
+  tree lbound;
+  tree ubound;
+  tree stride;
+  tree cond, cond1, cond3, cond4;
+  tree tmp;
+  gfc_ref *ref;
+
+  if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
+    {
+      tmp = gfc_rank_cst[dim];
+      lbound = gfc_conv_descriptor_lbound_get (desc, tmp);
+      ubound = gfc_conv_descriptor_ubound_get (desc, tmp);
+      stride = gfc_conv_descriptor_stride_get (desc, tmp);
+      cond1 = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
+                              ubound, lbound);
+      cond3 = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
+                              stride, gfc_index_zero_node);
+      cond3 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
+                              logical_type_node, cond3, cond1);
+      cond4 = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
+                              stride, gfc_index_zero_node);
+      if (assumed_size)
+       cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
+                               tmp, build_int_cst (gfc_array_index_type,
+                                                   expr->rank - 1));
+      else
+       cond = logical_false_node;
+
+      cond1 = fold_build2_loc (input_location, TRUTH_OR_EXPR,
+                              logical_type_node, cond3, cond4);
+      cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
+                             logical_type_node, cond, cond1);
+
+      return fold_build3_loc (input_location, COND_EXPR,
+                             gfc_array_index_type, cond,
+                             lbound, gfc_index_one_node);
+    }
+
+  if (expr->expr_type == EXPR_FUNCTION)
+    {
+      /* A conversion function, so use the argument.  */
+      gcc_assert (expr->value.function.isym
+                 && expr->value.function.isym->conversion);
+      expr = expr->value.function.actual->expr;
+    }
+
+  if (expr->expr_type == EXPR_VARIABLE)
+    {
+      tmp = TREE_TYPE (expr->symtree->n.sym->backend_decl);
+      for (ref = expr->ref; ref; ref = ref->next)
+       {
+         if (ref->type == REF_COMPONENT
+               && ref->u.c.component->as
+               && ref->next
+               && ref->next->u.ar.type == AR_FULL)
+           tmp = TREE_TYPE (ref->u.c.component->backend_decl);
+       }
+      return GFC_TYPE_ARRAY_LBOUND(tmp, dim);
+    }
+
+  return gfc_index_one_node;
+}
+
+
+void
+gfc_set_descriptor_for_assign_realloc (stmtblock_t *block, gfc_loopinfo *loop,
+                                      gfc_expr *expr1, gfc_expr *expr2,
+                                      tree desc, tree desc2, tree elemsize2,
+                                      tree class_expr2)
+{
+  bool coarray = (flag_coarray == GFC_FCOARRAY_LIB
+                 && gfc_caf_attr (expr1, true).codimension);
+
+  gfc_array_spec * as;
+  /* Get arrayspec if expr is a full array.  */
+  if (expr2 && expr2->expr_type == EXPR_FUNCTION
+       && expr2->value.function.isym
+       && expr2->value.function.isym->conversion)
+    {
+      /* For conversion functions, take the arg.  */
+      gfc_expr *arg = expr2->value.function.actual->expr;
+      as = gfc_get_full_arrayspec_from_expr (arg);
+    }
+  else if (expr2)
+    as = gfc_get_full_arrayspec_from_expr (expr2);
+  else
+    as = NULL;
+
+  /* Modify the lhs descriptor and the associated scalarizer
+     variables. F2003 7.4.1.3: "If variable is or becomes an
+     unallocated allocatable variable, then it is allocated with each
+     deferred type parameter equal to the corresponding type parameters
+     of expr , with the shape of expr , and with each lower bound equal
+     to the corresponding element of LBOUND(expr)."
+     Reuse size1 to keep a dimension-by-dimension track of the
+     stride of the new array.  */
+  tree size1 = gfc_index_one_node;
+  tree offset = gfc_index_zero_node;
+
+  for (int n = 0; n < expr2->rank; n++)
+    {
+      tree tmp = gfc_conv_array_extent_dim (loop->from[n], loop->to[n], NULL);
+
+      tree lbound = gfc_index_one_node;
+      tree ubound = tmp;
+
+      if (as)
+       {
+         tree lbd = get_std_lbound (expr2, desc2, n,
+                                    as->type == AS_ASSUMED_SIZE);
+         ubound = fold_build2_loc (input_location,
+                                   MINUS_EXPR,
+                                   gfc_array_index_type,
+                                   ubound, lbound);
+         ubound = fold_build2_loc (input_location,
+                                   PLUS_EXPR,
+                                   gfc_array_index_type,
+                                   ubound, lbd);
+         lbound = lbd;
+       }
+
+      gfc_conv_descriptor_lbound_set (block, desc,
+                                     gfc_rank_cst[n],
+                                     lbound);
+      gfc_conv_descriptor_ubound_set (block, desc,
+                                     gfc_rank_cst[n],
+                                     ubound);
+      gfc_conv_descriptor_stride_set (block, desc,
+                                     gfc_rank_cst[n],
+                                     size1);
+      lbound = gfc_conv_descriptor_lbound_get (desc,
+                                              gfc_rank_cst[n]);
+      tree tmp2 = fold_build2_loc (input_location, MULT_EXPR,
+                                  gfc_array_index_type, lbound, size1);
+      offset = fold_build2_loc (input_location, MINUS_EXPR,
+                               gfc_array_index_type,
+                               offset, tmp2);
+      tree size1 = fold_build2_loc (input_location, MULT_EXPR,
+                                   gfc_array_index_type, tmp, size1);
+    }
+
+  /* Set the lhs descriptor and scalarizer offsets.  For rank > 1,
+     the array offset is saved and the info.offset is used for a
+     running offset.  Use the saved_offset instead.  */
+  gfc_conv_descriptor_offset_set (block, desc, offset);
+
+  if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
+    gfc_conv_descriptor_span_set (block, desc, elemsize2);
+
+  /* For deferred character length, the 'size' field of the dtype might
+     have changed so set the dtype.  */
+  if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc))
+      && expr1->ts.type == BT_CHARACTER && expr1->ts.deferred)
+    {
+      tree type;
+      if (expr2->ts.u.cl->backend_decl)
+       type = gfc_typenode_for_spec (&expr2->ts);
+      else
+       type = gfc_typenode_for_spec (&expr1->ts);
+
+      tree dtype_value = gfc_get_dtype_rank_type (expr1->rank, type);
+      gfc_conv_descriptor_dtype_set (block, desc, dtype_value);
+    }
+  else if (expr1->ts.type == BT_CLASS)
+    {
+      tree type;
+      if (expr2->ts.type != BT_CLASS)
+       type = gfc_typenode_for_spec (&expr2->ts);
+      else
+       type = gfc_get_character_type_len (1, elemsize2);
+
+      tree dtype_value = gfc_get_dtype_rank_type (expr2->rank, type);
+      gfc_conv_descriptor_dtype_set (block, desc, dtype_value);
+
+      /* Set the _len field as well...  */
+      if (UNLIMITED_POLY (expr1))
+       {
+         tree tmp = gfc_class_len_get (TREE_OPERAND (desc, 0));
+         if (expr2->ts.type == BT_CHARACTER)
+           gfc_add_modify (block, tmp,
+                           fold_convert (TREE_TYPE (tmp),
+                                         TYPE_SIZE_UNIT (type)));
+         else if (UNLIMITED_POLY (expr2))
+           gfc_add_modify (block, tmp,
+                           gfc_class_len_get (TREE_OPERAND (desc2, 0)));
+         else
+           gfc_add_modify (block, tmp,
+                           build_int_cst (TREE_TYPE (tmp), 0));
+       }
+      /* ...and the vptr.  */
+      tree tmp = gfc_class_vptr_get (TREE_OPERAND (desc, 0));
+      tree tmp2;
+      if (expr2->ts.type == BT_CLASS && !VAR_P (desc2)
+         && TREE_CODE (desc2) == COMPONENT_REF)
+       {
+         tmp2 = gfc_get_class_from_expr (desc2);
+         tmp2 = gfc_class_vptr_get (tmp2);
+       }
+      else if (expr2->ts.type == BT_CLASS && class_expr2 != NULL_TREE)
+       tmp2 = gfc_class_vptr_get (class_expr2);
+      else
+       {
+         tmp2 = gfc_get_symbol_decl (gfc_find_vtab (&expr2->ts));
+         tmp2 = gfc_build_addr_expr (TREE_TYPE (tmp), tmp2);
+       }
+
+      gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (tmp), tmp2));
+    }
+  else if (coarray && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
+    {
+      gfc_conv_descriptor_dtype_set (block, desc,
+                                    gfc_get_dtype (TREE_TYPE (desc)));
+    }
+}
+
+
diff --git a/gcc/fortran/trans-descriptor.h b/gcc/fortran/trans-descriptor.h
index cdc9b323afbf..353e33880c7a 100644
--- a/gcc/fortran/trans-descriptor.h
+++ b/gcc/fortran/trans-descriptor.h
@@ -112,4 +112,8 @@ gfc_class_array_data_assign (stmtblock_t *, tree, tree, 
bool);
 void
 gfc_copy_descriptor (stmtblock_t *, tree, tree, int);
 
+void
+gfc_set_descriptor_for_assign_realloc (stmtblock_t *, gfc_loopinfo *,
+                                      gfc_expr *, gfc_expr *, tree, tree,
+                                      tree, tree);

Reply via email to