[gcc(refs/users/mikael/heads/refactor_descriptor_v05)] Factorisation gfc_conv_expr_descriptor

Mikael Morin mikael@gcc.gnu.org
Fri Jun 13 14:40:49 GMT 2025


https://gcc.gnu.org/g:bc9157f3ac1abbd0425f4cc026334bbd399340e4

commit bc9157f3ac1abbd0425f4cc026334bbd399340e4
Author: Mikael Morin <mikael@gcc.gnu.org>
Date:   Thu Jan 16 14:00:20 2025 +0100

    Factorisation gfc_conv_expr_descriptor

Diff:
---
 gcc/fortran/trans-array.cc | 380 +++++++++++++++++++++++----------------------
 1 file changed, 197 insertions(+), 183 deletions(-)

diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc
index 5527e99ecc01..1f96d813ca22 100644
--- a/gcc/fortran/trans-array.cc
+++ b/gcc/fortran/trans-array.cc
@@ -1543,6 +1543,38 @@ keep_descriptor_lower_bound (gfc_expr *e)
   return true;
 }
 
+static void
+copy_descriptor (stmtblock_t *block, tree dest, tree src,
+		 gfc_expr *src_expr, bool subref)
+{
+  struct lang_type *dest_ls = TYPE_LANG_SPECIFIC (TREE_TYPE (dest));
+  struct lang_type *src_ls = TYPE_LANG_SPECIFIC (TREE_TYPE (src));
+
+  /* When only the array_kind differs, do a view_convert.  */
+  tree tmp1;
+  if (dest_ls
+      && src_ls
+      && dest_ls->rank == src_ls->rank
+      && dest_ls->akind != src_ls->akind)
+    tmp1 = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (dest), src);
+  else
+    tmp1 = desc;
+
+  /* Copy the descriptor for pointer assignments.  */
+  gfc_add_modify (block, dest, tmp1);
+
+  /* Add any offsets from subreferences.  */
+  gfc_get_dataptr_offset (block, dest, src, NULL_TREE, subref, src_expr);
+
+  /* ....and set the span field.  */
+  tree tmp2
+  if (src_expr->ts.type == BT_CHARACTER)
+    tmp2 = gfc_conv_descriptor_span_get (src);
+  else
+    tmp2 = gfc_get_array_span (src, src_expr);
+  gfc_conv_descriptor_span_set (block, dest, tmp2);
+}
+
 
 /* Obtain offsets for trans-types.cc(gfc_get_array_descr_info).  */
 
@@ -8999,37 +9031,175 @@ is_explicit_coarray (gfc_expr *expr)
 
 
 static void
-copy_descriptor (stmtblock_t *block, tree dest, tree src,
-		 gfc_expr *src_expr, bool subref)
+set_descriptor (stmtblock_t *block, tree dest, tree src, gfc_expr *src_expr,
+		int rank, int corank, gfc_ss *ss, gfc_array_info *info,
+		tree lowers[GFC_MAX_DIMENSIONS],
+		tree uppers[GFC_MAX_DIMENSIONS],
+		bool unlimited_polymorphic, bool data_needed, bool subref)
 {
-  struct lang_type *dest_ls = TYPE_LANG_SPECIFIC (TREE_TYPE (dest));
-  struct lang_type *src_ls = TYPE_LANG_SPECIFIC (TREE_TYPE (src));
+  int ndim = info->ref ? info->ref->u.ar.dimen : rank;
 
-  /* When only the array_kind differs, do a view_convert.  */
-  tree tmp1;
-  if (dest_ls
-      && src_ls
-      && dest_ls->rank == src_ls->rank
-      && dest_ls->akind != src_ls->akind)
-    tmp1 = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (dest), src);
+  /* Set the span field.  */
+  tree tmp = NULL_TREE;
+  if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (src)))
+    tmp = gfc_conv_descriptor_span_get (src);
   else
-    tmp1 = desc;
+    tmp = gfc_get_array_span (src, src_expr);
+  if (tmp)
+    gfc_conv_descriptor_span_set (block, dest, tmp);
+
+  /* The following can be somewhat confusing.  We have two
+     descriptors, a new one and the original array.
+     {dest, parmtype, dim} refer to the new one.
+     {src, type, n, loop} refer to the original, which maybe
+     a descriptorless array.
+     The bounds of the scalarization are the bounds of the section.
+     We don't have to worry about numeric overflows when calculating
+     the offsets because all elements are within the array data.  */
+
+  /* Set the dtype.  */
+  tmp = gfc_conv_descriptor_dtype (dest);
+  tree dtype;
+  if (unlimited_polymorphic)
+    dtype = gfc_get_dtype (TREE_TYPE (src), &rank);
+  else if (src_expr->ts.type == BT_ASSUMED)
+    {
+      tree tmp2 = src;
+      if (DECL_LANG_SPECIFIC (tmp2) && GFC_DECL_SAVED_DESCRIPTOR (tmp2))
+	tmp2 = GFC_DECL_SAVED_DESCRIPTOR (tmp2);
+      if (POINTER_TYPE_P (TREE_TYPE (tmp2)))
+	tmp2 = build_fold_indirect_ref_loc (input_location, tmp2);
+      dtype = gfc_conv_descriptor_dtype (tmp2);
+    }
+  else
+    dtype = gfc_get_dtype (TREE_TYPE (dest));
+  gfc_add_modify (block, tmp, dtype);
 
-  /* Copy the descriptor for pointer assignments.  */
-  gfc_add_modify (block, dest, tmp1);
+  /* The 1st element in the section.  */
+  tree base = gfc_index_zero_node;
+  if (src_expr->ts.type == BT_CHARACTER && src_expr->rank == 0 && corank)
+    base = gfc_index_one_node;
 
-  /* Add any offsets from subreferences.  */
-  gfc_get_dataptr_offset (block, dest, src, NULL_TREE, subref, src_expr);
+  /* The offset from the 1st element in the section.  */
+  tree offset = gfc_index_zero_node;
 
-  /* ....and set the span field.  */
-  tree tmp2
-  if (src_expr->ts.type == BT_CHARACTER)
-    tmp2 = gfc_conv_descriptor_span_get (src);
+  for (int n = 0; n < ndim; n++)
+    {
+      tree stride = gfc_conv_array_stride (src, n);
+
+      /* Work out the 1st element in the section.  */
+      tree start;
+      if (info->ref
+	  && info->ref->u.ar.dimen_type[n] == DIMEN_ELEMENT)
+	{
+	  gcc_assert (info->subscript[n]
+		      && info->subscript[n]->info->type == GFC_SS_SCALAR);
+	  start = info->subscript[n]->info->data.scalar.value;
+	}
+      else
+	{
+	  /* Evaluate and remember the start of the section.  */
+	  start = info->start[n];
+	  stride = gfc_evaluate_now (stride, block);
+	}
+
+      tmp = gfc_conv_array_lbound (src, n);
+      tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp),
+			     start, tmp);
+      tmp = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (tmp),
+			     tmp, stride);
+      base = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (tmp),
+				base, tmp);
+
+      if (info->ref
+	  && info->ref->u.ar.dimen_type[n] == DIMEN_ELEMENT)
+	{
+	  /* For elemental dimensions, we only need the 1st
+	     element in the section.  */
+	  continue;
+	}
+
+      /* Vector subscripts need copying and are handled elsewhere.  */
+      if (info->ref)
+	gcc_assert (info->ref->u.ar.dimen_type[n] == DIMEN_RANGE);
+
+      /* look for the corresponding scalarizer dimension: dim.  */
+      int dim;
+      for (dim = 0; dim < ndim; dim++)
+	if (ss->dim[dim] == n)
+	  break;
+
+      /* loop exited early: the DIM being looked for has been found.  */
+      gcc_assert (dim < ndim);
+
+      /* Set the new lower bound.  */
+      tree from = lowers[dim];
+      tree to = uppers[dim];
+
+      gfc_conv_descriptor_lbound_set (block, dest,
+				      gfc_rank_cst[dim], from);
+
+      /* Set the new upper bound.  */
+      gfc_conv_descriptor_ubound_set (block, dest,
+				      gfc_rank_cst[dim], to);
+
+      /* Multiply the stride by the section stride to get the
+	 total stride.  */
+      stride = fold_build2_loc (input_location, MULT_EXPR,
+				gfc_array_index_type,
+				stride, info->stride[n]);
+
+      tmp = fold_build2_loc (input_location, MULT_EXPR,
+			     TREE_TYPE (offset), stride, from);
+      offset = fold_build2_loc (input_location, MINUS_EXPR,
+			       TREE_TYPE (offset), offset, tmp);
+
+      /* Store the new stride.  */
+      gfc_conv_descriptor_stride_set (block, dest,
+				      gfc_rank_cst[dim], stride);
+    }
+
+  for (int n = rank; n < rank + corank; n++)
+    {
+      tree from = lowers[n];
+      tree to = uppers[n];
+      gfc_conv_descriptor_lbound_set (block, dest,
+				      gfc_rank_cst[n], from);
+      if (n < rank + corank - 1)
+	gfc_conv_descriptor_ubound_set (block, dest,
+					gfc_rank_cst[n], to);
+    }
+
+  if (data_needed)
+    /* Point the data pointer at the 1st element in the section.  */
+    gfc_get_dataptr_offset (block, dest, src, base,
+			    subref, src_expr);
   else
-    tmp2 = gfc_get_array_span (src, src_expr);
-  gfc_conv_descriptor_span_set (block, dest, tmp2);
+    gfc_conv_descriptor_data_set (block, dest,
+				  gfc_index_zero_node);
+
+  gfc_conv_descriptor_offset_set (block, dest, offset);
+
+  if (flag_coarray == GFC_FCOARRAY_LIB && src_expr->corank)
+    {
+      tmp = INDIRECT_REF_P (src) ? TREE_OPERAND (src, 0) : src;
+      if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp)))
+	{
+	  tmp = gfc_conv_descriptor_token (tmp);
+	}
+      else if (DECL_P (tmp) && DECL_LANG_SPECIFIC (tmp)
+	       && GFC_DECL_TOKEN (tmp) != NULL_TREE)
+	tmp = GFC_DECL_TOKEN (tmp);
+      else
+	{
+	  tmp = GFC_TYPE_ARRAY_CAF_TOKEN (TREE_TYPE (tmp));
+	}
+
+      gfc_add_modify (block, gfc_conv_descriptor_token (dest), tmp);
+    }
 }
 
+
 /* Convert an array for passing as an actual argument.  Expressions and
    vector subscripts are evaluated and stored in a temporary, which is then
    passed.  For whole arrays the descriptor is passed.  For array sections
@@ -9072,11 +9242,11 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
   tree tmp;
   tree desc;
   stmtblock_t block;
-  tree start;
   int full;
   bool subref_array_target = false;
   bool deferred_array_component = false;
   bool substr = false;
+  bool unlimited_polymorphic = false;
   gfc_expr *arg, *ss_expr;
 
   if (se->want_coarray || expr->rank == 0)
@@ -9102,7 +9272,7 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
     }
 
   if (!se->direct_byref)
-    se->unlimited_polymorphic = UNLIMITED_POLY (expr);
+    unlimited_polymorphic = UNLIMITED_POLY (expr);
 
   /* Special case things we know we can pass easily.  */
   switch (expr->expr_type)
@@ -9386,12 +9556,6 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
       int dim, ndim, codim;
       tree parm;
       tree parmtype;
-      tree dtype;
-      tree stride;
-      tree from;
-      tree to;
-      tree base;
-      tree offset;
 
       ndim = info->ref ? info->ref->u.ar.dimen : ss->dimen;
 
@@ -9512,161 +9676,11 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
 			  gfc_get_array_span (desc, expr)));
 	}
 
-      /* Set the span field.  */
-      tmp = NULL_TREE;
-      if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
-	tmp = gfc_conv_descriptor_span_get (desc);
-      else
-	tmp = gfc_get_array_span (desc, expr);
-      if (tmp)
-	gfc_conv_descriptor_span_set (&loop.pre, parm, tmp);
-
-      /* The following can be somewhat confusing.  We have two
-         descriptors, a new one and the original array.
-         {parm, parmtype, dim} refer to the new one.
-         {desc, type, n, loop} refer to the original, which maybe
-         a descriptorless array.
-         The bounds of the scalarization are the bounds of the section.
-         We don't have to worry about numeric overflows when calculating
-         the offsets because all elements are within the array data.  */
-
-      /* Set the dtype.  */
-      tmp = gfc_conv_descriptor_dtype (parm);
-      if (se->unlimited_polymorphic)
-	dtype = gfc_get_dtype (TREE_TYPE (desc), &loop.dimen);
-      else if (expr->ts.type == BT_ASSUMED)
-	{
-	  tree tmp2 = desc;
-	  if (DECL_LANG_SPECIFIC (tmp2) && GFC_DECL_SAVED_DESCRIPTOR (tmp2))
-	    tmp2 = GFC_DECL_SAVED_DESCRIPTOR (tmp2);
-	  if (POINTER_TYPE_P (TREE_TYPE (tmp2)))
-	    tmp2 = build_fold_indirect_ref_loc (input_location, tmp2);
-	  dtype = gfc_conv_descriptor_dtype (tmp2);
-	}
-      else
-	dtype = gfc_get_dtype (parmtype);
-      gfc_add_modify (&loop.pre, tmp, dtype);
-
-      /* The 1st element in the section.  */
-      base = gfc_index_zero_node;
-      if (expr->ts.type == BT_CHARACTER && expr->rank == 0 && codim)
-	base = gfc_index_one_node;
 
-      /* The offset from the 1st element in the section.  */
-      offset = gfc_index_zero_node;
-
-      for (n = 0; n < ndim; n++)
-	{
-	  stride = gfc_conv_array_stride (desc, n);
+      set_descriptor (&se->pre, parm, desc, expr, loop.dimen, codim,
+		      ss, info, loop.from, loop.to, unlimited_polymorphic,
+		      !se->data_not_needed, subref_array_target);
 
-	  /* Work out the 1st element in the section.  */
-	  if (info->ref
-	      && info->ref->u.ar.dimen_type[n] == DIMEN_ELEMENT)
-	    {
-	      gcc_assert (info->subscript[n]
-			  && info->subscript[n]->info->type == GFC_SS_SCALAR);
-	      start = info->subscript[n]->info->data.scalar.value;
-	    }
-	  else
-	    {
-	      /* Evaluate and remember the start of the section.  */
-	      start = info->start[n];
-	      stride = gfc_evaluate_now (stride, &loop.pre);
-	    }
-
-	  tmp = gfc_conv_array_lbound (desc, n);
-	  tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp),
-				 start, tmp);
-	  tmp = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (tmp),
-				 tmp, stride);
-	  base = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (tmp),
-				    base, tmp);
-
-	  if (info->ref
-	      && info->ref->u.ar.dimen_type[n] == DIMEN_ELEMENT)
-	    {
-	      /* For elemental dimensions, we only need the 1st
-		 element in the section.  */
-	      continue;
-	    }
-
-	  /* Vector subscripts need copying and are handled elsewhere.  */
-	  if (info->ref)
-	    gcc_assert (info->ref->u.ar.dimen_type[n] == DIMEN_RANGE);
-
-	  /* look for the corresponding scalarizer dimension: dim.  */
-	  for (dim = 0; dim < ndim; dim++)
-	    if (ss->dim[dim] == n)
-	      break;
-
-	  /* loop exited early: the DIM being looked for has been found.  */
-	  gcc_assert (dim < ndim);
-
-	  /* Set the new lower bound.  */
-	  from = loop.from[dim];
-	  to = loop.to[dim];
-
-	  gfc_conv_descriptor_lbound_set (&loop.pre, parm,
-					  gfc_rank_cst[dim], from);
-
-	  /* Set the new upper bound.  */
-	  gfc_conv_descriptor_ubound_set (&loop.pre, parm,
-					  gfc_rank_cst[dim], to);
-
-	  /* Multiply the stride by the section stride to get the
-	     total stride.  */
-	  stride = fold_build2_loc (input_location, MULT_EXPR,
-				    gfc_array_index_type,
-				    stride, info->stride[n]);
-
-	  tmp = fold_build2_loc (input_location, MULT_EXPR,
-				 TREE_TYPE (offset), stride, from);
-	  offset = fold_build2_loc (input_location, MINUS_EXPR,
-				   TREE_TYPE (offset), offset, tmp);
-
-	  /* Store the new stride.  */
-	  gfc_conv_descriptor_stride_set (&loop.pre, parm,
-					  gfc_rank_cst[dim], stride);
-	}
-
-      for (n = loop.dimen; n < loop.dimen + codim; n++)
-	{
-	  from = loop.from[n];
-	  to = loop.to[n];
-	  gfc_conv_descriptor_lbound_set (&loop.pre, parm,
-					  gfc_rank_cst[n], from);
-	  if (n < loop.dimen + codim - 1)
-	    gfc_conv_descriptor_ubound_set (&loop.pre, parm,
-					    gfc_rank_cst[n], to);
-	}
-
-      if (se->data_not_needed)
-	gfc_conv_descriptor_data_set (&loop.pre, parm,
-				      gfc_index_zero_node);
-      else
-	/* Point the data pointer at the 1st element in the section.  */
-	gfc_get_dataptr_offset (&loop.pre, parm, desc, base,
-				subref_array_target, expr);
-
-      gfc_conv_descriptor_offset_set (&loop.pre, parm, offset);
-
-      if (flag_coarray == GFC_FCOARRAY_LIB && expr->corank)
-	{
-	  tmp = INDIRECT_REF_P (desc) ? TREE_OPERAND (desc, 0) : desc;
-	  if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp)))
-	    {
-	      tmp = gfc_conv_descriptor_token (tmp);
-	    }
-	  else if (DECL_P (tmp) && DECL_LANG_SPECIFIC (tmp)
-		   && GFC_DECL_TOKEN (tmp) != NULL_TREE)
-	    tmp = GFC_DECL_TOKEN (tmp);
-	  else
-	    {
-	      tmp = GFC_TYPE_ARRAY_CAF_TOKEN (TREE_TYPE (tmp));
-	    }
-
-	  gfc_add_modify (&loop.pre, gfc_conv_descriptor_token (parm), tmp);
-	}
       desc = parm;
     }


More information about the Gcc-cvs mailing list