diff mbox series

[committed] Allow taskloop cancellation

Message ID 20181202125435.GN12380@tucnak
State New
Headers show
Series [committed] Allow taskloop cancellation | expand

Commit Message

Jakub Jelinek Dec. 2, 2018, 12:54 p.m. UTC
Hi!

Taskloop cancellation which OpenMP 5.0 explicitly allows worked fine on the
library side and on the compiler side if the cancel taskgroup or
cancellation point taskgroup is inside of explicit task and there is no
outer parallel/teams etc. in that function, taskloop is in another function
that calls it.  The following adjusts the nesting checking, so that we
handle it properly and adds testsuite coverage.

Bootstrapped/regtested on powerpc64{,le}-linux, committed to trunk.

2018-12-02  Jakub Jelinek  <jakub@redhat.com>

	* omp-low.c (check_omp_nesting_restrictions): Allow cancel or
	cancellation point with taskgroup clause inside of taskloop.  Consider
	a taskloop construct without nogroup clause as implicit taskgroup for
	diagnostics if cancel/cancellation point with taskgroup clause is
	closely nested inside of taskgroup region.

	* c-c++-common/gomp/cancel-1.c (f2): Add various taskloop related
	tests.

	* testsuite/libgomp.c-c++-common/cancel-taskgroup-4.c: New test.


	Jakub
diff mbox series

Patch

--- gcc/omp-low.c.jj	2018-12-01 15:04:34.000000000 +0100
+++ gcc/omp-low.c	2018-12-01 15:38:47.237454873 +0100
@@ -2744,7 +2744,10 @@  check_omp_nesting_restrictions (gimple *
 	      kind = "sections";
 	      break;
 	    case 8:
-	      if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
+	      if (!is_task_ctx (ctx)
+		  && (!is_taskloop_ctx (ctx)
+		      || ctx->outer == NULL
+		      || !is_task_ctx (ctx->outer)))
 		bad = "#pragma omp task";
 	      else
 		{
@@ -2767,6 +2770,17 @@  check_omp_nesting_restrictions (gimple *
 				    "nested inside of %<taskgroup%> region",
 				    construct);
 			  return false;
+			case GIMPLE_OMP_TASK:
+			  if (gimple_omp_task_taskloop_p (octx->stmt)
+			      && octx->outer
+			      && is_taskloop_ctx (octx->outer))
+			    {
+			      tree clauses
+				= gimple_omp_for_clauses (octx->outer->stmt);
+			      if (!omp_find_clause (clauses, OMP_CLAUSE_NOGROUP))
+				break;
+			    }
+			  continue;
 			default:
 			  continue;
 			}
--- gcc/testsuite/c-c++-common/gomp/cancel-1.c.jj	2016-07-22 15:55:28.000000000 +0200
+++ gcc/testsuite/c-c++-common/gomp/cancel-1.c	2018-12-01 17:01:07.993603645 +0100
@@ -95,6 +95,40 @@  f2 (void)
       #pragma omp cancellation point sections	/* { dg-error "not closely nested inside" } */
       #pragma omp cancellation point taskgroup
     }
+    #pragma omp taskloop
+    for (i = 0; i < 10; i++)
+      {
+        #pragma omp cancel parallel		/* { dg-error "not closely nested inside" } */
+        #pragma omp cancel for			/* { dg-error "not closely nested inside" } */
+        #pragma omp cancel sections		/* { dg-error "not closely nested inside" } */
+        #pragma omp cancel taskgroup
+        #pragma omp cancellation point parallel	/* { dg-error "not closely nested inside" } */
+        #pragma omp cancellation point for	/* { dg-error "not closely nested inside" } */
+        #pragma omp cancellation point sections	/* { dg-error "not closely nested inside" } */
+        #pragma omp cancellation point taskgroup
+	#pragma omp task
+	{
+	  #pragma omp cancellation point taskgroup
+	  #pragma omp cancel taskgroup
+	}
+      }
+    #pragma omp taskloop nogroup
+    for (i = 0; i < 10; i++)
+      {
+        #pragma omp cancel parallel		/* { dg-error "not closely nested inside" } */
+        #pragma omp cancel for			/* { dg-error "not closely nested inside" } */
+        #pragma omp cancel sections		/* { dg-error "not closely nested inside" } */
+        #pragma omp cancel taskgroup		/* { dg-error "construct not closely nested inside of .taskgroup. region" } */
+        #pragma omp cancellation point parallel	/* { dg-error "not closely nested inside" } */
+        #pragma omp cancellation point for	/* { dg-error "not closely nested inside" } */
+        #pragma omp cancellation point sections	/* { dg-error "not closely nested inside" } */
+        #pragma omp cancellation point taskgroup/* { dg-error "construct not closely nested inside of .taskgroup. region" } */
+	#pragma omp task
+	{
+	  #pragma omp cancellation point taskgroup/* { dg-error "construct not closely nested inside of .taskgroup. region" } */
+	  #pragma omp cancel taskgroup		/* { dg-error "construct not closely nested inside of .taskgroup. region" } */
+	}
+      }
     #pragma omp taskgroup
     {
       #pragma omp task
@@ -105,6 +139,17 @@  f2 (void)
 	  #pragma omp cancel taskgroup
 	}
       }
+      #pragma omp taskloop nogroup
+      for (i = 0; i < 10; i++)
+	{
+	  #pragma omp task
+	  {
+	    #pragma omp cancellation point taskgroup
+	    #pragma omp cancel taskgroup
+	  }
+	  #pragma omp cancellation point taskgroup
+	  #pragma omp cancel taskgroup
+	}
     }
     #pragma omp taskgroup
     {
@@ -115,6 +160,18 @@  f2 (void)
 	  #pragma omp cancel taskgroup		/* { dg-error "construct not closely nested inside of .taskgroup. region" } */
 	  #pragma omp cancellation point taskgroup /* { dg-error "construct not closely nested inside of .taskgroup. region" } */
 	}
+	#pragma omp taskloop
+	for (i = 0; i < 10; i++)
+	  {
+	    #pragma omp cancel taskgroup
+	    #pragma omp cancellation point taskgroup
+	  }
+	#pragma omp taskloop nogroup
+	for (i = 0; i < 10; i++)
+	  {
+	    #pragma omp cancel taskgroup	     /* { dg-error "construct not closely nested inside of .taskgroup. region" } */
+	    #pragma omp cancellation point taskgroup /* { dg-error "construct not closely nested inside of .taskgroup. region" } */
+	  }
       }
       #pragma omp target
       {
@@ -144,6 +201,45 @@  f2 (void)
 	}
       }
     }
+    #pragma omp taskloop
+    for (i = 0; i < 10; i++)
+      {
+	#pragma omp parallel
+	{
+	  #pragma omp task
+	  {
+	    #pragma omp cancel taskgroup	     /* { dg-error "construct not closely nested inside of .taskgroup. region" } */
+	    #pragma omp cancellation point taskgroup /* { dg-error "construct not closely nested inside of .taskgroup. region" } */
+	  }
+	}
+        #pragma omp target
+	{
+	  #pragma omp task
+	  {
+	    #pragma omp cancel taskgroup	     /* { dg-error "construct not closely nested inside of .taskgroup. region" } */
+	    #pragma omp cancellation point taskgroup /* { dg-error "construct not closely nested inside of .taskgroup. region" } */
+	  }
+	}
+	#pragma omp target
+	#pragma omp teams
+	#pragma omp distribute
+	for (j = 0; j < 10; j++)
+	  {
+	    #pragma omp task
+	    {
+	      #pragma omp cancel taskgroup	/* { dg-error "construct not closely nested inside of .taskgroup. region" } */
+	      #pragma omp cancellation point taskgroup /* { dg-error "construct not closely nested inside of .taskgroup. region" } */
+	    }
+	  }
+	#pragma omp target data map(i)
+	{
+	  #pragma omp task
+	  {
+	    #pragma omp cancel taskgroup
+	    #pragma omp cancellation point taskgroup
+	  }
+	}
+      }
     #pragma omp for
     for (i = 0; i < 10; i++)
       {
--- libgomp/testsuite/libgomp.c-c++-common/cancel-taskgroup-4.c.jj	2018-12-01 15:17:36.637005863 +0100
+++ libgomp/testsuite/libgomp.c-c++-common/cancel-taskgroup-4.c	2018-12-01 15:47:47.000000000 +0100
@@ -0,0 +1,32 @@ 
+/* { dg-do run } */
+/* { dg-set-target-env-var OMP_CANCELLATION "true" } */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <omp.h>
+
+int
+main ()
+{
+  int i;
+  #pragma omp parallel
+  {
+    int c = 0;
+    #pragma omp barrier
+    #pragma omp master taskloop num_tasks (25) firstprivate (c)
+    for (i = 0; i < 50; i++)
+      {
+        if (c && omp_get_cancellation ())
+	  abort ();
+	#pragma omp cancellation point taskgroup
+	usleep (30);
+	if (i > 10)
+	  c = 1;
+	#pragma omp cancel taskgroup if (i > 10)
+	if (i > 10 && omp_get_cancellation ())
+	  abort ();
+      }
+    usleep (10);
+  }
+  return 0;
+}