No functional changes in this patch.
gcc/fortran/ChangeLog
* trans-openmp.cc (gfc_trans_omp_array_section): Add comments and
use a more descriptive variable name.
---
gcc/fortran/trans-openmp.cc | 58 ++++++++++++++++++++++++++++++-------
1 file changed, 47 insertions(+), 11 deletions(-)
diff --git a/gcc/fortran/trans-openmp.cc b/gcc/fortran/trans-openmp.cc
index 11873d3b6fe..fd4b19f6626 100644
--- a/gcc/fortran/trans-openmp.cc
+++ b/gcc/fortran/trans-openmp.cc
@@ -3352,7 +3352,24 @@ gfc_convert_expr_to_tree (stmtblock_t *block, gfc_expr
*expr)
static vec<tree, va_heap, vl_embed> *doacross_steps;
-/* Translate an array section or array element. */
+/* Map an array section or array element.
+ BLOCK will hold any output statements generated; if there are iterators,
+ it's a block for the current iterator group.
+ OP is the construct containing the map clause.
+ N is the entry that appears in the clause namelist. It may contain iterator
+ variables.
+ DECL is the base object associated with the namelist entry. It can be an
+ array descriptor, a bare array, or pointer to an array.
+ ELEMENT is true for an array element, false for an array section.
+ OPENMP is true for OpenMP, false for OpenACC.
+ PTR_KIND is the map operation.
+ NODE is an input operand representing the map clause.
+ NODE2, NODE3, and NODE4 are output operands that will hold new map clauses
+ generated by this function. Not all of them are always needed. NODE2
+ is for an array descriptor object, NODE3 is for its data array, NODE4
+ is for a pointer mapping.
+ ITERATOR is a list of active iterator descriptors, chained through
+ TREE_CHAIN. */
static void
gfc_trans_omp_array_section (stmtblock_t *block, gfc_exec_op op,
@@ -3362,7 +3379,10 @@ gfc_trans_omp_array_section (stmtblock_t *block,
gfc_exec_op op,
tree iterator)
{
gfc_se se;
- tree ptr, ptr2;
+ /* PTR is the array expression from n->expr. If iterators are this
+ involved expression can involve iterator variables. BASE points to the
+ base array object obtained from DECL. */
+ tree ptr, base;
tree elemsz = NULL_TREE;
gfc_init_se (&se, NULL);
@@ -3429,11 +3449,13 @@ gfc_trans_omp_array_section (stmtblock_t *block,
gfc_exec_op op,
&& OMP_CLAUSE_MAP_KIND (node) != GOMP_MAP_DELETE)
{
+ /* NODE4 is a newly-generated map clause for the pointer. */
node4 = build_omp_clause (input_location,
OMP_CLAUSE_MAP);
OMP_CLAUSE_SET_MAP_KIND (node4, GOMP_MAP_POINTER);
OMP_CLAUSE_DECL (node4) = decl;
OMP_CLAUSE_SIZE (node4) = size_int (0);
+ /* Make DECL be the descriptor rather than the pointer to it. */
decl = build_fold_indirect_ref (decl);
}
else if (ptr_kind == GOMP_MAP_ALWAYS_POINTER
@@ -3457,7 +3479,8 @@ gfc_trans_omp_array_section (stmtblock_t *block,
gfc_exec_op op,
if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
{
tree type = TREE_TYPE (decl);
- ptr2 = gfc_conv_descriptor_data_get (decl);
+ base = gfc_conv_descriptor_data_get (decl);
+ /* NODE2 is a newly-generated map clause for the array descriptor DECL.
*/
node2 = build_omp_clause (input_location, OMP_CLAUSE_MAP);
OMP_CLAUSE_DECL (node2) = decl;
OMP_CLAUSE_SIZE (node2) = TYPE_SIZE_UNIT (type);
@@ -3474,6 +3497,7 @@ gfc_trans_omp_array_section (stmtblock_t *block,
gfc_exec_op op,
}
else
OMP_CLAUSE_SET_MAP_KIND (node2, GOMP_MAP_TO_PSET);
+ /* NODE3 is a newly-generated map clause for the array data. */
node3 = build_omp_clause (input_location, OMP_CLAUSE_MAP);
OMP_CLAUSE_SET_MAP_KIND (node3, ptr_kind);
OMP_CLAUSE_DECL (node3) = gfc_conv_descriptor_data_get (decl);
@@ -3485,14 +3509,14 @@ gfc_trans_omp_array_section (stmtblock_t *block,
gfc_exec_op op,
if (ptr_kind == GOMP_MAP_ATTACH_DETACH && !openmp)
STRIP_NOPS (OMP_CLAUSE_DECL (node3));
}
- else
+ else /* DECL is bare array or pointer to an array. */
{
if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
{
tree offset;
- ptr2 = build_fold_addr_expr (decl);
+ base = build_fold_addr_expr (decl);
offset = fold_build2 (MINUS_EXPR, ptrdiff_type_node, ptr,
- fold_convert (ptrdiff_type_node, ptr2));
+ fold_convert (ptrdiff_type_node, base));
offset = build2 (TRUNC_DIV_EXPR, ptrdiff_type_node,
offset, fold_convert (ptrdiff_type_node, elemsz));
offset = build4_loc (input_location, ARRAY_REF,
@@ -3503,26 +3527,38 @@ gfc_trans_omp_array_section (stmtblock_t *block,
gfc_exec_op op,
if (ptr_kind == GOMP_MAP_ATTACH_DETACH && openmp)
return;
}
- else
+ else /* DECL is a pointer. */
{
gcc_assert (POINTER_TYPE_P (TREE_TYPE (decl)));
- ptr2 = decl;
+ base = decl;
}
node3 = build_omp_clause (input_location,
OMP_CLAUSE_MAP);
OMP_CLAUSE_SET_MAP_KIND (node3, ptr_kind);
OMP_CLAUSE_DECL (node3) = decl;
}
- ptr2 = fold_convert (ptrdiff_type_node, ptr2);
+
+ /* FIXME: This is a broken hack. The ptr expression is based on the
+ namelist entry and can contain references to iterator variables, which
+ are not yet set to their initial values when ptr is used. This
+ tries to replace instances of the iterator values with the initial values
+ in ptr explicitly. It's broken because the expansion of ptr can also
+ add statements to the iterator block that also contain references to
+ the uninitialized variables, and substituting those similarly breaks
+ other things. */
+ base = fold_convert (ptrdiff_type_node, base);
for (tree it = iterator; it; it = TREE_CHAIN (it))
{
ptr = simplify_replace_tree (ptr, TREE_VEC_ELT (it, 0),
TREE_VEC_ELT (it, 1));
- ptr2 = simplify_replace_tree (ptr2, TREE_VEC_ELT (it, 0),
+ base = simplify_replace_tree (base, TREE_VEC_ELT (it, 0),
TREE_VEC_ELT (it, 1));
}
+
+ /* The OMP_CLAUSE_SIZE field for the array data map clause node3
+ contains the initial offset of ptr from base, not the size. */
OMP_CLAUSE_SIZE (node3) = fold_build2 (MINUS_EXPR, ptrdiff_type_node,
- ptr, ptr2);
+ ptr, base);
}
static tree
--
2.39.5