[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