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 <ja...@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. --- 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; +} Jakub