*/
#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)
# 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)
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),
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",
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);
--- /dev/null
+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" } */
+}
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;
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);
}
}
+/* 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.
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,
gomp_mutex_unlock (&team->task_lock);
}
-static void gomp_task_run_post_handle_depend_hash (struct gomp_task *);
-
/* Called for nowait target tasks. */
bool
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,
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.
--- /dev/null
+#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;
+}