]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
openmp: Add taskwait nowait depend support [PR105378]
authorJakub Jelinek <jakub@redhat.com>
Tue, 5 Jul 2022 07:11:46 +0000 (09:11 +0200)
committerTobias Burnus <tobias@codesourcery.com>
Tue, 5 Jul 2022 07:17:18 +0000 (09:17 +0200)
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.

(cherry picked from commit b43836914bdc2a37563cf31359b2c4803bfe4374)

15 files changed:
gcc/ChangeLog.omp
gcc/c/ChangeLog.omp
gcc/c/c-parser.cc
gcc/cp/ChangeLog.omp
gcc/cp/parser.cc
gcc/gimplify.cc
gcc/omp-builtins.def
gcc/omp-expand.cc
gcc/testsuite/ChangeLog.omp
gcc/testsuite/c-c++-common/gomp/taskwait-depend-nowait-1.c [new file with mode: 0644]
libgomp/ChangeLog.omp
libgomp/libgomp.map
libgomp/libgomp_g.h
libgomp/task.c
libgomp/testsuite/libgomp.c-c++-common/taskwait-depend-nowait-1.c [new file with mode: 0644]

index 7592fecddcb36424645df23e70d2f7767714160a..aa9dabbdd6bc45f99c5469236c4937c5e0512b2d 100644 (file)
@@ -1,3 +1,17 @@
+2022-07-05  Tobias Burnus  <tobias@codesourcery.com>
+
+       Backport from mainline:
+       2022-05-24  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c/105378
+       * 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.
+
 2022-07-05  Tobias Burnus  <tobias@codesourcery.com>
 
        Backport from mainline:
index 51d735341f26ef491908aa586a9a45c5a90be720..2cca133beb3c29155ee5c8b2c508bb683ef819d1 100644 (file)
@@ -1,3 +1,11 @@
+2022-07-05  Tobias Burnus  <tobias@codesourcery.com>
+
+       Backport from mainline:
+       2022-05-24  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c/105378
+       * c-parser.cc (OMP_TASKWAIT_CLAUSE_MASK): Add nowait clause.
+
 2022-07-04  Tobias Burnus  <tobias@codesourcery.com>
 
        Backport from mainline:
index 903063d4c1e588d0eedd7ef55ca0705541a9efd4..d9489c298f848b86827b7c1dfb44d4d5a8bf128a 100644 (file)
@@ -20706,7 +20706,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)
index 924e0a3ec2e965959b41cbbb6337d7bb62d5a6b8..49c1994c65c3573c75a7ca230004af98fd918f80 100644 (file)
@@ -1,3 +1,11 @@
+2022-07-05  Tobias Burnus  <tobias@codesourcery.com>
+
+       Backport from mainline:
+       2022-05-24  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c/105378
+       * parser.cc (OMP_TASKWAIT_CLAUSE_MASK): Add nowait clause.
+
 2022-07-04  Tobias Burnus  <tobias@codesourcery.com>
 
        Backport from mainline:
index 957206cdc0c4f0f5014165d303409357f99f3e71..71cfe3f59a30e3ee1cbde79015950f07bc90feab 100644 (file)
@@ -43904,7 +43904,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)
index f7614ae6caabadc1dcf9c51e2095bef9161302b3..5409d4b0b6f6a83c4acad2ec3f2a1cdbae1259b7 100644 (file)
@@ -12973,17 +12973,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),
index 64531aa773f6e1994e0855ac168440b48fc7ed1a..d257278b9e5dc857eeb33ea461d1a2f39a7168bd 100644 (file)
@@ -93,6 +93,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",
index f228210cc60109bb4867d0fb6365f294b88beaa4..b1af4ce374816875a117008f7e26a78e15ba6c16 100644 (file)
@@ -920,10 +920,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);
index cf436d4ccf9e35e98311f551046555e8b584fb75..6523bed1dd54a299c25cfd465f6a60b408094ea4 100644 (file)
@@ -1,3 +1,11 @@
+2022-07-05  Tobias Burnus  <tobias@codesourcery.com>
+
+       Backport from mainline:
+       2022-05-24  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c/105378
+       * c-c++-common/gomp/taskwait-depend-nowait-1.c: New test.
+
 2022-07-05  Tobias Burnus  <tobias@codesourcery.com>
 
        Backport from mainline:
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 (file)
index 0000000..54df023
--- /dev/null
@@ -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" } */
+}
index 2888a8c1f6efb8ca80d96be9bf09443b227ce2fb..e1c16cb8f6b7e186c46f0a4800aa5450461645a9 100644 (file)
@@ -1,3 +1,20 @@
+2022-07-05  Tobias Burnus  <tobias@codesourcery.com>
+
+       Backport from mainline:
+       2022-05-24  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c/105378
+       * 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.
+
 2022-07-05  Tobias Burnus  <tobias@codesourcery.com>
 
        Backport from mainline:
index b0815e8f8b48f56950f09b8d10dc2413175f527a..5af5c2d8929e116098d31a17995537de827debd8 100644 (file)
@@ -413,6 +413,7 @@ GOMP_5.1 {
 
 GOMP_5.1.1 {
   global:
+       GOMP_taskwait_depend_nowait;
        GOMP_enable_pinned_mode;
 } GOMP_5.1;
 
index a8e29c576c4c0db10779c29b1166bea7d75148c5..ece1f97a61f355f83a5f2e326f1fadde26d9560c 100644 (file)
@@ -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);
index 6b11a8f02efefa0700456be042ea26dc32fbfd97..7925e5873c416acda7ea96be1b3440c02c797d25 100644 (file)
@@ -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 (file)
index 0000000..3d1519e
--- /dev/null
@@ -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;
+}