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 /libgomp/testsuite | |
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 'libgomp/testsuite')
12 files changed, 423 insertions, 0 deletions
diff --git a/libgomp/testsuite/libgomp.c-c++-common/task-detach-1.c b/libgomp/testsuite/libgomp.c-c++-common/task-detach-1.c new file mode 100644 index 0000000..8583e37 --- /dev/null +++ b/libgomp/testsuite/libgomp.c-c++-common/task-detach-1.c @@ -0,0 +1,36 @@ +/* { dg-do run } */ + +#include <omp.h> +#include <assert.h> + +/* Test chaining of detached tasks, with each task fulfilling the + completion event of the previous one. */ + +int main (void) +{ + omp_event_handle_t detach_event1, detach_event2; + int x = 0, y = 0, z = 0; + + #pragma omp parallel + #pragma omp single + { + #pragma omp task detach(detach_event1) + x++; + + #pragma omp task detach(detach_event2) + { + y++; + omp_fulfill_event (detach_event1); + } + + #pragma omp task + { + z++; + omp_fulfill_event (detach_event2); + } + } + + assert (x == 1); + assert (y == 1); + assert (z == 1); +} diff --git a/libgomp/testsuite/libgomp.c-c++-common/task-detach-2.c b/libgomp/testsuite/libgomp.c-c++-common/task-detach-2.c new file mode 100644 index 0000000..943ac2a --- /dev/null +++ b/libgomp/testsuite/libgomp.c-c++-common/task-detach-2.c @@ -0,0 +1,37 @@ +/* { dg-do run } */ + +#include <omp.h> +#include <assert.h> + +/* Test handling of detach clause with only a single thread. The runtime + should not block when a task with an unfulfilled event finishes + running. */ + +int main (void) +{ + omp_event_handle_t detach_event1, detach_event2; + int x = 0, y = 0, z = 0; + + #pragma omp parallel num_threads(1) + #pragma omp single + { + #pragma omp task detach(detach_event1) + x++; + + #pragma omp task detach(detach_event2) + { + y++; + omp_fulfill_event (detach_event1); + } + + #pragma omp task + { + z++; + omp_fulfill_event (detach_event2); + } + } + + assert (x == 1); + assert (y == 1); + assert (z == 1); +} diff --git a/libgomp/testsuite/libgomp.c-c++-common/task-detach-3.c b/libgomp/testsuite/libgomp.c-c++-common/task-detach-3.c new file mode 100644 index 0000000..2609fb1 --- /dev/null +++ b/libgomp/testsuite/libgomp.c-c++-common/task-detach-3.c @@ -0,0 +1,33 @@ +/* { dg-do run } */ + +#include <omp.h> +#include <assert.h> + +/* Test the task detach clause used together with dependencies. */ + +int main (void) +{ + omp_event_handle_t detach_event; + int x = 0, y = 0, z = 0; + int dep; + + #pragma omp parallel + #pragma omp single + { + #pragma omp task depend(out:dep) detach(detach_event) + x++; + + #pragma omp task + { + y++; + omp_fulfill_event(detach_event); + } + + #pragma omp task depend(in:dep) + z++; + } + + assert (x == 1); + assert (y == 1); + assert (z == 1); +} diff --git a/libgomp/testsuite/libgomp.c-c++-common/task-detach-4.c b/libgomp/testsuite/libgomp.c-c++-common/task-detach-4.c new file mode 100644 index 0000000..eeb9554 --- /dev/null +++ b/libgomp/testsuite/libgomp.c-c++-common/task-detach-4.c @@ -0,0 +1,24 @@ +/* { dg-do run } */ + +#include <omp.h> +#include <assert.h> + +/* Test detach clause, where a task fulfills its own completion event. */ + +int main (void) +{ + omp_event_handle_t detach_event; + int x = 0; + + detach_event = (omp_event_handle_t) 0x123456789abcdef0; + + #pragma omp parallel + #pragma omp single + #pragma omp task detach(detach_event) + { + x++; + omp_fulfill_event(detach_event); + } + + assert (x == 1); +} diff --git a/libgomp/testsuite/libgomp.c-c++-common/task-detach-5.c b/libgomp/testsuite/libgomp.c-c++-common/task-detach-5.c new file mode 100644 index 0000000..5a01517 --- /dev/null +++ b/libgomp/testsuite/libgomp.c-c++-common/task-detach-5.c @@ -0,0 +1,42 @@ +/* { dg-do run } */ + +#include <omp.h> +#include <assert.h> + +/* Test tasks with detach clause. Each thread spawns off a chain of tasks, + that can then be executed by any available thread. */ + +int main (void) +{ + int x = 0, y = 0, z = 0; + int thread_count; + omp_event_handle_t detach_event1, detach_event2; + + #pragma omp parallel firstprivate(detach_event1, detach_event2) + { + #pragma omp single + thread_count = omp_get_num_threads(); + + #pragma omp task detach(detach_event1) untied + #pragma omp atomic update + x++; + + #pragma omp task detach(detach_event2) untied + { + #pragma omp atomic update + y++; + omp_fulfill_event (detach_event1); + } + + #pragma omp task untied + { + #pragma omp atomic update + z++; + omp_fulfill_event (detach_event2); + } + } + + assert (x == thread_count); + assert (y == thread_count); + assert (z == thread_count); +} diff --git a/libgomp/testsuite/libgomp.c-c++-common/task-detach-6.c b/libgomp/testsuite/libgomp.c-c++-common/task-detach-6.c new file mode 100644 index 0000000..b5f68cc --- /dev/null +++ b/libgomp/testsuite/libgomp.c-c++-common/task-detach-6.c @@ -0,0 +1,46 @@ +/* { dg-do run } */ + +#include <omp.h> +#include <assert.h> + +/* Test tasks with detach clause on an offload device. Each device + thread spawns off a chain of tasks, that can then be executed by + any available thread. */ + +int main (void) +{ + int x = 0, y = 0, z = 0; + int thread_count; + omp_event_handle_t detach_event1, detach_event2; + + #pragma omp target map(tofrom: x, y, z) map(from: thread_count) + #pragma omp parallel firstprivate(detach_event1, detach_event2) + { + #pragma omp single + thread_count = omp_get_num_threads(); + + #pragma omp task detach(detach_event1) untied + #pragma omp atomic update + x++; + + #pragma omp task detach(detach_event2) untied + { + #pragma omp atomic update + y++; + omp_fulfill_event (detach_event1); + } + + #pragma omp task untied + { + #pragma omp atomic update + z++; + omp_fulfill_event (detach_event2); + } + + #pragma omp taskwait + } + + assert (x == thread_count); + assert (y == thread_count); + assert (z == thread_count); +} diff --git a/libgomp/testsuite/libgomp.fortran/task-detach-1.f90 b/libgomp/testsuite/libgomp.fortran/task-detach-1.f90 new file mode 100644 index 0000000..217bf65 --- /dev/null +++ b/libgomp/testsuite/libgomp.fortran/task-detach-1.f90 @@ -0,0 +1,33 @@ +! { dg-do run } + +! Test chaining of detached tasks, with each task fulfilling the +! completion event of the previous one. + +program task_detach_1 + use omp_lib + + integer (kind=omp_event_handle_kind) :: detach_event1, detach_event2 + integer :: x = 0, y = 0, z = 0 + + !$omp parallel + !$omp single + !$omp task detach(detach_event1) + x = x + 1 + !$omp end task + + !$omp task detach(detach_event2) + y = y + 1 + call omp_fulfill_event (detach_event1) + !$omp end task + + !$omp task + z = z + 1 + call omp_fulfill_event (detach_event2) + !$omp end task + !$omp end single + !$omp end parallel + + if (x /= 1) stop 1 + if (y /= 1) stop 2 + if (z /= 1) stop 3 +end program diff --git a/libgomp/testsuite/libgomp.fortran/task-detach-2.f90 b/libgomp/testsuite/libgomp.fortran/task-detach-2.f90 new file mode 100644 index 0000000..ecb4829 --- /dev/null +++ b/libgomp/testsuite/libgomp.fortran/task-detach-2.f90 @@ -0,0 +1,34 @@ +! { dg-do run } + +! Test handling of detach clause with only a single thread. The runtime +! should not block when a task with an unfulfilled event finishes +! running. + +program task_detach_2 + use omp_lib + + integer (kind=omp_event_handle_kind) :: detach_event1, detach_event2 + integer :: x = 0, y = 0, z = 0 + + !$omp parallel num_threads(1) + !$omp single + !$omp task detach(detach_event1) + x = x + 1 + !$omp end task + + !$omp task detach(detach_event2) + y = y + 1 + call omp_fulfill_event (detach_event1) + !$omp end task + + !$omp task + z = z + 1 + call omp_fulfill_event (detach_event2) + !$omp end task + !$omp end single + !$omp end parallel + + if (x /= 1) stop 1 + if (y /= 1) stop 2 + if (z /= 1) stop 3 +end program diff --git a/libgomp/testsuite/libgomp.fortran/task-detach-3.f90 b/libgomp/testsuite/libgomp.fortran/task-detach-3.f90 new file mode 100644 index 0000000..bdf93a5 --- /dev/null +++ b/libgomp/testsuite/libgomp.fortran/task-detach-3.f90 @@ -0,0 +1,33 @@ +! { dg-do run } + +! Test the task detach clause used together with dependencies. + +program task_detach_3 + + use omp_lib + + integer (kind=omp_event_handle_kind) :: detach_event + integer :: x = 0, y = 0, z = 0 + integer :: dep + + !$omp parallel + !$omp single + !$omp task depend(out:dep) detach(detach_event) + x = x + 1 + !$omp end task + + !$omp task + y = y + 1 + call omp_fulfill_event(detach_event) + !$omp end task + + !$omp task depend(in:dep) + z = z + 1 + !$omp end task + !$omp end single + !$omp end parallel + + if (x /= 1) stop 1 + if (y /= 1) stop 2 + if (z /= 1) stop 3 +end program diff --git a/libgomp/testsuite/libgomp.fortran/task-detach-4.f90 b/libgomp/testsuite/libgomp.fortran/task-detach-4.f90 new file mode 100644 index 0000000..6d0843c --- /dev/null +++ b/libgomp/testsuite/libgomp.fortran/task-detach-4.f90 @@ -0,0 +1,22 @@ +! { dg-do run } + +! Test detach clause, where a task fulfills its own completion event. + +program task_detach_4 + + use omp_lib + + integer (kind=omp_event_handle_kind) :: detach_event + integer :: x = 0 + + !$omp parallel + !$omp single + !$omp task detach(detach_event) + x = x + 1 + call omp_fulfill_event(detach_event) + !$omp end task + !$omp end single + !$omp end parallel + + if (x /= 1) stop 1 +end program diff --git a/libgomp/testsuite/libgomp.fortran/task-detach-5.f90 b/libgomp/testsuite/libgomp.fortran/task-detach-5.f90 new file mode 100644 index 0000000..955d687 --- /dev/null +++ b/libgomp/testsuite/libgomp.fortran/task-detach-5.f90 @@ -0,0 +1,39 @@ +! { dg-do run } + +! Test tasks with detach clause. Each thread spawns off a chain of tasks, +! that can then be executed by any available thread. + +program task_detach_5 + use omp_lib + + integer (kind=omp_event_handle_kind) :: detach_event1, detach_event2 + integer :: x = 0, y = 0, z = 0 + integer :: thread_count + + !$omp parallel firstprivate(detach_event1, detach_event2) + !$omp single + thread_count = omp_get_num_threads() + !$omp end single + + !$omp task detach(detach_event1) untied + !$omp atomic update + x = x + 1 + !$omp end task + + !$omp task detach(detach_event2) untied + !$omp atomic update + y = y + 1 + call omp_fulfill_event (detach_event1); + !$omp end task + + !$omp task untied + !$omp atomic update + z = z + 1 + call omp_fulfill_event (detach_event2); + !$omp end task + !$omp end parallel + + if (x /= thread_count) stop 1 + if (y /= thread_count) stop 2 + if (z /= thread_count) stop 3 +end program diff --git a/libgomp/testsuite/libgomp.fortran/task-detach-6.f90 b/libgomp/testsuite/libgomp.fortran/task-detach-6.f90 new file mode 100644 index 0000000..0fe2155 --- /dev/null +++ b/libgomp/testsuite/libgomp.fortran/task-detach-6.f90 @@ -0,0 +1,44 @@ +! { dg-do run } + +! Test tasks with detach clause on an offload device. Each device +! thread spawns off a chain of tasks, that can then be executed by +! any available thread. + +program task_detach_6 + use omp_lib + + integer (kind=omp_event_handle_kind) :: detach_event1, detach_event2 + integer :: x = 0, y = 0, z = 0 + integer :: thread_count + + !$omp target map(tofrom: x, y, z) map(from: thread_count) + !$omp parallel firstprivate(detach_event1, detach_event2) + !$omp single + thread_count = omp_get_num_threads() + !$omp end single + + !$omp task detach(detach_event1) untied + !$omp atomic update + x = x + 1 + !$omp end task + + !$omp task detach(detach_event2) untied + !$omp atomic update + y = y + 1 + call omp_fulfill_event (detach_event1); + !$omp end task + + !$omp task untied + !$omp atomic update + z = z + 1 + call omp_fulfill_event (detach_event2); + !$omp end task + + !$omp taskwait + !$omp end parallel + !$omp end target + + if (x /= thread_count) stop 1 + if (y /= thread_count) stop 2 + if (z /= thread_count) stop 3 +end program |