aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran/trans-openmp.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/fortran/trans-openmp.c')
-rw-r--r--gcc/fortran/trans-openmp.c561
1 files changed, 389 insertions, 172 deletions
diff --git a/gcc/fortran/trans-openmp.c b/gcc/fortran/trans-openmp.c
index 6666955..063d4c1 100644
--- a/gcc/fortran/trans-openmp.c
+++ b/gcc/fortran/trans-openmp.c
@@ -44,6 +44,7 @@ along with GCC; see the file COPYING3. If not see
#undef GCC_DIAG_STYLE
#define GCC_DIAG_STYLE __gcc_gfc__
#include "attribs.h"
+#include "function.h"
int ompws_flags;
@@ -90,16 +91,13 @@ gfc_omp_check_optional_argument (tree decl, bool for_present_check)
if (!DECL_LANG_SPECIFIC (decl))
return NULL_TREE;
- bool is_array_type = false;
+ tree orig_decl = decl;
/* For assumed-shape arrays, a local decl with arg->data is used. */
if (TREE_CODE (decl) != PARM_DECL
&& (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl))
|| GFC_ARRAY_TYPE_P (TREE_TYPE (decl))))
- {
- is_array_type = true;
- decl = GFC_DECL_SAVED_DESCRIPTOR (decl);
- }
+ decl = GFC_DECL_SAVED_DESCRIPTOR (decl);
if (decl == NULL_TREE
|| TREE_CODE (decl) != PARM_DECL
@@ -132,23 +130,8 @@ gfc_omp_check_optional_argument (tree decl, bool for_present_check)
return decl;
}
- tree cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
- decl, null_pointer_node);
-
- /* Fortran regards unallocated allocatables/disassociated pointer which
- are passed to a nonallocatable, nonpointer argument as not associated;
- cf. F2018, 15.5.2.12, Paragraph 1. */
- if (is_array_type)
- {
- tree cond2 = build_fold_indirect_ref_loc (input_location, decl);
- cond2 = gfc_conv_array_data (cond2);
- cond2 = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
- cond2, null_pointer_node);
- cond = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
- boolean_type_node, cond, cond2);
- }
-
- return cond;
+ return fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
+ orig_decl, null_pointer_node);
}
@@ -224,7 +207,8 @@ gfc_omp_privatize_by_reference (const_tree decl)
return false;
}
-/* True if OpenMP sharing attribute of DECL is predetermined. */
+/* OMP_CLAUSE_DEFAULT_UNSPECIFIED unless OpenMP sharing attribute
+ of DECL is predetermined. */
enum omp_clause_default_kind
gfc_omp_predetermined_sharing (tree decl)
@@ -295,6 +279,28 @@ gfc_omp_predetermined_sharing (tree decl)
return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
}
+
+/* OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED unless OpenMP mapping attribute
+ of DECL is predetermined. */
+
+enum omp_clause_defaultmap_kind
+gfc_omp_predetermined_mapping (tree decl)
+{
+ if (DECL_ARTIFICIAL (decl)
+ && ! GFC_DECL_RESULT (decl)
+ && ! (DECL_LANG_SPECIFIC (decl)
+ && GFC_DECL_SAVED_DESCRIPTOR (decl)))
+ return OMP_CLAUSE_DEFAULTMAP_TO;
+
+ /* These are either array or derived parameters, or vtables. */
+ if (VAR_P (decl) && TREE_READONLY (decl)
+ && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
+ return OMP_CLAUSE_DEFAULTMAP_TO;
+
+ return OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED;
+}
+
+
/* Return decl that should be used when reporting DEFAULT(NONE)
diagnostics. */
@@ -324,6 +330,11 @@ gfc_has_alloc_comps (tree type, tree decl)
return false;
}
+ if (GFC_DESCRIPTOR_TYPE_P (type)
+ && (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER
+ || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER_CONT))
+ return false;
+
if (GFC_DESCRIPTOR_TYPE_P (type) || GFC_ARRAY_TYPE_P (type))
type = gfc_get_element_type (type);
@@ -602,10 +613,21 @@ gfc_omp_clause_default_ctor (tree clause, tree decl, tree outer)
tree type = TREE_TYPE (decl), size, ptr, cond, then_b, else_b;
stmtblock_t block, cond_block;
- gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_PRIVATE
- || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LASTPRIVATE
- || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LINEAR
- || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_REDUCTION);
+ switch (OMP_CLAUSE_CODE (clause))
+ {
+ case OMP_CLAUSE__LOOPTEMP_:
+ case OMP_CLAUSE__REDUCTEMP_:
+ case OMP_CLAUSE__CONDTEMP_:
+ case OMP_CLAUSE__SCANTEMP_:
+ return NULL;
+ case OMP_CLAUSE_PRIVATE:
+ case OMP_CLAUSE_LASTPRIVATE:
+ case OMP_CLAUSE_LINEAR:
+ case OMP_CLAUSE_REDUCTION:
+ break;
+ default:
+ gcc_unreachable ();
+ }
if ((! GFC_DESCRIPTOR_TYPE_P (type)
|| GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
@@ -1287,22 +1309,6 @@ gfc_omp_finish_clause (tree c, gimple_seq *pre_p)
return;
tree orig_decl = decl;
- /* For nonallocatable, nonpointer arrays, a temporary variable is
- generated, but this one is only defined if the variable is present;
- hence, we now set it to NULL to avoid accessing undefined variables.
- We cannot use a temporary variable here as otherwise the replacement
- of the variables in omp-low.c will not work. */
- if (present && GFC_ARRAY_TYPE_P (TREE_TYPE (decl)))
- {
- tree tmp = fold_build2_loc (input_location, MODIFY_EXPR,
- void_type_node, decl, null_pointer_node);
- tree cond = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
- boolean_type_node, present);
- tmp = build3_loc (input_location, COND_EXPR, void_type_node,
- cond, tmp, NULL_TREE);
- gimplify_and_add (tmp, pre_p);
- }
-
c4 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
OMP_CLAUSE_SET_MAP_KIND (c4, GOMP_MAP_POINTER);
OMP_CLAUSE_DECL (c4) = decl;
@@ -1683,6 +1689,10 @@ gfc_trans_omp_variable_list (enum omp_clause_code code,
tree node = build_omp_clause (input_location, code);
OMP_CLAUSE_DECL (node) = t;
list = gfc_trans_add_clause (node, list);
+
+ if (code == OMP_CLAUSE_LASTPRIVATE
+ && namelist->u.lastprivate_conditional)
+ OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (node) = 1;
}
}
return list;
@@ -2097,10 +2107,11 @@ static vec<tree, va_heap, vl_embed> *doacross_steps;
static void
gfc_trans_omp_array_section (stmtblock_t *block, gfc_omp_namelist *n,
tree decl, bool element, gomp_map_kind ptr_kind,
- tree node, tree &node2, tree &node3, tree &node4)
+ tree &node, tree &node2, tree &node3, tree &node4)
{
gfc_se se;
tree ptr, ptr2;
+ tree elemsz = NULL_TREE;
gfc_init_se (&se, NULL);
@@ -2109,7 +2120,8 @@ gfc_trans_omp_array_section (stmtblock_t *block, gfc_omp_namelist *n,
gfc_conv_expr_reference (&se, n->expr);
gfc_add_block_to_block (block, &se.pre);
ptr = se.expr;
- OMP_CLAUSE_SIZE (node) = TYPE_SIZE_UNIT (TREE_TYPE (ptr));
+ OMP_CLAUSE_SIZE (node) = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ptr)));
+ elemsz = OMP_CLAUSE_SIZE (node);
}
else
{
@@ -2119,14 +2131,15 @@ gfc_trans_omp_array_section (stmtblock_t *block, gfc_omp_namelist *n,
gfc_add_block_to_block (block, &se.pre);
OMP_CLAUSE_SIZE (node) = gfc_full_array_size (block, se.expr,
GFC_TYPE_ARRAY_RANK (type));
- tree elemsz = TYPE_SIZE_UNIT (gfc_get_element_type (type));
+ elemsz = TYPE_SIZE_UNIT (gfc_get_element_type (type));
elemsz = fold_convert (gfc_array_index_type, elemsz);
OMP_CLAUSE_SIZE (node) = fold_build2 (MULT_EXPR, gfc_array_index_type,
OMP_CLAUSE_SIZE (node), elemsz);
}
- gfc_add_block_to_block (block, &se.post);
+ gcc_assert (se.post.head == NULL_TREE);
ptr = fold_convert (build_pointer_type (char_type_node), ptr);
OMP_CLAUSE_DECL (node) = build_fold_indirect_ref (ptr);
+ ptr = fold_convert (ptrdiff_type_node, ptr);
if (POINTER_TYPE_P (TREE_TYPE (decl))
&& GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (decl)))
@@ -2139,28 +2152,71 @@ gfc_trans_omp_array_section (stmtblock_t *block, gfc_omp_namelist *n,
OMP_CLAUSE_SIZE (node4) = size_int (0);
decl = build_fold_indirect_ref (decl);
}
- ptr = fold_convert (sizetype, ptr);
+ else if (ptr_kind == GOMP_MAP_ALWAYS_POINTER
+ && n->expr->ts.type == BT_CHARACTER
+ && n->expr->ts.deferred)
+ {
+ gomp_map_kind map_kind;
+ if (GOMP_MAP_COPY_TO_P (OMP_CLAUSE_MAP_KIND (node)))
+ map_kind = GOMP_MAP_TO;
+ else if (OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_RELEASE
+ || OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_DELETE)
+ map_kind = OMP_CLAUSE_MAP_KIND (node);
+ else
+ map_kind = GOMP_MAP_ALLOC;
+ gcc_assert (se.string_length);
+ node4 = build_omp_clause (input_location, OMP_CLAUSE_MAP);
+ OMP_CLAUSE_SET_MAP_KIND (node4, map_kind);
+ OMP_CLAUSE_DECL (node4) = se.string_length;
+ OMP_CLAUSE_SIZE (node4) = TYPE_SIZE_UNIT (gfc_charlen_type_node);
+ }
if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
{
+ tree desc_node;
tree type = TREE_TYPE (decl);
ptr2 = gfc_conv_descriptor_data_get (decl);
- node2 = build_omp_clause (input_location,
- OMP_CLAUSE_MAP);
- OMP_CLAUSE_SET_MAP_KIND (node2, GOMP_MAP_TO_PSET);
- OMP_CLAUSE_DECL (node2) = decl;
- OMP_CLAUSE_SIZE (node2) = TYPE_SIZE_UNIT (type);
+ desc_node = build_omp_clause (input_location, OMP_CLAUSE_MAP);
+ OMP_CLAUSE_DECL (desc_node) = decl;
+ OMP_CLAUSE_SIZE (desc_node) = TYPE_SIZE_UNIT (type);
+ if (ptr_kind == GOMP_MAP_ALWAYS_POINTER)
+ {
+ OMP_CLAUSE_SET_MAP_KIND (desc_node, GOMP_MAP_TO);
+ node2 = node;
+ node = desc_node; /* Needs to come first. */
+ }
+ else
+ {
+ OMP_CLAUSE_SET_MAP_KIND (desc_node, GOMP_MAP_TO_PSET);
+ node2 = desc_node;
+ }
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);
+ /* This purposely does not include GOMP_MAP_ALWAYS_POINTER. The extra
+ cast prevents gimplify.c from recognising it as being part of the
+ struct – and adding an 'alloc: for the 'desc.data' pointer, which
+ would break as the 'desc' (the descriptor) is also mapped
+ (see node4 above). */
if (ptr_kind == GOMP_MAP_ATTACH_DETACH)
STRIP_NOPS (OMP_CLAUSE_DECL (node3));
}
else
{
if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
- ptr2 = build_fold_addr_expr (decl);
+ {
+ tree offset;
+ ptr2 = build_fold_addr_expr (decl);
+ offset = fold_build2 (MINUS_EXPR, ptrdiff_type_node, ptr,
+ fold_convert (ptrdiff_type_node, ptr2));
+ offset = build2 (TRUNC_DIV_EXPR, ptrdiff_type_node,
+ offset, fold_convert (ptrdiff_type_node, elemsz));
+ offset = build4_loc (input_location, ARRAY_REF,
+ TREE_TYPE (TREE_TYPE (decl)),
+ decl, offset, NULL_TREE, NULL_TREE);
+ OMP_CLAUSE_DECL (node) = offset;
+ }
else
{
gcc_assert (POINTER_TYPE_P (TREE_TYPE (decl)));
@@ -2171,14 +2227,15 @@ gfc_trans_omp_array_section (stmtblock_t *block, gfc_omp_namelist *n,
OMP_CLAUSE_SET_MAP_KIND (node3, ptr_kind);
OMP_CLAUSE_DECL (node3) = decl;
}
- ptr2 = fold_convert (sizetype, ptr2);
- OMP_CLAUSE_SIZE (node3)
- = fold_build2 (MINUS_EXPR, sizetype, ptr, ptr2);
+ ptr2 = fold_convert (ptrdiff_type_node, ptr2);
+ OMP_CLAUSE_SIZE (node3) = fold_build2 (MINUS_EXPR, ptrdiff_type_node,
+ ptr, ptr2);
}
static tree
gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
- locus where, bool declare_simd = false)
+ locus where, bool declare_simd = false,
+ bool openacc = false)
{
tree omp_clauses = NULL_TREE, chunk_size, c;
int list, ifc;
@@ -2233,6 +2290,9 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
case OMP_LIST_IS_DEVICE_PTR:
clause_code = OMP_CLAUSE_IS_DEVICE_PTR;
goto add_clause;
+ case OMP_LIST_NONTEMPORAL:
+ clause_code = OMP_CLAUSE_NONTEMPORAL;
+ goto add_clause;
add_clause:
omp_clauses
@@ -2493,6 +2553,67 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
tree node2 = NULL_TREE;
tree node3 = NULL_TREE;
tree node4 = NULL_TREE;
+
+ switch (n->u.map_op)
+ {
+ case OMP_MAP_ALLOC:
+ OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALLOC);
+ break;
+ case OMP_MAP_IF_PRESENT:
+ OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_IF_PRESENT);
+ break;
+ case OMP_MAP_ATTACH:
+ OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ATTACH);
+ break;
+ case OMP_MAP_TO:
+ OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_TO);
+ break;
+ case OMP_MAP_FROM:
+ OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FROM);
+ break;
+ case OMP_MAP_TOFROM:
+ OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_TOFROM);
+ break;
+ case OMP_MAP_ALWAYS_TO:
+ OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALWAYS_TO);
+ break;
+ case OMP_MAP_ALWAYS_FROM:
+ OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALWAYS_FROM);
+ break;
+ case OMP_MAP_ALWAYS_TOFROM:
+ OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALWAYS_TOFROM);
+ break;
+ case OMP_MAP_RELEASE:
+ OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_RELEASE);
+ break;
+ case OMP_MAP_DELETE:
+ OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_DELETE);
+ break;
+ case OMP_MAP_DETACH:
+ OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_DETACH);
+ break;
+ case OMP_MAP_FORCE_ALLOC:
+ OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_ALLOC);
+ break;
+ case OMP_MAP_FORCE_TO:
+ OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_TO);
+ break;
+ case OMP_MAP_FORCE_FROM:
+ OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_FROM);
+ break;
+ case OMP_MAP_FORCE_TOFROM:
+ OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_TOFROM);
+ break;
+ case OMP_MAP_FORCE_PRESENT:
+ OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_PRESENT);
+ break;
+ case OMP_MAP_FORCE_DEVICEPTR:
+ OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_DEVICEPTR);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
tree decl = gfc_trans_omp_variable (n->sym, false);
if (DECL_P (decl))
TREE_ADDRESSABLE (decl) = 1;
@@ -2501,7 +2622,7 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
&& n->expr->ref->u.ar.type == AR_FULL))
{
tree present = gfc_omp_check_optional_argument (decl, true);
- if (n->sym->ts.type == BT_CLASS)
+ if (openacc && n->sym->ts.type == BT_CLASS)
{
tree type = TREE_TYPE (decl);
if (n->sym->attr.optional)
@@ -2582,9 +2703,7 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
decl = build_fold_indirect_ref (decl);
}
}
- if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl))
- && n->u.map_op != OMP_MAP_ATTACH
- && n->u.map_op != OMP_MAP_DETACH)
+ if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
{
tree type = TREE_TYPE (decl);
tree ptr = gfc_conv_descriptor_data_get (decl);
@@ -2602,7 +2721,6 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
OMP_CLAUSE_SIZE (node2) = TYPE_SIZE_UNIT (type);
node3 = build_omp_clause (input_location,
OMP_CLAUSE_MAP);
- OMP_CLAUSE_SET_MAP_KIND (node3, GOMP_MAP_POINTER);
if (present)
{
ptr = gfc_conv_descriptor_data_get (decl);
@@ -2616,6 +2734,33 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
OMP_CLAUSE_DECL (node3)
= gfc_conv_descriptor_data_get (decl);
OMP_CLAUSE_SIZE (node3) = size_int (0);
+ if (n->u.map_op == OMP_MAP_ATTACH)
+ {
+ /* Standalone attach clauses used with arrays with
+ descriptors must copy the descriptor to the target,
+ else they won't have anything to perform the
+ attachment onto (see OpenACC 2.6, "2.6.3. Data
+ Structures with Pointers"). */
+ OMP_CLAUSE_SET_MAP_KIND (node3, GOMP_MAP_ATTACH);
+ /* We don't want to map PTR at all in this case, so
+ delete its node and shuffle the others down. */
+ node = node2;
+ node2 = node3;
+ node3 = NULL;
+ goto finalize_map_clause;
+ }
+ else if (n->u.map_op == OMP_MAP_DETACH)
+ {
+ OMP_CLAUSE_SET_MAP_KIND (node3, GOMP_MAP_DETACH);
+ /* Similarly to above, we don't want to unmap PTR
+ here. */
+ node = node2;
+ node2 = node3;
+ node3 = NULL;
+ goto finalize_map_clause;
+ }
+ else
+ OMP_CLAUSE_SET_MAP_KIND (node3, GOMP_MAP_POINTER);
/* We have to check for n->sym->attr.dimension because
of scalar coarrays. */
@@ -2729,8 +2874,42 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
/* Last component is a scalar. */
gfc_conv_expr (&se, n->expr);
gfc_add_block_to_block (block, &se.pre);
- OMP_CLAUSE_DECL (node) = se.expr;
+ /* For BT_CHARACTER a pointer is returned. */
+ OMP_CLAUSE_DECL (node)
+ = POINTER_TYPE_P (TREE_TYPE (se.expr))
+ ? build_fold_indirect_ref (se.expr) : se.expr;
gfc_add_block_to_block (block, &se.post);
+ if (sym_attr.pointer || sym_attr.allocatable)
+ {
+ node2 = build_omp_clause (input_location,
+ OMP_CLAUSE_MAP);
+ OMP_CLAUSE_SET_MAP_KIND (node2,
+ openacc
+ ? GOMP_MAP_ATTACH_DETACH
+ : GOMP_MAP_ALWAYS_POINTER);
+ OMP_CLAUSE_DECL (node2)
+ = POINTER_TYPE_P (TREE_TYPE (se.expr))
+ ? se.expr : gfc_build_addr_expr (NULL, se.expr);
+ OMP_CLAUSE_SIZE (node2) = size_int (0);
+ if (!openacc
+ && n->expr->ts.type == BT_CHARACTER
+ && n->expr->ts.deferred)
+ {
+ gcc_assert (se.string_length);
+ tree tmp = gfc_get_char_type (n->expr->ts.kind);
+ OMP_CLAUSE_SIZE (node)
+ = fold_build2 (MULT_EXPR, size_type_node,
+ fold_convert (size_type_node,
+ se.string_length),
+ TYPE_SIZE_UNIT (tmp));
+ node3 = build_omp_clause (input_location,
+ OMP_CLAUSE_MAP);
+ OMP_CLAUSE_SET_MAP_KIND (node3, GOMP_MAP_TO);
+ OMP_CLAUSE_DECL (node3) = se.string_length;
+ OMP_CLAUSE_SIZE (node3)
+ = TYPE_SIZE_UNIT (gfc_charlen_type_node);
+ }
+ }
goto finalize_map_clause;
}
@@ -2757,7 +2936,7 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
if (lastcomp->u.c.component->ts.type == BT_DERIVED
|| lastcomp->u.c.component->ts.type == BT_CLASS)
{
- if (sym_attr.allocatable || sym_attr.pointer)
+ if (sym_attr.pointer || (openacc && sym_attr.allocatable))
{
tree data, size;
@@ -2778,15 +2957,17 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
node2 = build_omp_clause (input_location,
OMP_CLAUSE_MAP);
OMP_CLAUSE_SET_MAP_KIND (node2,
- GOMP_MAP_ATTACH_DETACH);
+ openacc
+ ? GOMP_MAP_ATTACH_DETACH
+ : GOMP_MAP_ALWAYS_POINTER);
OMP_CLAUSE_DECL (node2) = data;
OMP_CLAUSE_SIZE (node2) = size_int (0);
}
else
{
- OMP_CLAUSE_DECL (node) = decl;
+ OMP_CLAUSE_DECL (node) = inner;
OMP_CLAUSE_SIZE (node)
- = TYPE_SIZE_UNIT (TREE_TYPE (decl));
+ = TYPE_SIZE_UNIT (TREE_TYPE (inner));
}
}
else if (lastcomp->next
@@ -2805,32 +2986,82 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (inner)))
{
+ gomp_map_kind map_kind;
+ tree desc_node;
tree type = TREE_TYPE (inner);
tree ptr = gfc_conv_descriptor_data_get (inner);
ptr = build_fold_indirect_ref (ptr);
OMP_CLAUSE_DECL (node) = ptr;
- node2 = build_omp_clause (input_location,
- OMP_CLAUSE_MAP);
- OMP_CLAUSE_SET_MAP_KIND (node2, GOMP_MAP_TO_PSET);
- OMP_CLAUSE_DECL (node2) = inner;
- OMP_CLAUSE_SIZE (node2) = TYPE_SIZE_UNIT (type);
- node3 = build_omp_clause (input_location,
- OMP_CLAUSE_MAP);
- OMP_CLAUSE_SET_MAP_KIND (node3,
- GOMP_MAP_ATTACH_DETACH);
- OMP_CLAUSE_DECL (node3)
- = gfc_conv_descriptor_data_get (inner);
- STRIP_NOPS (OMP_CLAUSE_DECL (node3));
- OMP_CLAUSE_SIZE (node3) = size_int (0);
int rank = GFC_TYPE_ARRAY_RANK (type);
OMP_CLAUSE_SIZE (node)
= gfc_full_array_size (block, inner, rank);
tree elemsz
= TYPE_SIZE_UNIT (gfc_get_element_type (type));
+ if (GOMP_MAP_COPY_TO_P (OMP_CLAUSE_MAP_KIND (node)))
+ map_kind = GOMP_MAP_TO;
+ else if (n->u.map_op == OMP_MAP_RELEASE
+ || n->u.map_op == OMP_MAP_DELETE)
+ map_kind = OMP_CLAUSE_MAP_KIND (node);
+ else
+ map_kind = GOMP_MAP_ALLOC;
+ if (!openacc
+ && n->expr->ts.type == BT_CHARACTER
+ && n->expr->ts.deferred)
+ {
+ gcc_assert (se.string_length);
+ tree len = fold_convert (size_type_node,
+ se.string_length);
+ elemsz = gfc_get_char_type (n->expr->ts.kind);
+ elemsz = TYPE_SIZE_UNIT (elemsz);
+ elemsz = fold_build2 (MULT_EXPR, size_type_node,
+ len, elemsz);
+ node4 = build_omp_clause (input_location,
+ OMP_CLAUSE_MAP);
+ OMP_CLAUSE_SET_MAP_KIND (node4, map_kind);
+ OMP_CLAUSE_DECL (node4) = se.string_length;
+ OMP_CLAUSE_SIZE (node4)
+ = TYPE_SIZE_UNIT (gfc_charlen_type_node);
+ }
elemsz = fold_convert (gfc_array_index_type, elemsz);
OMP_CLAUSE_SIZE (node)
= fold_build2 (MULT_EXPR, gfc_array_index_type,
OMP_CLAUSE_SIZE (node), elemsz);
+ desc_node = build_omp_clause (input_location,
+ OMP_CLAUSE_MAP);
+ if (openacc)
+ OMP_CLAUSE_SET_MAP_KIND (desc_node,
+ GOMP_MAP_TO_PSET);
+ else
+ OMP_CLAUSE_SET_MAP_KIND (desc_node, map_kind);
+ OMP_CLAUSE_DECL (desc_node) = inner;
+ OMP_CLAUSE_SIZE (desc_node) = TYPE_SIZE_UNIT (type);
+ if (openacc)
+ node2 = desc_node;
+ else
+ {
+ node2 = node;
+ node = desc_node; /* Put first. */
+ }
+ node3 = build_omp_clause (input_location,
+ OMP_CLAUSE_MAP);
+ OMP_CLAUSE_SET_MAP_KIND (node3,
+ openacc
+ ? GOMP_MAP_ATTACH_DETACH
+ : GOMP_MAP_ALWAYS_POINTER);
+ OMP_CLAUSE_DECL (node3)
+ = gfc_conv_descriptor_data_get (inner);
+ /* Similar to gfc_trans_omp_array_section (details
+ there), we add/keep the cast for OpenMP to prevent
+ that an 'alloc:' gets added for node3 ('desc.data')
+ as that is part of the whole descriptor (node3).
+ TODO: Remove once the ME handles this properly. */
+ if (!openacc)
+ OMP_CLAUSE_DECL (node3)
+ = fold_convert (TREE_TYPE (TREE_OPERAND(ptr, 0)),
+ OMP_CLAUSE_DECL (node3));
+ else
+ STRIP_NOPS (OMP_CLAUSE_DECL (node3));
+ OMP_CLAUSE_SIZE (node3) = size_int (0);
}
else
OMP_CLAUSE_DECL (node) = inner;
@@ -2842,9 +3073,11 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
&& lastcomp->next->type == REF_ARRAY
&& lastcomp->next->u.ar.type == AR_ELEMENT);
+ gomp_map_kind kind = (openacc ? GOMP_MAP_ATTACH_DETACH
+ : GOMP_MAP_ALWAYS_POINTER);
gfc_trans_omp_array_section (block, n, inner, element,
- GOMP_MAP_ATTACH_DETACH,
- node, node2, node3, node4);
+ kind, node, node2, node3,
+ node4);
}
}
else /* An array element or array section. */
@@ -2856,65 +3089,7 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
}
finalize_map_clause:
- switch (n->u.map_op)
- {
- case OMP_MAP_ALLOC:
- OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALLOC);
- break;
- case OMP_MAP_IF_PRESENT:
- OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_IF_PRESENT);
- break;
- case OMP_MAP_ATTACH:
- OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ATTACH);
- break;
- case OMP_MAP_TO:
- OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_TO);
- break;
- case OMP_MAP_FROM:
- OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FROM);
- break;
- case OMP_MAP_TOFROM:
- OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_TOFROM);
- break;
- case OMP_MAP_ALWAYS_TO:
- OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALWAYS_TO);
- break;
- case OMP_MAP_ALWAYS_FROM:
- OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALWAYS_FROM);
- break;
- case OMP_MAP_ALWAYS_TOFROM:
- OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALWAYS_TOFROM);
- break;
- case OMP_MAP_RELEASE:
- OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_RELEASE);
- break;
- case OMP_MAP_DELETE:
- OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_DELETE);
- break;
- case OMP_MAP_DETACH:
- OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_DETACH);
- break;
- case OMP_MAP_FORCE_ALLOC:
- OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_ALLOC);
- break;
- case OMP_MAP_FORCE_TO:
- OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_TO);
- break;
- case OMP_MAP_FORCE_FROM:
- OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_FROM);
- break;
- case OMP_MAP_FORCE_TOFROM:
- OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_TOFROM);
- break;
- case OMP_MAP_FORCE_PRESENT:
- OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_PRESENT);
- break;
- case OMP_MAP_FORCE_DEVICEPTR:
- OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_DEVICEPTR);
- break;
- default:
- gcc_unreachable ();
- }
+
omp_clauses = gfc_trans_add_clause (node, omp_clauses);
if (node2)
omp_clauses = gfc_trans_add_clause (node2, omp_clauses);
@@ -3054,9 +3229,15 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_IF);
switch (ifc)
{
+ case OMP_IF_CANCEL:
+ OMP_CLAUSE_IF_MODIFIER (c) = VOID_CST;
+ break;
case OMP_IF_PARALLEL:
OMP_CLAUSE_IF_MODIFIER (c) = OMP_PARALLEL;
break;
+ case OMP_IF_SIMD:
+ OMP_CLAUSE_IF_MODIFIER (c) = OMP_SIMD;
+ break;
case OMP_IF_TASK:
OMP_CLAUSE_IF_MODIFIER (c) = OMP_TASK;
break;
@@ -3203,6 +3384,12 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
omp_clauses = gfc_trans_add_clause (c, omp_clauses);
}
+ if (clauses->order_concurrent)
+ {
+ c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_ORDER);
+ omp_clauses = gfc_trans_add_clause (c, omp_clauses);
+ }
+
if (clauses->untied)
{
c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_UNTIED);
@@ -3666,7 +3853,7 @@ gfc_trans_oacc_construct (gfc_code *code)
gfc_start_block (&block);
oacc_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
- code->loc);
+ code->loc, false, true);
stmt = gfc_trans_omp_code (code->block->next, true);
stmt = build2_loc (input_location, construct_code, void_type_node, stmt,
oacc_clauses);
@@ -3702,7 +3889,7 @@ gfc_trans_oacc_executable_directive (gfc_code *code)
gfc_start_block (&block);
oacc_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
- code->loc);
+ code->loc, false, true);
stmt = build1_loc (input_location, construct_code, void_type_node,
oacc_clauses);
gfc_add_expr_to_block (&block, stmt);
@@ -3764,9 +3951,13 @@ gfc_trans_omp_atomic (gfc_code *code)
enum tree_code op = ERROR_MARK;
enum tree_code aop = OMP_ATOMIC;
bool var_on_left = false;
- enum omp_memory_order mo
- = ((atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_SEQ_CST)
- ? OMP_MEMORY_ORDER_SEQ_CST : OMP_MEMORY_ORDER_RELAXED);
+ enum omp_memory_order mo;
+ if (atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_SEQ_CST)
+ mo = OMP_MEMORY_ORDER_SEQ_CST;
+ else if (atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_ACQ_REL)
+ mo = OMP_MEMORY_ORDER_ACQ_REL;
+ else
+ mo = OMP_MEMORY_ORDER_RELAXED;
code = code->block->next;
gcc_assert (code->op == EXEC_ASSIGN);
@@ -4050,13 +4241,18 @@ gfc_trans_omp_cancel (gfc_code *code)
default: gcc_unreachable ();
}
gfc_start_block (&block);
- if (code->ext.omp_clauses->if_expr)
+ if (code->ext.omp_clauses->if_expr
+ || code->ext.omp_clauses->if_exprs[OMP_IF_CANCEL])
{
gfc_se se;
tree if_var;
+ gcc_assert ((code->ext.omp_clauses->if_expr == NULL)
+ ^ (code->ext.omp_clauses->if_exprs[OMP_IF_CANCEL] == NULL));
gfc_init_se (&se, NULL);
- gfc_conv_expr (&se, code->ext.omp_clauses->if_expr);
+ gfc_conv_expr (&se, code->ext.omp_clauses->if_expr != NULL
+ ? code->ext.omp_clauses->if_expr
+ : code->ext.omp_clauses->if_exprs[OMP_IF_CANCEL]);
gfc_add_block_to_block (&block, &se.pre);
if_var = gfc_evaluate_now (se.expr, &block);
gfc_add_block_to_block (&block, &se.post);
@@ -4095,12 +4291,20 @@ gfc_trans_omp_cancellation_point (gfc_code *code)
static tree
gfc_trans_omp_critical (gfc_code *code)
{
- tree name = NULL_TREE, stmt;
- if (code->ext.omp_clauses != NULL)
+ stmtblock_t block;
+ tree stmt, name = NULL_TREE;
+ if (code->ext.omp_clauses->critical_name != NULL)
name = get_identifier (code->ext.omp_clauses->critical_name);
- stmt = gfc_trans_code (code->block->next);
- return build3_loc (input_location, OMP_CRITICAL, void_type_node, stmt,
- NULL_TREE, name);
+ gfc_start_block (&block);
+ stmt = make_node (OMP_CRITICAL);
+ TREE_TYPE (stmt) = void_type_node;
+ OMP_CRITICAL_BODY (stmt) = gfc_trans_code (code->block->next);
+ OMP_CRITICAL_NAME (stmt) = name;
+ OMP_CRITICAL_CLAUSES (stmt) = gfc_trans_omp_clauses (&block,
+ code->ext.omp_clauses,
+ code->loc);
+ gfc_add_expr_to_block (&block, stmt);
+ return gfc_finish_block (&block);
}
typedef struct dovar_init_d {
@@ -4296,23 +4500,22 @@ gfc_trans_omp_do (gfc_code *code, gfc_exec_op op, stmtblock_t *pblock,
break;
}
}
- if (!dovar_found)
+ if (!dovar_found && op == EXEC_OMP_SIMD)
{
- if (op == EXEC_OMP_SIMD)
+ if (collapse == 1)
{
- if (collapse == 1)
- {
- tmp = build_omp_clause (input_location, OMP_CLAUSE_LINEAR);
- OMP_CLAUSE_LINEAR_STEP (tmp) = step;
- OMP_CLAUSE_LINEAR_NO_COPYIN (tmp) = 1;
- }
- else
- tmp = build_omp_clause (input_location, OMP_CLAUSE_LASTPRIVATE);
- if (!simple)
- dovar_found = 2;
+ tmp = build_omp_clause (input_location, OMP_CLAUSE_LINEAR);
+ OMP_CLAUSE_LINEAR_STEP (tmp) = step;
+ OMP_CLAUSE_LINEAR_NO_COPYIN (tmp) = 1;
+ OMP_CLAUSE_DECL (tmp) = dovar_decl;
+ omp_clauses = gfc_trans_add_clause (tmp, omp_clauses);
}
- else
- tmp = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE);
+ if (!simple)
+ dovar_found = 2;
+ }
+ else if (!dovar_found && !simple)
+ {
+ tmp = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE);
OMP_CLAUSE_DECL (tmp) = dovar_decl;
omp_clauses = gfc_trans_add_clause (tmp, omp_clauses);
}
@@ -4370,6 +4573,8 @@ gfc_trans_omp_do (gfc_code *code, gfc_exec_op op, stmtblock_t *pblock,
{
tree l = build_omp_clause (input_location,
OMP_CLAUSE_LASTPRIVATE);
+ if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
+ OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (l) = 1;
OMP_CLAUSE_DECL (l) = dovar_decl;
OMP_CLAUSE_CHAIN (l) = omp_clauses;
OMP_CLAUSE_LASTPRIVATE_STMT (l) = tmp;
@@ -4528,7 +4733,7 @@ gfc_trans_oacc_combined_directive (gfc_code *code)
if (construct_code == OACC_KERNELS)
construct_clauses.lists[OMP_LIST_REDUCTION] = NULL;
oacc_clauses = gfc_trans_omp_clauses (&block, &construct_clauses,
- code->loc);
+ code->loc, false, true);
}
if (!loop_clauses.seq)
pblock = &block;
@@ -4759,7 +4964,7 @@ gfc_split_omp_clauses (gfc_code *code,
clausesa[GFC_OMP_SPLIT_TARGET].if_exprs[OMP_IF_TARGET]
= code->ext.omp_clauses->if_exprs[OMP_IF_TARGET];
/* And this is copied to all. */
- clausesa[GFC_OMP_SPLIT_PARALLEL].if_expr
+ clausesa[GFC_OMP_SPLIT_TARGET].if_expr
= code->ext.omp_clauses->if_expr;
}
if (mask & GFC_OMP_MASK_TEAMS)
@@ -4786,6 +4991,8 @@ gfc_split_omp_clauses (gfc_code *code,
/* Duplicate collapse. */
clausesa[GFC_OMP_SPLIT_DISTRIBUTE].collapse
= code->ext.omp_clauses->collapse;
+ clausesa[GFC_OMP_SPLIT_DISTRIBUTE].order_concurrent
+ = code->ext.omp_clauses->order_concurrent;
}
if (mask & GFC_OMP_MASK_PARALLEL)
{
@@ -4831,6 +5038,8 @@ gfc_split_omp_clauses (gfc_code *code,
/* Duplicate collapse. */
clausesa[GFC_OMP_SPLIT_DO].collapse
= code->ext.omp_clauses->collapse;
+ clausesa[GFC_OMP_SPLIT_DO].order_concurrent
+ = code->ext.omp_clauses->order_concurrent;
}
if (mask & GFC_OMP_MASK_SIMD)
{
@@ -4843,6 +5052,13 @@ gfc_split_omp_clauses (gfc_code *code,
/* Duplicate collapse. */
clausesa[GFC_OMP_SPLIT_SIMD].collapse
= code->ext.omp_clauses->collapse;
+ clausesa[GFC_OMP_SPLIT_SIMD].if_exprs[OMP_IF_SIMD]
+ = code->ext.omp_clauses->if_exprs[OMP_IF_SIMD];
+ clausesa[GFC_OMP_SPLIT_SIMD].order_concurrent
+ = code->ext.omp_clauses->order_concurrent;
+ /* And this is copied to all. */
+ clausesa[GFC_OMP_SPLIT_SIMD].if_expr
+ = code->ext.omp_clauses->if_expr;
}
if (mask & GFC_OMP_MASK_TASKLOOP)
{
@@ -5361,7 +5577,7 @@ gfc_trans_omp_target (gfc_code *code)
pushlevel ();
gfc_start_block (&iblock);
tree inner_clauses
- = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_PARALLEL],
+ = gfc_trans_omp_clauses (&iblock, &clausesa[GFC_OMP_SPLIT_PARALLEL],
code->loc);
stmt = gfc_trans_omp_code (code->block->next, true);
stmt = build2_loc (input_location, OMP_PARALLEL, void_type_node, stmt,
@@ -5427,6 +5643,7 @@ gfc_trans_omp_target (gfc_code *code)
omp_clauses);
if (code->op != EXEC_OMP_TARGET)
OMP_TARGET_COMBINED (stmt) = 1;
+ cfun->has_omp_target = true;
}
gfc_add_expr_to_block (&block, stmt);
return gfc_finish_block (&block);
@@ -5705,7 +5922,7 @@ gfc_trans_oacc_declare (gfc_code *code)
gfc_start_block (&block);
oacc_clauses = gfc_trans_omp_clauses (&block, code->ext.oacc_declare->clauses,
- code->loc);
+ code->loc, false, true);
stmt = gfc_trans_omp_code (code->block->next, true);
stmt = build2_loc (input_location, construct_code, void_type_node, stmt,
oacc_clauses);