public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [committed] openmp: Add taskwait nowait depend support [PR105378]
@ 2022-05-24  7:17 Jakub Jelinek
  0 siblings, 0 replies; only message in thread
From: Jakub Jelinek @ 2022-05-24  7:17 UTC (permalink / raw)
  To: gcc-patches; +Cc: Tobias Burnus

Hi!

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.

Bootstrapped/regtested on x86_64-linux and i686-linux, committed to
trunk.

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.

--- gcc/omp-builtins.def.jj	2022-01-18 11:58:59.718980114 +0100
+++ gcc/omp-builtins.def	2022-05-23 11:36:48.808706835 +0200
@@ -89,6 +89,9 @@ DEF_GOMP_BUILTIN (BUILT_IN_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",
--- gcc/gimplify.cc.jj	2022-05-17 16:51:06.779778719 +0200
+++ gcc/gimplify.cc	2022-05-23 11:34:46.739994990 +0200
@@ -12319,17 +12319,34 @@ gimplify_omp_task (tree *expr_p, gimple_
   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),
--- gcc/omp-expand.cc.jj	2022-05-20 11:45:17.783745028 +0200
+++ gcc/omp-expand.cc	2022-05-23 11:39:53.403758997 +0200
@@ -916,10 +916,12 @@ expand_taskwait_call (basic_block bb, go
 
   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);
--- gcc/c/c-parser.cc.jj	2022-05-19 11:48:28.111675938 +0200
+++ gcc/c/c-parser.cc	2022-05-23 11:17:39.777832454 +0200
@@ -20453,7 +20453,8 @@ c_parser_omp_task (location_t loc, c_par
 */
 
 #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)
--- gcc/cp/parser.cc.jj	2022-05-19 11:48:28.305673269 +0200
+++ gcc/cp/parser.cc	2022-05-23 11:17:39.717833086 +0200
@@ -43793,7 +43793,8 @@ cp_parser_omp_task (cp_parser *parser, c
    # 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)
--- gcc/testsuite/c-c++-common/gomp/taskwait-depend-nowait-1.c.jj	2022-05-23 13:36:55.750182443 +0200
+++ gcc/testsuite/c-c++-common/gomp/taskwait-depend-nowait-1.c	2022-05-23 13:41:12.802511936 +0200
@@ -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" } */
+}
--- libgomp/libgomp_g.h.jj	2022-01-11 23:11:23.890269075 +0100
+++ libgomp/libgomp_g.h	2022-05-23 11:51:17.729539973 +0200
@@ -305,6 +305,7 @@ extern void GOMP_taskloop_ull (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);
--- libgomp/libgomp.map.jj	2022-05-20 11:45:17.962742636 +0200
+++ libgomp/libgomp.map	2022-05-23 11:48:56.440030452 +0200
@@ -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;
--- libgomp/task.c.jj	2022-05-20 11:45:17.977742435 +0200
+++ libgomp/task.c	2022-05-23 14:34:07.712451626 +0200
@@ -460,6 +460,17 @@ gomp_task_handle_depend (struct gomp_tas
     }
 }
 
+/* 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 *da
 	      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
   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 (str
 	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.
 
--- libgomp/testsuite/libgomp.c-c++-common/taskwait-depend-nowait-1.c.jj	2022-05-23 13:58:53.002486838 +0200
+++ libgomp/testsuite/libgomp.c-c++-common/taskwait-depend-nowait-1.c	2022-05-23 14:38:16.983860457 +0200
@@ -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;
+}

	Jakub


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-05-24  7:17 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-05-24  7:17 [committed] openmp: Add taskwait nowait depend support [PR105378] Jakub Jelinek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).