diff options
author | Kwok Cheung Yeung <kcy@codesourcery.com> | 2021-01-16 12:58:13 -0800 |
---|---|---|
committer | Kwok Cheung Yeung <kcy@codesourcery.com> | 2021-01-16 12:58:13 -0800 |
commit | a6d22fb21c6f1ad7e8b6b722bfc0e7e11f50cb92 (patch) | |
tree | 7d7d0ac7d3170bea065caea25f6942a864b9a73b /gcc | |
parent | 5e5d56919dd544a530445cfd8c3f6264f3d706f3 (diff) | |
download | gcc-a6d22fb21c6f1ad7e8b6b722bfc0e7e11f50cb92.zip gcc-a6d22fb21c6f1ad7e8b6b722bfc0e7e11f50cb92.tar.gz gcc-a6d22fb21c6f1ad7e8b6b722bfc0e7e11f50cb92.tar.bz2 |
openmp: Add support for the OpenMP 5.0 task detach clause
2021-01-16 Kwok Cheung Yeung <kcy@codesourcery.com>
gcc/
* builtin-types.def
(BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_BOOL_UINT_PTR_INT): Rename
to...
(BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_BOOL_UINT_PTR_INT_PTR):
...this. Add extra argument.
* gimplify.c (omp_default_clause): Ensure that event handle is
firstprivate in a task region.
(gimplify_scan_omp_clauses): Handle OMP_CLAUSE_DETACH.
(gimplify_adjust_omp_clauses): Likewise.
* omp-builtins.def (BUILT_IN_GOMP_TASK): Change function type to
BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_BOOL_UINT_PTR_INT_PTR.
* omp-expand.c (expand_task_call): Add GOMP_TASK_FLAG_DETACH to flags
if detach clause specified. Add detach argument when generating
call to GOMP_task.
* omp-low.c (scan_sharing_clauses): Setup data environment for detach
clause.
(finish_taskreg_scan): Move field for variable containing the event
handle to the front of the struct.
* tree-core.h (enum omp_clause_code): Add OMP_CLAUSE_DETACH. Fix
ordering.
* tree-nested.c (convert_nonlocal_omp_clauses): Handle
OMP_CLAUSE_DETACH clause.
(convert_local_omp_clauses): Handle OMP_CLAUSE_DETACH clause.
* tree-pretty-print.c (dump_omp_clause): Handle OMP_CLAUSE_DETACH.
* tree.c (omp_clause_num_ops): Add entry for OMP_CLAUSE_DETACH.
Fix ordering.
(omp_clause_code_name): Add entry for OMP_CLAUSE_DETACH. Fix
ordering.
(walk_tree_1): Handle OMP_CLAUSE_DETACH.
gcc/c-family/
* c-pragma.h (pragma_omp_clause): Add PRAGMA_OMP_CLAUSE_DETACH.
Redefine PRAGMA_OACC_CLAUSE_DETACH.
gcc/c/
* c-parser.c (c_parser_omp_clause_detach): New.
(c_parser_omp_all_clauses): Handle PRAGMA_OMP_CLAUSE_DETACH clause.
(OMP_TASK_CLAUSE_MASK): Add mask for PRAGMA_OMP_CLAUSE_DETACH.
* c-typeck.c (c_finish_omp_clauses): Handle PRAGMA_OMP_CLAUSE_DETACH
clause. Prevent use of detach with mergeable and overriding the
data sharing mode of the event handle.
gcc/cp/
* parser.c (cp_parser_omp_clause_detach): New.
(cp_parser_omp_all_clauses): Handle PRAGMA_OMP_CLAUSE_DETACH.
(OMP_TASK_CLAUSE_MASK): Add mask for PRAGMA_OMP_CLAUSE_DETACH.
* pt.c (tsubst_omp_clauses): Handle OMP_CLAUSE_DETACH clause.
* semantics.c (finish_omp_clauses): Handle OMP_CLAUSE_DETACH clause.
Prevent use of detach with mergeable and overriding the data sharing
mode of the event handle.
gcc/fortran/
* dump-parse-tree.c (show_omp_clauses): Handle detach clause.
* frontend-passes.c (gfc_code_walker): Walk detach expression.
* gfortran.h (struct gfc_omp_clauses): Add detach field.
(gfc_c_intptr_kind): New.
* openmp.c (gfc_free_omp_clauses): Free detach clause.
(gfc_match_omp_detach): New.
(enum omp_mask1): Add OMP_CLAUSE_DETACH.
(enum omp_mask2): Remove OMP_CLAUSE_DETACH.
(gfc_match_omp_clauses): Handle OMP_CLAUSE_DETACH for OpenMP.
(OMP_TASK_CLAUSES): Add OMP_CLAUSE_DETACH.
(resolve_omp_clauses): Prevent use of detach with mergeable and
overriding the data sharing mode of the event handle.
* trans-openmp.c (gfc_trans_omp_clauses): Handle detach clause.
* trans-types.c (gfc_c_intptr_kind): New.
(gfc_init_kinds): Initialize gfc_c_intptr_kind.
* types.def
(BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_BOOL_UINT_PTR_INT): Rename
to...
(BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_BOOL_UINT_PTR_INT_PTR):
...this. Add extra argument.
gcc/testsuite/
* c-c++-common/gomp/task-detach-1.c: New.
* g++.dg/gomp/task-detach-1.C: New.
* gcc.dg/gomp/task-detach-1.c: New.
* gfortran.dg/gomp/task-detach-1.f90: New.
include/
* gomp-constants.h (GOMP_TASK_FLAG_DETACH): New.
libgomp/
* fortran.c (omp_fulfill_event_): New.
* libgomp.h (struct gomp_task): Add detach and completion_sem fields.
(struct gomp_team): Add task_detach_queue and task_detach_count
fields.
* libgomp.map (OMP_5.0.1): Add omp_fulfill_event and omp_fulfill_event_.
* libgomp_g.h (GOMP_task): Add extra argument.
* omp.h.in (enum omp_event_handle_t): New.
(omp_fulfill_event): New.
* omp_lib.f90.in (omp_event_handle_kind): New.
(omp_fulfill_event): New.
* omp_lib.h.in (omp_event_handle_kind): New.
(omp_fulfill_event): Declare.
* priority_queue.c (priority_tree_find): New.
(priority_list_find): New.
(priority_queue_find): New.
* priority_queue.h (priority_queue_predicate): New.
(priority_queue_find): New.
* task.c (gomp_init_task): Initialize detach field.
(task_fulfilled_p): New.
(GOMP_task): Add detach argument. Ignore detach argument if
GOMP_TASK_FLAG_DETACH not set in flags. Initialize completion_sem
field. Copy address of completion_sem into detach argument and
into the start of the data record. Wait for detach event if task
not deferred.
(gomp_barrier_handle_tasks): Queue tasks with unfulfilled events.
Remove completed tasks and requeue dependent tasks.
(omp_fulfill_event): New.
* team.c (gomp_new_team): Initialize task_detach_queue and
task_detach_count fields.
(free_team): Free task_detach_queue field.
* testsuite/libgomp.c-c++-common/task-detach-1.c: New testcase.
* testsuite/libgomp.c-c++-common/task-detach-2.c: New testcase.
* testsuite/libgomp.c-c++-common/task-detach-3.c: New testcase.
* testsuite/libgomp.c-c++-common/task-detach-4.c: New testcase.
* testsuite/libgomp.c-c++-common/task-detach-5.c: New testcase.
* testsuite/libgomp.c-c++-common/task-detach-6.c: New testcase.
* testsuite/libgomp.fortran/task-detach-1.f90: New testcase.
* testsuite/libgomp.fortran/task-detach-2.f90: New testcase.
* testsuite/libgomp.fortran/task-detach-3.f90: New testcase.
* testsuite/libgomp.fortran/task-detach-4.f90: New testcase.
* testsuite/libgomp.fortran/task-detach-5.f90: New testcase.
* testsuite/libgomp.fortran/task-detach-6.f90: New testcase.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/builtin-types.def | 8 | ||||
-rw-r--r-- | gcc/c-family/c-pragma.h | 3 | ||||
-rw-r--r-- | gcc/c/c-parser.c | 57 | ||||
-rw-r--r-- | gcc/c/c-typeck.c | 58 | ||||
-rw-r--r-- | gcc/cp/parser.c | 53 | ||||
-rw-r--r-- | gcc/cp/pt.c | 1 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 61 | ||||
-rw-r--r-- | gcc/fortran/dump-parse-tree.c | 6 | ||||
-rw-r--r-- | gcc/fortran/frontend-passes.c | 1 | ||||
-rw-r--r-- | gcc/fortran/gfortran.h | 2 | ||||
-rw-r--r-- | gcc/fortran/openmp.c | 60 | ||||
-rw-r--r-- | gcc/fortran/trans-openmp.c | 16 | ||||
-rw-r--r-- | gcc/fortran/trans-types.c | 3 | ||||
-rw-r--r-- | gcc/fortran/types.def | 8 | ||||
-rw-r--r-- | gcc/gimplify.c | 14 | ||||
-rw-r--r-- | gcc/omp-builtins.def | 2 | ||||
-rw-r--r-- | gcc/omp-expand.c | 19 | ||||
-rw-r--r-- | gcc/omp-low.c | 47 | ||||
-rw-r--r-- | gcc/testsuite/c-c++-common/gomp/task-detach-1.c | 37 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/gomp/task-detach-1.C | 29 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/gomp/task-detach-1.c | 20 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/gomp/task-detach-1.f90 | 29 | ||||
-rw-r--r-- | gcc/tree-core.h | 29 | ||||
-rw-r--r-- | gcc/tree-nested.c | 2 | ||||
-rw-r--r-- | gcc/tree-pretty-print.c | 6 | ||||
-rw-r--r-- | gcc/tree.c | 15 |
26 files changed, 546 insertions, 40 deletions
diff --git a/gcc/builtin-types.def b/gcc/builtin-types.def index 47abf90..d160826 100644 --- a/gcc/builtin-types.def +++ b/gcc/builtin-types.def @@ -759,10 +759,6 @@ DEF_FUNCTION_TYPE_8 (BT_FN_BOOL_UINT_ULLPTR_LONG_ULL_ULLPTR_ULLPTR_PTR_PTR, BT_BOOL, BT_UINT, BT_PTR_ULONGLONG, BT_LONG, BT_ULONGLONG, BT_PTR_ULONGLONG, BT_PTR_ULONGLONG, BT_PTR, BT_PTR) -DEF_FUNCTION_TYPE_9 (BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_BOOL_UINT_PTR_INT, - BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR, - BT_PTR_FN_VOID_PTR_PTR, BT_LONG, BT_LONG, - BT_BOOL, BT_UINT, BT_PTR, BT_INT) DEF_FUNCTION_TYPE_9 (BT_FN_VOID_INT_OMPFN_SIZE_PTR_PTR_PTR_UINT_PTR_PTR, BT_VOID, BT_INT, BT_PTR_FN_VOID_PTR, BT_SIZE, BT_PTR, BT_PTR, BT_PTR, BT_UINT, BT_PTR, BT_PTR) @@ -770,6 +766,10 @@ DEF_FUNCTION_TYPE_9 (BT_FN_BOOL_LONG_LONG_LONG_LONG_LONG_LONGPTR_LONGPTR_PTR_PTR BT_BOOL, BT_LONG, BT_LONG, BT_LONG, BT_LONG, BT_LONG, BT_PTR_LONG, BT_PTR_LONG, BT_PTR, BT_PTR) +DEF_FUNCTION_TYPE_10 (BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_BOOL_UINT_PTR_INT_PTR, + BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR, + BT_PTR_FN_VOID_PTR_PTR, BT_LONG, BT_LONG, + BT_BOOL, BT_UINT, BT_PTR, BT_INT, BT_PTR) DEF_FUNCTION_TYPE_10 (BT_FN_BOOL_BOOL_ULL_ULL_ULL_LONG_ULL_ULLPTR_ULLPTR_PTR_PTR, BT_BOOL, BT_BOOL, BT_ULONGLONG, BT_ULONGLONG, BT_ULONGLONG, BT_LONG, BT_ULONGLONG, BT_PTR_ULONGLONG, diff --git a/gcc/c-family/c-pragma.h b/gcc/c-family/c-pragma.h index de45203..6c34ffa 100644 --- a/gcc/c-family/c-pragma.h +++ b/gcc/c-family/c-pragma.h @@ -95,6 +95,7 @@ enum pragma_omp_clause { PRAGMA_OMP_CLAUSE_DEFAULT, PRAGMA_OMP_CLAUSE_DEFAULTMAP, PRAGMA_OMP_CLAUSE_DEPEND, + PRAGMA_OMP_CLAUSE_DETACH, PRAGMA_OMP_CLAUSE_DEVICE, PRAGMA_OMP_CLAUSE_DEVICE_TYPE, PRAGMA_OMP_CLAUSE_DIST_SCHEDULE, @@ -151,7 +152,6 @@ enum pragma_omp_clause { PRAGMA_OACC_CLAUSE_COPYOUT, PRAGMA_OACC_CLAUSE_CREATE, PRAGMA_OACC_CLAUSE_DELETE, - PRAGMA_OACC_CLAUSE_DETACH, PRAGMA_OACC_CLAUSE_DEVICEPTR, PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT, PRAGMA_OACC_CLAUSE_FINALIZE, @@ -174,6 +174,7 @@ enum pragma_omp_clause { PRAGMA_OACC_CLAUSE_COPYIN = PRAGMA_OMP_CLAUSE_COPYIN, PRAGMA_OACC_CLAUSE_DEVICE = PRAGMA_OMP_CLAUSE_DEVICE, PRAGMA_OACC_CLAUSE_DEFAULT = PRAGMA_OMP_CLAUSE_DEFAULT, + PRAGMA_OACC_CLAUSE_DETACH = PRAGMA_OMP_CLAUSE_DETACH, PRAGMA_OACC_CLAUSE_FIRSTPRIVATE = PRAGMA_OMP_CLAUSE_FIRSTPRIVATE, PRAGMA_OACC_CLAUSE_IF = PRAGMA_OMP_CLAUSE_IF, PRAGMA_OACC_CLAUSE_PRIVATE = PRAGMA_OMP_CLAUSE_PRIVATE, diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index c77d9fc..a8df208 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -15977,6 +15977,56 @@ c_parser_omp_clause_uniform (c_parser *parser, tree list) return list; } +/* OpenMP 5.0: + detach ( event-handle ) */ + +static tree +c_parser_omp_clause_detach (c_parser *parser, tree list) +{ + matching_parens parens; + location_t clause_loc = c_parser_peek_token (parser)->location; + + if (!parens.require_open (parser)) + return list; + + if (c_parser_next_token_is_not (parser, CPP_NAME) + || c_parser_peek_token (parser)->id_kind != C_ID_ID) + { + c_parser_error (parser, "expected identifier"); + parens.skip_until_found_close (parser); + return list; + } + + tree t = lookup_name (c_parser_peek_token (parser)->value); + if (t == NULL_TREE) + { + undeclared_variable (c_parser_peek_token (parser)->location, + c_parser_peek_token (parser)->value); + parens.skip_until_found_close (parser); + return list; + } + c_parser_consume_token (parser); + + tree type = TYPE_MAIN_VARIANT (TREE_TYPE (t)); + if (!INTEGRAL_TYPE_P (type) + || TREE_CODE (type) != ENUMERAL_TYPE + || TYPE_NAME (type) != get_identifier ("omp_event_handle_t")) + { + error_at (clause_loc, "%<detach%> clause event handle " + "has type %qT rather than " + "%<omp_event_handle_t%>", + type); + parens.skip_until_found_close (parser); + return list; + } + + tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DETACH); + OMP_CLAUSE_DECL (u) = t; + OMP_CLAUSE_CHAIN (u) = list; + parens.skip_until_found_close (parser); + return u; +} + /* Parse all OpenACC clauses. The set clauses allowed by the directive is a bitmask in MASK. Return the list of clauses found. */ @@ -16243,6 +16293,10 @@ c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask, clauses = c_parser_omp_clause_default (parser, clauses, false); c_name = "default"; break; + case PRAGMA_OMP_CLAUSE_DETACH: + clauses = c_parser_omp_clause_detach (parser, clauses); + c_name = "detach"; + break; case PRAGMA_OMP_CLAUSE_FIRSTPRIVATE: clauses = c_parser_omp_clause_firstprivate (parser, clauses); c_name = "firstprivate"; @@ -19190,7 +19244,8 @@ c_parser_omp_single (location_t loc, c_parser *parser, bool *if_p) | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \ - | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION)) + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DETACH)) static tree c_parser_omp_task (location_t loc, c_parser *parser, bool *if_p) diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index 083134a..8ef0843 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -13854,6 +13854,8 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) tree simdlen = NULL_TREE, safelen = NULL_TREE; bool branch_seen = false; bool copyprivate_seen = false; + bool mergeable_seen = false; + tree *detach_seen = NULL; bool linear_variable_step_check = false; tree *nowait_clause = NULL; tree ordered_clause = NULL_TREE; @@ -14937,6 +14939,21 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) pc = &OMP_CLAUSE_CHAIN (c); continue; + case OMP_CLAUSE_DETACH: + t = OMP_CLAUSE_DECL (c); + if (detach_seen) + { + error_at (OMP_CLAUSE_LOCATION (c), + "too many %qs clauses on a task construct", + "detach"); + remove = true; + break; + } + detach_seen = pc; + pc = &OMP_CLAUSE_CHAIN (c); + c_mark_addressable (t); + continue; + case OMP_CLAUSE_IF: case OMP_CLAUSE_NUM_THREADS: case OMP_CLAUSE_NUM_TEAMS: @@ -14945,7 +14962,6 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) case OMP_CLAUSE_UNTIED: case OMP_CLAUSE_COLLAPSE: case OMP_CLAUSE_FINAL: - case OMP_CLAUSE_MERGEABLE: case OMP_CLAUSE_DEVICE: case OMP_CLAUSE_DIST_SCHEDULE: case OMP_CLAUSE_PARALLEL: @@ -14979,6 +14995,11 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) pc = &OMP_CLAUSE_CHAIN (c); continue; + case OMP_CLAUSE_MERGEABLE: + mergeable_seen = true; + pc = &OMP_CLAUSE_CHAIN (c); + continue; + case OMP_CLAUSE_NOGROUP: nogroup_seen = pc; pc = &OMP_CLAUSE_CHAIN (c); @@ -15230,6 +15251,41 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) *nogroup_seen = OMP_CLAUSE_CHAIN (*nogroup_seen); } + if (detach_seen) + { + if (mergeable_seen) + { + error_at (OMP_CLAUSE_LOCATION (*detach_seen), + "%<detach%> clause must not be used together with " + "%<mergeable%> clause"); + *detach_seen = OMP_CLAUSE_CHAIN (*detach_seen); + } + else + { + tree detach_decl = OMP_CLAUSE_DECL (*detach_seen); + + for (pc = &clauses, c = clauses; c ; c = *pc) + { + bool remove = false; + if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE) + && OMP_CLAUSE_DECL (c) == detach_decl) + { + error_at (OMP_CLAUSE_LOCATION (c), + "the event handle of a %<detach%> clause " + "should not be in a data-sharing clause"); + remove = true; + } + if (remove) + *pc = OMP_CLAUSE_CHAIN (c); + else + pc = &OMP_CLAUSE_CHAIN (c); + } + } + } + bitmap_obstack_release (NULL); return clauses; } diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index c713852..e67339d 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -37412,6 +37412,52 @@ cp_parser_omp_clause_depend_sink (cp_parser *parser, location_t clause_loc, } /* OpenMP 5.0: + detach ( event-handle ) */ + +static tree +cp_parser_omp_clause_detach (cp_parser *parser, tree list) +{ + matching_parens parens; + + if (!parens.require_open (parser)) + return list; + + cp_token *token; + tree name, decl; + + token = cp_lexer_peek_token (parser->lexer); + name = cp_parser_id_expression (parser, /*template_p=*/false, + /*check_dependency_p=*/true, + /*template_p=*/NULL, + /*declarator_p=*/false, + /*optional_p=*/false); + if (name == error_mark_node) + decl = error_mark_node; + else + { + if (identifier_p (name)) + decl = cp_parser_lookup_name_simple (parser, name, token->location); + else + decl = name; + if (decl == error_mark_node) + cp_parser_name_lookup_error (parser, name, decl, NLE_NULL, + token->location); + } + + if (decl == error_mark_node + || !parens.require_close (parser)) + cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, + /*or_comma=*/false, + /*consume_paren=*/true); + + tree u = build_omp_clause (token->location, OMP_CLAUSE_DETACH); + OMP_CLAUSE_DECL (u) = decl; + OMP_CLAUSE_CHAIN (u) = list; + + return u; +} + +/* OpenMP 5.0: iterators ( iterators-definition ) iterators-definition: @@ -38470,6 +38516,10 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask, token->location); c_name = "depend"; break; + case PRAGMA_OMP_CLAUSE_DETACH: + clauses = cp_parser_omp_clause_detach (parser, clauses); + c_name = "detach"; + break; case PRAGMA_OMP_CLAUSE_MAP: clauses = cp_parser_omp_clause_map (parser, clauses); c_name = "map"; @@ -41045,7 +41095,8 @@ cp_parser_omp_single (cp_parser *parser, cp_token *pragma_tok, bool *if_p) | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \ - | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION)) + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DETACH)) static tree cp_parser_omp_task (cp_parser *parser, cp_token *pragma_tok, bool *if_p) diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index c27ef6d..9571401 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -17354,6 +17354,7 @@ tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort, case OMP_CLAUSE_VECTOR: case OMP_CLAUSE_ASYNC: case OMP_CLAUSE_WAIT: + case OMP_CLAUSE_DETACH: OMP_CLAUSE_OPERAND (nc, 0) = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 0), args, complain, in_decl, /*integral_constant_expression_p=*/false); diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index c6b4c70..c8a6283 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -6401,6 +6401,8 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) has been seen, -2 if mixed inscan/normal reduction diagnosed. */ int reduction_seen = 0; bool allocate_seen = false; + bool detach_seen = false; + bool mergeable_seen = false; bitmap_obstack_initialize (NULL); bitmap_initialize (&generic_head, &bitmap_default_obstack); @@ -7418,6 +7420,36 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) } } break; + case OMP_CLAUSE_DETACH: + t = OMP_CLAUSE_DECL (c); + if (detach_seen) + { + error_at (OMP_CLAUSE_LOCATION (c), + "too many %qs clauses on a task construct", + "detach"); + remove = true; + break; + } + else + { + tree type = TYPE_MAIN_VARIANT (TREE_TYPE (t)); + if (!type_dependent_expression_p (t) + && (!INTEGRAL_TYPE_P (type) + || TREE_CODE (type) != ENUMERAL_TYPE + || (DECL_NAME (TYPE_NAME (type)) + != get_identifier ("omp_event_handle_t")))) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%<detach%> clause event handle " + "has type %qT rather than " + "%<omp_event_handle_t%>", + type); + remove = true; + } + detach_seen = true; + cxx_mark_addressable (t); + } + break; case OMP_CLAUSE_MAP: case OMP_CLAUSE_TO: @@ -7949,7 +7981,6 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) case OMP_CLAUSE_DEFAULT: case OMP_CLAUSE_UNTIED: case OMP_CLAUSE_COLLAPSE: - case OMP_CLAUSE_MERGEABLE: case OMP_CLAUSE_PARALLEL: case OMP_CLAUSE_FOR: case OMP_CLAUSE_SECTIONS: @@ -7968,6 +7999,10 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) case OMP_CLAUSE_FINALIZE: break; + case OMP_CLAUSE_MERGEABLE: + mergeable_seen = true; + break; + case OMP_CLAUSE_TILE: for (tree list = OMP_CLAUSE_TILE_LIST (c); !remove && list; list = TREE_CHAIN (list)) @@ -8205,6 +8240,17 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) } pc = &OMP_CLAUSE_CHAIN (c); continue; + case OMP_CLAUSE_DETACH: + if (mergeable_seen) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%<detach%> clause must not be used together with " + "%<mergeable%> clause"); + *pc = OMP_CLAUSE_CHAIN (c); + continue; + } + pc = &OMP_CLAUSE_CHAIN (c); + continue; case OMP_CLAUSE_NOWAIT: if (copyprivate_seen) { @@ -8365,6 +8411,19 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) } } + if (detach_seen + && (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE) + && OMP_CLAUSE_DECL (c) == t) + { + error_at (OMP_CLAUSE_LOCATION (c), + "the event handle of a %<detach%> clause " + "should not be in a data-sharing clause"); + remove = true; + } + /* We're interested in the base element, not arrays. */ inner_type = type = TREE_TYPE (t); if ((need_complete_type diff --git a/gcc/fortran/dump-parse-tree.c b/gcc/fortran/dump-parse-tree.c index a612804..059d842 100644 --- a/gcc/fortran/dump-parse-tree.c +++ b/gcc/fortran/dump-parse-tree.c @@ -1727,6 +1727,12 @@ show_omp_clauses (gfc_omp_clauses *omp_clauses) show_expr (omp_clauses->priority); fputc (')', dumpfile); } + if (omp_clauses->detach) + { + fputs (" DETACH(", dumpfile); + show_expr (omp_clauses->detach); + fputc (')', dumpfile); + } for (i = 0; i < OMP_IF_LAST; i++) if (omp_clauses->if_exprs[i]) { diff --git a/gcc/fortran/frontend-passes.c b/gcc/fortran/frontend-passes.c index b1e3926..63ee7b9 100644 --- a/gcc/fortran/frontend-passes.c +++ b/gcc/fortran/frontend-passes.c @@ -5597,6 +5597,7 @@ gfc_code_walker (gfc_code **c, walk_code_fn_t codefn, walk_expr_fn_t exprfn, WALK_SUBEXPR (co->ext.omp_clauses->hint); WALK_SUBEXPR (co->ext.omp_clauses->num_tasks); WALK_SUBEXPR (co->ext.omp_clauses->priority); + WALK_SUBEXPR (co->ext.omp_clauses->detach); for (idx = 0; idx < OMP_IF_LAST; idx++) WALK_SUBEXPR (co->ext.omp_clauses->if_exprs[idx]); for (idx = 0; diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index 4dd72b6..7935aca 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -1416,6 +1416,7 @@ typedef struct gfc_omp_clauses struct gfc_expr *hint; struct gfc_expr *num_tasks; struct gfc_expr *priority; + struct gfc_expr *detach; struct gfc_expr *if_exprs[OMP_IF_LAST]; enum gfc_omp_sched_kind dist_sched_kind; struct gfc_expr *dist_chunk_size; @@ -3104,6 +3105,7 @@ extern int gfc_default_character_kind; extern int gfc_default_logical_kind; extern int gfc_default_complex_kind; extern int gfc_c_int_kind; +extern int gfc_c_intptr_kind; extern int gfc_atomic_int_kind; extern int gfc_atomic_logical_kind; extern int gfc_intio_kind; diff --git a/gcc/fortran/openmp.c b/gcc/fortran/openmp.c index cb166f9..a9ecd96 100644 --- a/gcc/fortran/openmp.c +++ b/gcc/fortran/openmp.c @@ -91,6 +91,7 @@ gfc_free_omp_clauses (gfc_omp_clauses *c) gfc_free_expr (c->hint); gfc_free_expr (c->num_tasks); gfc_free_expr (c->priority); + gfc_free_expr (c->detach); for (i = 0; i < OMP_IF_LAST; i++) gfc_free_expr (c->if_exprs[i]); gfc_free_expr (c->async_expr); @@ -448,6 +449,39 @@ cleanup: return MATCH_ERROR; } +/* Match detach(event-handle). */ + +static match +gfc_match_omp_detach (gfc_expr **expr) +{ + locus old_loc = gfc_current_locus; + + if (gfc_match ("detach ( ") != MATCH_YES) + goto syntax_error; + + if (gfc_match_variable (expr, 0) != MATCH_YES) + goto syntax_error; + + if ((*expr)->ts.type != BT_INTEGER || (*expr)->ts.kind != gfc_c_intptr_kind) + { + gfc_error ("%qs at %L should be of type " + "integer(kind=omp_event_handle_kind)", + (*expr)->symtree->n.sym->name, &(*expr)->where); + return MATCH_ERROR; + } + + if (gfc_match_char (')') != MATCH_YES) + goto syntax_error; + + return MATCH_YES; + +syntax_error: + gfc_error ("Syntax error in OpenMP detach clause at %C"); + gfc_current_locus = old_loc; + return MATCH_ERROR; + +} + /* Match depend(sink : ...) construct a namelist from it. */ static match @@ -807,6 +841,7 @@ enum omp_mask1 OMP_CLAUSE_ATOMIC, /* OpenMP 5.0. */ OMP_CLAUSE_CAPTURE, /* OpenMP 5.0. */ OMP_CLAUSE_MEMORDER, /* OpenMP 5.0. */ + OMP_CLAUSE_DETACH, /* OpenMP 5.0. */ OMP_CLAUSE_NOWAIT, /* This must come last. */ OMP_MASK1_LAST @@ -840,7 +875,6 @@ enum omp_mask2 OMP_CLAUSE_IF_PRESENT, OMP_CLAUSE_FINALIZE, OMP_CLAUSE_ATTACH, - OMP_CLAUSE_DETACH, /* This must come last. */ OMP_MASK2_LAST }; @@ -1378,6 +1412,12 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask, gfc_current_locus = old_loc; } if ((mask & OMP_CLAUSE_DETACH) + && !openacc + && !c->detach + && gfc_match_omp_detach (&c->detach) == MATCH_YES) + continue; + if ((mask & OMP_CLAUSE_DETACH) + && openacc && gfc_match ("detach ( ") == MATCH_YES && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP], OMP_MAP_DETACH, false, @@ -2763,7 +2803,8 @@ cleanup: (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \ | OMP_CLAUSE_SHARED | OMP_CLAUSE_IF | OMP_CLAUSE_DEFAULT \ | OMP_CLAUSE_UNTIED | OMP_CLAUSE_FINAL | OMP_CLAUSE_MERGEABLE \ - | OMP_CLAUSE_DEPEND | OMP_CLAUSE_PRIORITY | OMP_CLAUSE_IN_REDUCTION) + | OMP_CLAUSE_DEPEND | OMP_CLAUSE_PRIORITY | OMP_CLAUSE_IN_REDUCTION \ + | OMP_CLAUSE_DETACH) #define OMP_TASKLOOP_CLAUSES \ (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \ | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_SHARED | OMP_CLAUSE_IF \ @@ -5061,6 +5102,10 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses, if (n->sym->attr.associate_var) gfc_error ("ASSOCIATE name %qs in SHARED clause at %L", n->sym->name, &n->where); + if (omp_clauses->detach + && n->sym == omp_clauses->detach->symtree->n.sym) + gfc_error ("DETACH event handle %qs in SHARED clause at %L", + n->sym->name, &n->where); } break; case OMP_LIST_ALIGNED: @@ -5387,7 +5432,13 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses, default: break; } - + if (omp_clauses->detach + && (list == OMP_LIST_PRIVATE + || list == OMP_LIST_FIRSTPRIVATE + || list == OMP_LIST_LASTPRIVATE) + && n->sym == omp_clauses->detach->symtree->n.sym) + gfc_error ("DETACH event handle %qs in %s clause at %L", + n->sym->name, name, &n->where); switch (list) { case OMP_LIST_REDUCTION_INSCAN: @@ -5684,6 +5735,9 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses, gfc_error ("%s must contain at least one MAP clause at %L", p, &code->loc); } + if (!openacc && omp_clauses->mergeable && omp_clauses->detach) + gfc_error ("%<DETACH%> clause at %L must not be used together with " + "%<MERGEABLE%> clause", &omp_clauses->detach->where); } diff --git a/gcc/fortran/trans-openmp.c b/gcc/fortran/trans-openmp.c index 70bfc02..00358ca 100644 --- a/gcc/fortran/trans-openmp.c +++ b/gcc/fortran/trans-openmp.c @@ -3673,6 +3673,22 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses, omp_clauses = gfc_trans_add_clause (c, omp_clauses); } + if (clauses->detach) + { + tree detach; + + gfc_init_se (&se, NULL); + gfc_conv_expr (&se, clauses->detach); + gfc_add_block_to_block (block, &se.pre); + detach = se.expr; + gfc_add_block_to_block (block, &se.post); + + c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DETACH); + TREE_ADDRESSABLE (detach) = 1; + OMP_CLAUSE_DECL (c) = detach; + omp_clauses = gfc_trans_add_clause (c, omp_clauses); + } + if (clauses->hint) { tree hint; diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c index d153db7..ccdc468 100644 --- a/gcc/fortran/trans-types.c +++ b/gcc/fortran/trans-types.c @@ -114,6 +114,7 @@ int gfc_default_character_kind; int gfc_default_logical_kind; int gfc_default_complex_kind; int gfc_c_int_kind; +int gfc_c_intptr_kind; int gfc_atomic_int_kind; int gfc_atomic_logical_kind; @@ -691,6 +692,8 @@ gfc_init_kinds (void) /* Choose atomic kinds to match C's int. */ gfc_atomic_int_kind = gfc_c_int_kind; gfc_atomic_logical_kind = gfc_c_int_kind; + + gfc_c_intptr_kind = POINTER_SIZE / 8; } diff --git a/gcc/fortran/types.def b/gcc/fortran/types.def index 3d7f365..8626ed0 100644 --- a/gcc/fortran/types.def +++ b/gcc/fortran/types.def @@ -235,10 +235,6 @@ DEF_FUNCTION_TYPE_8 (BT_FN_BOOL_UINT_ULLPTR_LONG_ULL_ULLPTR_ULLPTR_PTR_PTR, BT_BOOL, BT_UINT, BT_PTR_ULONGLONG, BT_LONG, BT_ULONGLONG, BT_PTR_ULONGLONG, BT_PTR_ULONGLONG, BT_PTR, BT_PTR) -DEF_FUNCTION_TYPE_9 (BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_BOOL_UINT_PTR_INT, - BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR, - BT_PTR_FN_VOID_PTR_PTR, BT_LONG, BT_LONG, - BT_BOOL, BT_UINT, BT_PTR, BT_INT) DEF_FUNCTION_TYPE_9 (BT_FN_VOID_INT_OMPFN_SIZE_PTR_PTR_PTR_UINT_PTR_PTR, BT_VOID, BT_INT, BT_PTR_FN_VOID_PTR, BT_SIZE, BT_PTR, BT_PTR, BT_PTR, BT_UINT, BT_PTR, BT_PTR) @@ -246,6 +242,10 @@ DEF_FUNCTION_TYPE_9 (BT_FN_BOOL_LONG_LONG_LONG_LONG_LONG_LONGPTR_LONGPTR_PTR_PTR BT_BOOL, BT_LONG, BT_LONG, BT_LONG, BT_LONG, BT_LONG, BT_PTR_LONG, BT_PTR_LONG, BT_PTR, BT_PTR) +DEF_FUNCTION_TYPE_10 (BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_BOOL_UINT_PTR_INT_PTR, + BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR, + BT_PTR_FN_VOID_PTR_PTR, BT_LONG, BT_LONG, + BT_BOOL, BT_UINT, BT_PTR, BT_INT, BT_PTR) DEF_FUNCTION_TYPE_10 (BT_FN_BOOL_BOOL_ULL_ULL_ULL_LONG_ULL_ULLPTR_ULLPTR_PTR_PTR, BT_BOOL, BT_BOOL, BT_ULONGLONG, BT_ULONGLONG, BT_ULONGLONG, BT_LONG, BT_ULONGLONG, BT_PTR_ULONGLONG, diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 18a154a..d2ac5f9 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -7220,6 +7220,15 @@ omp_default_clause (struct gimplify_omp_ctx *ctx, tree decl, enum omp_clause_default_kind kind; kind = lang_hooks.decls.omp_predetermined_sharing (decl); + if (ctx->region_type & ORT_TASK) + { + tree detach_clause = omp_find_clause (ctx->clauses, OMP_CLAUSE_DETACH); + + /* The event-handle specified by a detach clause should always be firstprivate, + regardless of the current default. */ + if (detach_clause && OMP_CLAUSE_DECL (detach_clause) == decl) + kind = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE; + } if (kind != OMP_CLAUSE_DEFAULT_UNSPECIFIED) default_kind = kind; else if (VAR_P (decl) && TREE_STATIC (decl) && DECL_IN_CONSTANT_POOL (decl)) @@ -9754,6 +9763,10 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, } break; + case OMP_CLAUSE_DETACH: + flags = GOVD_FIRSTPRIVATE | GOVD_SEEN; + goto do_add; + case OMP_CLAUSE_IF: if (OMP_CLAUSE_IF_MODIFIER (c) != ERROR_MARK && OMP_CLAUSE_IF_MODIFIER (c) != code) @@ -10900,6 +10913,7 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p, case OMP_CLAUSE_DEFAULTMAP: case OMP_CLAUSE_ORDER: case OMP_CLAUSE_BIND: + case OMP_CLAUSE_DETACH: case OMP_CLAUSE_USE_DEVICE_PTR: case OMP_CLAUSE_USE_DEVICE_ADDR: case OMP_CLAUSE_IS_DEVICE_PTR: diff --git a/gcc/omp-builtins.def b/gcc/omp-builtins.def index 04356ac..cfbf1e6 100644 --- a/gcc/omp-builtins.def +++ b/gcc/omp-builtins.def @@ -381,7 +381,7 @@ DEF_GOMP_BUILTIN (BUILT_IN_GOMP_PARALLEL_REDUCTIONS, "GOMP_parallel_reductions", BT_FN_UINT_OMPFN_PTR_UINT_UINT, ATTR_NOTHROW_LIST) DEF_GOMP_BUILTIN (BUILT_IN_GOMP_TASK, "GOMP_task", - BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_BOOL_UINT_PTR_INT, + BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_BOOL_UINT_PTR_INT_PTR, ATTR_NOTHROW_LIST) DEF_GOMP_BUILTIN (BUILT_IN_GOMP_TASKLOOP, "GOMP_taskloop", BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_UINT_LONG_INT_LONG_LONG_LONG, diff --git a/gcc/omp-expand.c b/gcc/omp-expand.c index 54b11ad..7559ec8 100644 --- a/gcc/omp-expand.c +++ b/gcc/omp-expand.c @@ -762,6 +762,7 @@ expand_task_call (struct omp_region *region, basic_block bb, tree depend = omp_find_clause (clauses, OMP_CLAUSE_DEPEND); tree finalc = omp_find_clause (clauses, OMP_CLAUSE_FINAL); tree priority = omp_find_clause (clauses, OMP_CLAUSE_PRIORITY); + tree detach = omp_find_clause (clauses, OMP_CLAUSE_DETACH); unsigned int iflags = (untied ? GOMP_TASK_FLAG_UNTIED : 0) @@ -811,8 +812,13 @@ expand_task_call (struct omp_region *region, basic_block bb, if (omp_find_clause (clauses, OMP_CLAUSE_REDUCTION)) iflags |= GOMP_TASK_FLAG_REDUCTION; } - else if (priority) - iflags |= GOMP_TASK_FLAG_PRIORITY; + else + { + if (priority) + iflags |= GOMP_TASK_FLAG_PRIORITY; + if (detach) + iflags |= GOMP_TASK_FLAG_DETACH; + } tree flags = build_int_cst (unsigned_type_node, iflags); @@ -853,6 +859,11 @@ expand_task_call (struct omp_region *region, basic_block bb, priority = integer_zero_node; gsi = gsi_last_nondebug_bb (bb); + + detach = (detach + ? build_fold_addr_expr (OMP_CLAUSE_DECL (detach)) + : null_pointer_node); + tree t = gimple_omp_task_data_arg (entry_stmt); if (t == NULL) t2 = null_pointer_node; @@ -875,10 +886,10 @@ expand_task_call (struct omp_region *region, basic_block bb, num_tasks, priority, startvar, endvar, step); else t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK), - 9, t1, t2, t3, + 10, t1, t2, t3, gimple_omp_task_arg_size (entry_stmt), gimple_omp_task_arg_align (entry_stmt), cond, flags, - depend, priority); + depend, priority, detach); force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false, GSI_CONTINUE_LINKING); diff --git a/gcc/omp-low.c b/gcc/omp-low.c index 29c8da1..c1267dc 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -1412,6 +1412,7 @@ scan_sharing_clauses (tree clauses, omp_context *ctx) case OMP_CLAUSE_NUM_GANGS: case OMP_CLAUSE_NUM_WORKERS: case OMP_CLAUSE_VECTOR_LENGTH: + case OMP_CLAUSE_DETACH: if (ctx->outer) scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer); break; @@ -1779,6 +1780,7 @@ scan_sharing_clauses (tree clauses, omp_context *ctx) case OMP_CLAUSE_SIMDLEN: case OMP_CLAUSE_ALIGNED: case OMP_CLAUSE_DEPEND: + case OMP_CLAUSE_DETACH: case OMP_CLAUSE_ALLOCATE: case OMP_CLAUSE__LOOPTEMP_: case OMP_CLAUSE__REDUCTEMP_: @@ -2350,6 +2352,9 @@ finish_taskreg_scan (omp_context *ctx) { location_t loc = gimple_location (ctx->stmt); tree *p, vla_fields = NULL_TREE, *q = &vla_fields; + tree detach_clause + = omp_find_clause (gimple_omp_task_clauses (ctx->stmt), + OMP_CLAUSE_DETACH); /* Move VLA fields to the end. */ p = &TYPE_FIELDS (ctx->record_type); while (*p) @@ -2416,6 +2421,48 @@ finish_taskreg_scan (omp_context *ctx) TYPE_FIELDS (ctx->srecord_type) = f1; } } + if (detach_clause) + { + tree c, field; + + /* Look for a firstprivate clause with the detach event handle. */ + for (c = gimple_omp_taskreg_clauses (ctx->stmt); + c; c = OMP_CLAUSE_CHAIN (c)) + { + if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_FIRSTPRIVATE) + continue; + if (maybe_lookup_decl_in_outer_ctx (OMP_CLAUSE_DECL (c), ctx) + == OMP_CLAUSE_DECL (detach_clause)) + break; + } + + gcc_assert (c); + field = lookup_field (OMP_CLAUSE_DECL (c), ctx); + + /* Move field corresponding to the detach clause first. + This is filled by GOMP_task and needs to be in a + specific position. */ + p = &TYPE_FIELDS (ctx->record_type); + while (*p) + if (*p == field) + *p = DECL_CHAIN (*p); + else + p = &DECL_CHAIN (*p); + DECL_CHAIN (field) = TYPE_FIELDS (ctx->record_type); + TYPE_FIELDS (ctx->record_type) = field; + if (ctx->srecord_type) + { + field = lookup_sfield (OMP_CLAUSE_DECL (detach_clause), ctx); + p = &TYPE_FIELDS (ctx->srecord_type); + while (*p) + if (*p == field) + *p = DECL_CHAIN (*p); + else + p = &DECL_CHAIN (*p); + DECL_CHAIN (field) = TYPE_FIELDS (ctx->srecord_type); + TYPE_FIELDS (ctx->srecord_type) = field; + } + } layout_type (ctx->record_type); fixup_child_record_type (ctx); if (ctx->srecord_type) diff --git a/gcc/testsuite/c-c++-common/gomp/task-detach-1.c b/gcc/testsuite/c-c++-common/gomp/task-detach-1.c new file mode 100644 index 0000000..4558bc1 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/task-detach-1.c @@ -0,0 +1,37 @@ +/* { dg-do compile } */ +/* { dg-options "-fopenmp" } */ + +typedef enum omp_event_handle_t +{ + __omp_event_handle_t_max__ = __UINTPTR_MAX__ +} omp_event_handle_t; + +extern void omp_fulfill_event (omp_event_handle_t); + +void f (omp_event_handle_t x, omp_event_handle_t y, int z) +{ + #pragma omp task detach (x) detach (y) /* { dg-error "too many 'detach' clauses on a task construct" } */ + ; + + #pragma omp task mergeable detach (x) /* { dg-error "'detach' clause must not be used together with 'mergeable' clause" } */ + ; + + #pragma omp task detach (x) mergeable /* { dg-error "'detach' clause must not be used together with 'mergeable' clause" } */ + ; + + #pragma omp task detach (z) /* { dg-error "'detach' clause event handle has type 'int' rather than 'omp_event_handle_t'" } */ + ; + + #pragma omp parallel master default (none) /* { dg-message "enclosing 'parallel'" } */ + #pragma omp task detach (x) /* { dg-error "'x' not specified in enclosing 'parallel'" } */ + ; + + #pragma omp task detach (x) default (none) /* This should work. */ + omp_fulfill_event (x); + + #pragma omp task detach (x) firstprivate (x) /* { dg-error "the event handle of a 'detach' clause should not be in a data-sharing clause" } */ + ; + + #pragma omp task detach (x) shared (x) /* { dg-error "the event handle of a 'detach' clause should not be in a data-sharing clause" } */ + ; +} diff --git a/gcc/testsuite/g++.dg/gomp/task-detach-1.C b/gcc/testsuite/g++.dg/gomp/task-detach-1.C new file mode 100644 index 0000000..6028cb4 --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/task-detach-1.C @@ -0,0 +1,29 @@ +// { dg-do compile } +// { dg-options "-fopenmp" } + +typedef enum omp_event_handle_t +{ + __omp_event_handle_t_max__ = __UINTPTR_MAX__ +} omp_event_handle_t; + +template <typename T> +void foo () +{ + T t; + #pragma omp task detach (t) + ; +} + +template <typename T> +void bar () +{ + T t; + #pragma omp task detach (t) // { dg-error "'detach' clause event handle has type 'int' rather than 'omp_event_handle_t'" } + ; +} + +void f() +{ + foo <omp_event_handle_t> (); + bar <int> (); // { dg-message "required from here" } +} diff --git a/gcc/testsuite/gcc.dg/gomp/task-detach-1.c b/gcc/testsuite/gcc.dg/gomp/task-detach-1.c new file mode 100644 index 0000000..611044d --- /dev/null +++ b/gcc/testsuite/gcc.dg/gomp/task-detach-1.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-fopenmp" } */ + +typedef enum omp_event_handle_t +{ + __omp_event_handle_t_max__ = __UINTPTR_MAX__ +} omp_event_handle_t; + +extern void omp_fulfill_event (omp_event_handle_t); + +void f (omp_event_handle_t x) +{ + void g (void) + { + #pragma omp task detach (x) + omp_fulfill_event (x); + } + + g (); +} diff --git a/gcc/testsuite/gfortran.dg/gomp/task-detach-1.f90 b/gcc/testsuite/gfortran.dg/gomp/task-detach-1.f90 new file mode 100644 index 0000000..4763f13 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/task-detach-1.f90 @@ -0,0 +1,29 @@ +! { dg-do compile } +! { dg-options "-fopenmp" } + +program task_detach_1 + use iso_c_binding, only: c_intptr_t + implicit none + + integer, parameter :: omp_event_handle_kind = c_intptr_t + integer (kind=omp_event_handle_kind) :: x, y + integer :: z + + !$omp task detach(x) detach(y) ! { dg-error "Failed to match clause at \\\(1\\\)" } + !$omp end task ! { dg-error "Unexpected !\\\$OMP END TASK statement at \\\(1\\\)" } + + !$omp task mergeable detach(x) ! { dg-error "'DETACH' clause at \\\(1\\\) must not be used together with 'MERGEABLE' clause" } + !$omp end task + + !$omp task detach(x) mergeable ! { dg-error "'DETACH' clause at \\\(1\\\) must not be used together with 'MERGEABLE' clause" } + !$omp end task + + !$omp task detach(z) ! { dg-error "'z' at \\\(1\\\) should be of type integer\\\(kind=omp_event_handle_kind\\\)" } + !$omp end task ! { dg-error "Unexpected !\\\$OMP END TASK statement at \\\(1\\\)" } + + !$omp task detach (x) firstprivate (x) ! { dg-error "DETACH event handle 'x' in FIRSTPRIVATE clause at \\\(1\\\)" } + !$omp end task + + !$omp task detach (x) shared (x) ! { dg-error "DETACH event handle 'x' in SHARED clause at \\\(1\\\)" } + !$omp end task +end program diff --git a/gcc/tree-core.h b/gcc/tree-core.h index d3c37a0..d2e6c89 100644 --- a/gcc/tree-core.h +++ b/gcc/tree-core.h @@ -299,19 +299,8 @@ enum omp_clause_code { /* OpenMP clause: link (variable-list). */ OMP_CLAUSE_LINK, - /* OpenMP clause: from (variable-list). */ - OMP_CLAUSE_FROM, - - /* OpenMP clause: to (variable-list). */ - OMP_CLAUSE_TO, - - /* OpenACC clauses: {copy, copyin, copyout, create, delete, deviceptr, - device, host (self), present, present_or_copy (pcopy), present_or_copyin - (pcopyin), present_or_copyout (pcopyout), present_or_create (pcreate)} - (variable-list). - - OpenMP clause: map ({alloc:,to:,from:,tofrom:,}variable-list). */ - OMP_CLAUSE_MAP, + /* OpenMP clause: detach (event-handle). */ + OMP_CLAUSE_DETACH, /* OpenACC clause: use_device (variable-list). OpenMP clause: use_device_ptr (ptr-list). */ @@ -329,6 +318,20 @@ enum omp_clause_code { /* OpenMP clause: exclusive (variable-list). */ OMP_CLAUSE_EXCLUSIVE, + /* OpenMP clause: from (variable-list). */ + OMP_CLAUSE_FROM, + + /* OpenMP clause: to (variable-list). */ + OMP_CLAUSE_TO, + + /* OpenACC clauses: {copy, copyin, copyout, create, delete, deviceptr, + device, host (self), present, present_or_copy (pcopy), present_or_copyin + (pcopyin), present_or_copyout (pcopyout), present_or_create (pcreate)} + (variable-list). + + OpenMP clause: map ({alloc:,to:,from:,tofrom:,}variable-list). */ + OMP_CLAUSE_MAP, + /* Internal structure to hold OpenACC cache directive's variable-list. #pragma acc cache (variable-list). */ OMP_CLAUSE__CACHE_, diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c index 8f2ccff..1b52669 100644 --- a/gcc/tree-nested.c +++ b/gcc/tree-nested.c @@ -1339,6 +1339,7 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi) case OMP_CLAUSE_USE_DEVICE_PTR: case OMP_CLAUSE_USE_DEVICE_ADDR: case OMP_CLAUSE_IS_DEVICE_PTR: + case OMP_CLAUSE_DETACH: do_decl_clause: if (pdecl == NULL) pdecl = &OMP_CLAUSE_DECL (clause); @@ -2108,6 +2109,7 @@ convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi) case OMP_CLAUSE_USE_DEVICE_PTR: case OMP_CLAUSE_USE_DEVICE_ADDR: case OMP_CLAUSE_IS_DEVICE_PTR: + case OMP_CLAUSE_DETACH: do_decl_clause: if (pdecl == NULL) pdecl = &OMP_CLAUSE_DECL (clause); diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c index f52a785..aabe6bb 100644 --- a/gcc/tree-pretty-print.c +++ b/gcc/tree-pretty-print.c @@ -1265,6 +1265,12 @@ dump_omp_clause (pretty_printer *pp, tree clause, int spc, dump_flags_t flags) case OMP_CLAUSE_FINALIZE: pp_string (pp, "finalize"); break; + case OMP_CLAUSE_DETACH: + pp_string (pp, "detach("); + dump_generic_node (pp, OMP_CLAUSE_DECL (clause), spc, flags, + false); + pp_right_paren (pp); + break; default: gcc_unreachable (); @@ -297,14 +297,15 @@ unsigned const char omp_clause_num_ops[] = 1, /* OMP_CLAUSE_UNIFORM */ 1, /* OMP_CLAUSE_TO_DECLARE */ 1, /* OMP_CLAUSE_LINK */ - 2, /* OMP_CLAUSE_FROM */ - 2, /* OMP_CLAUSE_TO */ - 2, /* OMP_CLAUSE_MAP */ + 1, /* OMP_CLAUSE_DETACH */ 1, /* OMP_CLAUSE_USE_DEVICE_PTR */ 1, /* OMP_CLAUSE_USE_DEVICE_ADDR */ 1, /* OMP_CLAUSE_IS_DEVICE_PTR */ 1, /* OMP_CLAUSE_INCLUSIVE */ 1, /* OMP_CLAUSE_EXCLUSIVE */ + 2, /* OMP_CLAUSE_FROM */ + 2, /* OMP_CLAUSE_TO */ + 2, /* OMP_CLAUSE_MAP */ 2, /* OMP_CLAUSE__CACHE_ */ 2, /* OMP_CLAUSE_GANG */ 1, /* OMP_CLAUSE_ASYNC */ @@ -382,14 +383,15 @@ const char * const omp_clause_code_name[] = "uniform", "to", "link", - "from", - "to", - "map", + "detach", "use_device_ptr", "use_device_addr", "is_device_ptr", "inclusive", "exclusive", + "from", + "to", + "map", "_cache_", "gang", "async", @@ -12240,6 +12242,7 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, case OMP_CLAUSE_HINT: case OMP_CLAUSE_TO_DECLARE: case OMP_CLAUSE_LINK: + case OMP_CLAUSE_DETACH: case OMP_CLAUSE_USE_DEVICE_PTR: case OMP_CLAUSE_USE_DEVICE_ADDR: case OMP_CLAUSE_IS_DEVICE_PTR: |