aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2022-05-24 09:12:44 +0200
committerJakub Jelinek <jakub@redhat.com>2022-05-24 09:12:44 +0200
commitb43836914bdc2a37563cf31359b2c4803bfe4374 (patch)
treeb46c9fd3a7988e119e9dc60919b0866efdd6c52e
parent1adf11822bd48f4d65156b7642514630c08c4d00 (diff)
downloadgcc-b43836914bdc2a37563cf31359b2c4803bfe4374.zip
gcc-b43836914bdc2a37563cf31359b2c4803bfe4374.tar.gz
gcc-b43836914bdc2a37563cf31359b2c4803bfe4374.tar.bz2
openmp: Add taskwait nowait depend support [PR105378]
This patch adds support for (so far C/C++) #pragma omp taskwait nowait depend(...) directive, which is like #pragma omp task depend(...) ; but slightly optimized on the library side, so that it creates the task only for the purpose of dependency tracking and doesn't actually schedule it and wait for it when the dependencies are satisfied, instead makes its dependencies satisfied right away. 2022-05-24 Jakub Jelinek <jakub@redhat.com> PR c/105378 gcc/ * omp-builtins.def (BUILT_IN_GOMP_TASKWAIT_DEPEND_NOWAIT): New builtin. * gimplify.cc (gimplify_omp_task): Diagnose taskwait with nowait clause but no depend clauses. * omp-expand.cc (expand_taskwait_call): Use BUILT_IN_GOMP_TASKWAIT_DEPEND_NOWAIT rather than BUILT_IN_GOMP_TASKWAIT_DEPEND if nowait clause is present. gcc/c/ * c-parser.cc (OMP_TASKWAIT_CLAUSE_MASK): Add nowait clause. gcc/cp/ * parser.cc (OMP_TASKWAIT_CLAUSE_MASK): Add nowait clause. gcc/testsuite/ * c-c++-common/gomp/taskwait-depend-nowait-1.c: New test. libgomp/ * libgomp_g.h (GOMP_taskwait_depend_nowait): Declare. * libgomp.map (GOMP_taskwait_depend_nowait): Export at GOMP_5.1.1. * task.c (empty_task): New function. (gomp_task_run_post_handle_depend_hash): Declare earlier. (gomp_task_run_post_handle_depend): Declare. (GOMP_task): Optimize fn == empty_task if there is nothing to wait for. (gomp_task_run_post_handle_dependers): Optimize task->fn == empty_task. (GOMP_taskwait_depend_nowait): New function. * testsuite/libgomp.c-c++-common/taskwait-depend-nowait-1.c: New test.
-rw-r--r--gcc/c/c-parser.cc3
-rw-r--r--gcc/cp/parser.cc3
-rw-r--r--gcc/gimplify.cc31
-rw-r--r--gcc/omp-builtins.def3
-rw-r--r--gcc/omp-expand.cc8
-rw-r--r--gcc/testsuite/c-c++-common/gomp/taskwait-depend-nowait-1.c17
-rw-r--r--libgomp/libgomp.map5
-rw-r--r--libgomp/libgomp_g.h1
-rw-r--r--libgomp/task.c47
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/taskwait-depend-nowait-1.c39
10 files changed, 143 insertions, 14 deletions
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index 8df8f60..492d995 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -20453,7 +20453,8 @@ c_parser_omp_task (location_t loc, c_parser *parser, bool *if_p)
*/
#define OMP_TASKWAIT_CLAUSE_MASK \
- (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND)
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
static void
c_parser_omp_taskwait (c_parser *parser)
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 24585c1..868b861 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -43793,7 +43793,8 @@ cp_parser_omp_task (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
# pragma omp taskwait taskwait-clause[opt] new-line */
#define OMP_TASKWAIT_CLAUSE_MASK \
- (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND)
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
static void
cp_parser_omp_taskwait (cp_parser *parser, cp_token *pragma_tok)
diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc
index 98f5544..cd17966 100644
--- a/gcc/gimplify.cc
+++ b/gcc/gimplify.cc
@@ -12319,17 +12319,34 @@ gimplify_omp_task (tree *expr_p, gimple_seq *pre_p)
tree expr = *expr_p;
gimple *g;
gimple_seq body = NULL;
+ bool nowait = false;
+ bool has_depend = false;
if (OMP_TASK_BODY (expr) == NULL_TREE)
- for (tree c = OMP_TASK_CLAUSES (expr); c; c = OMP_CLAUSE_CHAIN (c))
- if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
- && OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_MUTEXINOUTSET)
+ {
+ for (tree c = OMP_TASK_CLAUSES (expr); c; c = OMP_CLAUSE_CHAIN (c))
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
+ {
+ has_depend = true;
+ if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_MUTEXINOUTSET)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<mutexinoutset%> kind in %<depend%> clause on a "
+ "%<taskwait%> construct");
+ break;
+ }
+ }
+ else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NOWAIT)
+ nowait = true;
+ if (nowait && !has_depend)
{
- error_at (OMP_CLAUSE_LOCATION (c),
- "%<mutexinoutset%> kind in %<depend%> clause on a "
- "%<taskwait%> construct");
- break;
+ error_at (EXPR_LOCATION (expr),
+ "%<taskwait%> construct with %<nowait%> clause but no "
+ "%<depend%> clauses");
+ *expr_p = NULL_TREE;
+ return;
}
+ }
gimplify_scan_omp_clauses (&OMP_TASK_CLAUSES (expr), pre_p,
omp_find_clause (OMP_TASK_CLAUSES (expr),
diff --git a/gcc/omp-builtins.def b/gcc/omp-builtins.def
index cfa6483..ee5213e 100644
--- a/gcc/omp-builtins.def
+++ b/gcc/omp-builtins.def
@@ -89,6 +89,9 @@ DEF_GOMP_BUILTIN (BUILT_IN_GOMP_TASKWAIT, "GOMP_taskwait",
BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_TASKWAIT_DEPEND, "GOMP_taskwait_depend",
BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_TASKWAIT_DEPEND_NOWAIT,
+ "GOMP_taskwait_depend_nowait",
+ BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_TASKYIELD, "GOMP_taskyield",
BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_TASKGROUP_START, "GOMP_taskgroup_start",
diff --git a/gcc/omp-expand.cc b/gcc/omp-expand.cc
index 5729a20..0821b8d 100644
--- a/gcc/omp-expand.cc
+++ b/gcc/omp-expand.cc
@@ -916,10 +916,12 @@ expand_taskwait_call (basic_block bb, gomp_task *entry_stmt)
depend = OMP_CLAUSE_DECL (depend);
+ bool nowait = omp_find_clause (clauses, OMP_CLAUSE_NOWAIT) != NULL_TREE;
gimple_stmt_iterator gsi = gsi_last_nondebug_bb (bb);
- tree t
- = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASKWAIT_DEPEND),
- 1, depend);
+ enum built_in_function f = (nowait
+ ? BUILT_IN_GOMP_TASKWAIT_DEPEND_NOWAIT
+ : BUILT_IN_GOMP_TASKWAIT_DEPEND);
+ tree t = build_call_expr (builtin_decl_explicit (f), 1, depend);
force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
false, GSI_CONTINUE_LINKING);
diff --git a/gcc/testsuite/c-c++-common/gomp/taskwait-depend-nowait-1.c b/gcc/testsuite/c-c++-common/gomp/taskwait-depend-nowait-1.c
new file mode 100644
index 0000000..54df023
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/taskwait-depend-nowait-1.c
@@ -0,0 +1,17 @@
+void
+foo (int *p)
+{
+ #pragma omp taskwait depend(iterator(i = 0:16) , in : p[i]) nowait depend(out : p[32])
+}
+
+void
+bar (int *p)
+{
+ #pragma omp taskwait depend(mutexinoutset : p[0]) nowait /* { dg-error "'mutexinoutset' kind in 'depend' clause on a 'taskwait' construct" } */
+}
+
+void
+baz (void)
+{
+ #pragma omp taskwait nowait /* { dg-error "'taskwait' construct with 'nowait' clause but no 'depend' clauses" } */
+}
diff --git a/libgomp/libgomp.map b/libgomp/libgomp.map
index 6334fdc..46d5f10 100644
--- a/libgomp/libgomp.map
+++ b/libgomp/libgomp.map
@@ -410,6 +410,11 @@ GOMP_5.1 {
GOMP_teams4;
} GOMP_5.0.1;
+GOMP_5.1.1 {
+ global:
+ GOMP_taskwait_depend_nowait;
+} GOMP_5.1;
+
OACC_2.0 {
global:
acc_get_num_devices;
diff --git a/libgomp/libgomp_g.h b/libgomp/libgomp_g.h
index 09674a1..84b9f2c 100644
--- a/libgomp/libgomp_g.h
+++ b/libgomp/libgomp_g.h
@@ -305,6 +305,7 @@ extern void GOMP_taskloop_ull (void (*) (void *), void *,
unsigned long long);
extern void GOMP_taskwait (void);
extern void GOMP_taskwait_depend (void **);
+extern void GOMP_taskwait_depend_nowait (void **);
extern void GOMP_taskyield (void);
extern void GOMP_taskgroup_start (void);
extern void GOMP_taskgroup_end (void);
diff --git a/libgomp/task.c b/libgomp/task.c
index 6b11a8f..7925e58 100644
--- a/libgomp/task.c
+++ b/libgomp/task.c
@@ -460,6 +460,17 @@ gomp_task_handle_depend (struct gomp_task *task, struct gomp_task *parent,
}
}
+/* Body of empty task like taskwait nowait depend. */
+
+static void
+empty_task (void *data __attribute__((unused)))
+{
+}
+
+static void gomp_task_run_post_handle_depend_hash (struct gomp_task *);
+static inline size_t gomp_task_run_post_handle_depend (struct gomp_task *,
+ struct gomp_team *);
+
/* Called when encountering an explicit task directive. If IF_CLAUSE is
false, then we must not delay in executing the task. If UNTIED is true,
then the task may be executed by any member of the team.
@@ -681,6 +692,18 @@ GOMP_task (void (*fn) (void *), void *data, void (*cpyfn) (void *, void *),
gomp_mutex_unlock (&team->task_lock);
return;
}
+ /* Check for taskwait nowait depend which doesn't need to wait for
+ anything. */
+ if (__builtin_expect (fn == empty_task, 0))
+ {
+ if (taskgroup)
+ taskgroup->num_children--;
+ gomp_task_run_post_handle_depend_hash (task);
+ gomp_mutex_unlock (&team->task_lock);
+ gomp_finish_task (task);
+ free (task);
+ return;
+ }
}
priority_queue_insert (PQ_CHILDREN, &parent->children_queue,
@@ -839,8 +862,6 @@ GOMP_PLUGIN_target_task_completion (void *data)
gomp_mutex_unlock (&team->task_lock);
}
-static void gomp_task_run_post_handle_depend_hash (struct gomp_task *);
-
/* Called for nowait target tasks. */
bool
@@ -1357,6 +1378,18 @@ gomp_task_run_post_handle_dependers (struct gomp_task *child_task,
continue;
struct gomp_taskgroup *taskgroup = task->taskgroup;
+ if (__builtin_expect (task->fn == empty_task, 0))
+ {
+ if (!parent)
+ task->parent = NULL;
+ if (gomp_task_run_post_handle_depend (task, team))
+ ++ret;
+ if (taskgroup)
+ taskgroup->num_children--;
+ gomp_finish_task (task);
+ free (task);
+ continue;
+ }
if (parent)
{
priority_queue_insert (PQ_CHILDREN, &parent->children_queue,
@@ -1832,6 +1865,16 @@ GOMP_taskwait_depend (void **depend)
gomp_task_maybe_wait_for_dependencies (depend);
}
+/* Called when encountering a taskwait directive with nowait and depend
+ clause(s). Create a possibly deferred task construct with empty body. */
+
+void
+GOMP_taskwait_depend_nowait (void **depend)
+{
+ ialias_call (GOMP_task) (empty_task, "", NULL, 0, 1, true,
+ GOMP_TASK_FLAG_DEPEND, depend, 0, NULL);
+}
+
/* An undeferred task is about to run. Wait for all tasks that this
undeferred task depends on.
diff --git a/libgomp/testsuite/libgomp.c-c++-common/taskwait-depend-nowait-1.c b/libgomp/testsuite/libgomp.c-c++-common/taskwait-depend-nowait-1.c
new file mode 100644
index 0000000..3d1519e
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/taskwait-depend-nowait-1.c
@@ -0,0 +1,39 @@
+#ifdef __cplusplus
+extern "C"
+#endif
+void abort (void);
+
+int
+main ()
+{
+ int a[64], b = 1;
+ #pragma omp parallel num_threads (4)
+ #pragma omp single
+ {
+ int i;
+ #pragma omp taskwait depend(in: a) nowait
+ #pragma omp taskwait depend(in: a) nowait
+ #pragma omp taskwait
+ #pragma omp taskgroup
+ {
+ #pragma omp taskwait depend(in: a) nowait
+ #pragma omp taskwait depend(in: a) nowait
+ }
+ for (i = 0; i < 64; ++i)
+ #pragma omp task depend(in: a) shared(a)
+ a[i] = i;
+ #pragma omp taskwait depend(inout: a) nowait
+ for (i = 0; i < 64; ++i)
+ #pragma omp task depend(inoutset: a) shared(a)
+ if (a[i] != i)
+ abort ();
+ else
+ a[i] = 2 * i + 1;
+ #pragma omp taskwait nowait depend(out: a) depend(in: b)
+ #pragma omp taskwait depend(inout: b)
+ for (i = 0; i < 64; ++i)
+ if (a[i] != 2 * i + 1)
+ abort ();
+ }
+ return 0;
+}