[flang-commits] [flang] 70894c8 - [flang][OpenMP] Add semantic checks for cancellation nesting

Arnamoy Bhattacharyya via flang-commits flang-commits at lists.llvm.org
Fri Aug 13 07:11:27 PDT 2021


Author: Peixin Qiao
Date: 2021-08-13T10:11:39-04:00
New Revision: 70894c8dd14d35ba8bc6ab317d76e0b325c3f7f0

URL: https://github.com/llvm/llvm-project/commit/70894c8dd14d35ba8bc6ab317d76e0b325c3f7f0
DIFF: https://github.com/llvm/llvm-project/commit/70894c8dd14d35ba8bc6ab317d76e0b325c3f7f0.diff

LOG: [flang][OpenMP] Add semantic checks for cancellation nesting

This patch implements the following semantic checks for cancellation constructs:
```
OpenMP Version 5.0 Section 2.18.1: CANCEL construct restriction:
If construct-type-clause is taskgroup, the cancel construct must be
closely nested inside a task or a taskloop construct and the cancel
region must be closely nested inside a taskgroup region. If
construct-type-clause is sections, the cancel construct must be closely
nested inside a sections or section construct. Otherwise, the cancel
construct must be closely nested inside an OpenMP construct that matches
the type specified in construct-type-clause of the cancel construct.

OpenMP Version 5.0 Section 2.18.2: CANCELLATION POINT restriction:
A cancellation point construct for which construct-type-clause is
taskgroup must be closely nested inside a task or taskloop construct,
and the cancellation point region must be closely nested inside a
taskgroup region. A cancellation point construct for which
construct-type-clause is sections must be closely nested inside a
sections or section construct. A cancellation point construct for which
construct-type-clause is neither sections nor taskgroup must be closely
nested inside an OpenMP construct that matches the type specified in
construct-type-clause.
```

Also add test cases for the check.

Reviewed By: kiranchandramohan

Differential Revision: https://reviews.llvm.org/D106538

Added: 
    flang/test/Semantics/omp-nested-cancel.f90
    flang/test/Semantics/omp-nested-cancellation-point.f90

Modified: 
    flang/lib/Semantics/check-omp-structure.cpp
    flang/lib/Semantics/check-omp-structure.h
    flang/test/Semantics/omp-clause-validity01.f90

Removed: 
    


################################################################################
diff  --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index e8e5ca991f14f..34499e6d5f975 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -846,7 +846,9 @@ void OmpStructureChecker::Leave(const parser::OpenMPFlushConstruct &x) {
 
 void OmpStructureChecker::Enter(const parser::OpenMPCancelConstruct &x) {
   const auto &dir{std::get<parser::Verbatim>(x.t)};
+  const auto &type{std::get<parser::OmpCancelType>(x.t)};
   PushContextAndClauseSets(dir.source, llvm::omp::Directive::OMPD_cancel);
+  CheckCancellationNest(dir.source, type.v);
 }
 
 void OmpStructureChecker::Leave(const parser::OpenMPCancelConstruct &) {
@@ -867,8 +869,10 @@ void OmpStructureChecker::Leave(const parser::OpenMPCriticalConstruct &) {
 void OmpStructureChecker::Enter(
     const parser::OpenMPCancellationPointConstruct &x) {
   const auto &dir{std::get<parser::Verbatim>(x.t)};
+  const auto &type{std::get<parser::OmpCancelType>(x.t)};
   PushContextAndClauseSets(
       dir.source, llvm::omp::Directive::OMPD_cancellation_point);
+  CheckCancellationNest(dir.source, type.v);
 }
 
 void OmpStructureChecker::Leave(
@@ -876,6 +880,133 @@ void OmpStructureChecker::Leave(
   dirContext_.pop_back();
 }
 
+void OmpStructureChecker::CheckCancellationNest(
+    const parser::CharBlock &source, const parser::OmpCancelType::Type &type) {
+  if (CurrentDirectiveIsNested()) {
+    // If construct-type-clause is taskgroup, the cancellation construct must be
+    // closely nested inside a task or a taskloop construct and the cancellation
+    // region must be closely nested inside a taskgroup region. If
+    // construct-type-clause is sections, the cancellation construct must be
+    // closely nested inside a sections or section construct. Otherwise, the
+    // cancellation construct must be closely nested inside an OpenMP construct
+    // that matches the type specified in construct-type-clause of the
+    // cancellation construct.
+
+    OmpDirectiveSet allowedTaskgroupSet{
+        llvm::omp::Directive::OMPD_task, llvm::omp::Directive::OMPD_taskloop};
+    OmpDirectiveSet allowedSectionsSet{llvm::omp::Directive::OMPD_sections,
+        llvm::omp::Directive::OMPD_parallel_sections};
+    OmpDirectiveSet allowedDoSet{llvm::omp::Directive::OMPD_do,
+        llvm::omp::Directive::OMPD_distribute_parallel_do,
+        llvm::omp::Directive::OMPD_parallel_do,
+        llvm::omp::Directive::OMPD_target_parallel_do,
+        llvm::omp::Directive::OMPD_target_teams_distribute_parallel_do,
+        llvm::omp::Directive::OMPD_teams_distribute_parallel_do};
+    OmpDirectiveSet allowedParallelSet{llvm::omp::Directive::OMPD_parallel,
+        llvm::omp::Directive::OMPD_target_parallel};
+
+    bool eligibleCancellation{false};
+    switch (type) {
+    case parser::OmpCancelType::Type::Taskgroup:
+      if (allowedTaskgroupSet.test(GetContextParent().directive)) {
+        eligibleCancellation = true;
+        if (dirContext_.size() >= 3) {
+          // Check if the cancellation region is closely nested inside a
+          // taskgroup region when there are more than two levels of directives
+          // in the directive context stack.
+          if (GetContextParent().directive == llvm::omp::Directive::OMPD_task ||
+              FindClauseParent(llvm::omp::Clause::OMPC_nogroup)) {
+            for (int i = dirContext_.size() - 3; i >= 0; i--) {
+              if (dirContext_[i].directive ==
+                  llvm::omp::Directive::OMPD_taskgroup) {
+                break;
+              }
+              if (allowedParallelSet.test(dirContext_[i].directive)) {
+                eligibleCancellation = false;
+                break;
+              }
+            }
+          }
+        }
+      }
+      if (!eligibleCancellation) {
+        context_.Say(source,
+            "With %s clause, %s construct must be closely nested inside TASK "
+            "or TASKLOOP construct and %s region must be closely nested inside "
+            "TASKGROUP region"_err_en_US,
+            parser::ToUpperCaseLetters(
+                parser::OmpCancelType::EnumToString(type)),
+            ContextDirectiveAsFortran(), ContextDirectiveAsFortran());
+      }
+      return;
+    case parser::OmpCancelType::Type::Sections:
+      if (allowedSectionsSet.test(GetContextParent().directive)) {
+        eligibleCancellation = true;
+      }
+      break;
+    case Fortran::parser::OmpCancelType::Type::Do:
+      if (allowedDoSet.test(GetContextParent().directive)) {
+        eligibleCancellation = true;
+      }
+      break;
+    case parser::OmpCancelType::Type::Parallel:
+      if (allowedParallelSet.test(GetContextParent().directive)) {
+        eligibleCancellation = true;
+      }
+      break;
+    default:
+      break;
+    }
+    if (!eligibleCancellation) {
+      context_.Say(source,
+          "With %s clause, %s construct cannot be closely nested inside %s "
+          "construct"_err_en_US,
+          parser::ToUpperCaseLetters(parser::OmpCancelType::EnumToString(type)),
+          ContextDirectiveAsFortran(),
+          parser::ToUpperCaseLetters(
+              getDirectiveName(GetContextParent().directive).str()));
+    }
+  } else {
+    // The cancellation directive cannot be orphaned.
+    switch (type) {
+    case parser::OmpCancelType::Type::Taskgroup:
+      context_.Say(source,
+          "%s %s directive is not closely nested inside "
+          "TASK or TASKLOOP"_err_en_US,
+          ContextDirectiveAsFortran(),
+          parser::ToUpperCaseLetters(
+              parser::OmpCancelType::EnumToString(type)));
+      break;
+    case parser::OmpCancelType::Type::Sections:
+      context_.Say(source,
+          "%s %s directive is not closely nested inside "
+          "SECTION or SECTIONS"_err_en_US,
+          ContextDirectiveAsFortran(),
+          parser::ToUpperCaseLetters(
+              parser::OmpCancelType::EnumToString(type)));
+      break;
+    case Fortran::parser::OmpCancelType::Type::Do:
+      context_.Say(source,
+          "%s %s directive is not closely nested inside "
+          "the construct that matches the DO clause type"_err_en_US,
+          ContextDirectiveAsFortran(),
+          parser::ToUpperCaseLetters(
+              parser::OmpCancelType::EnumToString(type)));
+      break;
+    case parser::OmpCancelType::Type::Parallel:
+      context_.Say(source,
+          "%s %s directive is not closely nested inside "
+          "the construct that matches the PARALLEL clause type"_err_en_US,
+          ContextDirectiveAsFortran(),
+          parser::ToUpperCaseLetters(
+              parser::OmpCancelType::EnumToString(type)));
+      break;
+    default:
+      break;
+    }
+  }
+}
+
 void OmpStructureChecker::Enter(const parser::OmpEndBlockDirective &x) {
   const auto &dir{std::get<parser::OmpBlockDirective>(x.t)};
   ResetPartialContext(dir.source);

diff  --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index fcb117d7e4c40..2eebb8f705089 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -225,6 +225,8 @@ class OmpStructureChecker
   void CheckCycleConstraints(const parser::OpenMPLoopConstruct &x);
   void CheckDistLinear(const parser::OpenMPLoopConstruct &x);
   void CheckSIMDNest(const parser::OpenMPConstruct &x);
+  void CheckCancellationNest(
+      const parser::CharBlock &source, const parser::OmpCancelType::Type &type);
   std::int64_t GetOrdCollapseLevel(const parser::OpenMPLoopConstruct &x);
   void CheckIfDoOrderedClause(const parser::OmpBlockDirective &blkDirectiv);
   bool CheckReductionOperators(const parser::OmpClause::Reduction &);

diff  --git a/flang/test/Semantics/omp-clause-validity01.f90 b/flang/test/Semantics/omp-clause-validity01.f90
index 79d3c1d6c2f9a..e4dd150459a49 100644
--- a/flang/test/Semantics/omp-clause-validity01.f90
+++ b/flang/test/Semantics/omp-clause-validity01.f90
@@ -494,9 +494,6 @@
   !ERROR: RELAXED clause is not allowed on the FLUSH directive
   !$omp flush relaxed
 
-  !$omp cancel DO
-  !$omp cancellation point parallel
-
 ! 2.13.2 critical Construct
 
   ! !$omp critical (first)

diff  --git a/flang/test/Semantics/omp-nested-cancel.f90 b/flang/test/Semantics/omp-nested-cancel.f90
new file mode 100644
index 0000000000000..579d762a02fac
--- /dev/null
+++ b/flang/test/Semantics/omp-nested-cancel.f90
@@ -0,0 +1,250 @@
+! RUN: %S/test_errors.sh %s %t %flang -fopenmp
+! REQUIRES: shell
+
+! OpenMP Version 5.0
+! Check OpenMP construct validity for the following directives:
+! 2.18.1 Cancel Construct
+
+program main
+  integer :: i, N = 10
+  real :: a
+
+  !ERROR: CANCEL TASKGROUP directive is not closely nested inside TASK or TASKLOOP
+  !$omp cancel taskgroup
+
+  !ERROR: CANCEL SECTIONS directive is not closely nested inside SECTION or SECTIONS
+  !$omp cancel sections
+
+  !ERROR: CANCEL DO directive is not closely nested inside the construct that matches the DO clause type
+  !$omp cancel do
+
+  !ERROR: CANCEL PARALLEL directive is not closely nested inside the construct that matches the PARALLEL clause type
+  !$omp cancel parallel
+
+  !$omp parallel
+  !$omp sections
+  !$omp cancel sections
+  !$omp section
+  a = 3.14
+  !$omp end sections
+  !$omp end parallel
+
+  !$omp sections
+  !$omp section
+  !$omp cancel sections
+  a = 3.14
+  !$omp end sections
+
+  !$omp parallel
+  !ERROR: With SECTIONS clause, CANCEL construct cannot be closely nested inside PARALLEL construct
+  !$omp cancel sections
+  a = 3.14
+  !$omp end parallel
+
+  !$omp parallel sections
+  !$omp cancel sections
+  a = 3.14
+  !$omp end parallel sections
+
+  !$omp do
+  do i = 1, N
+    a = 3.14
+    !$omp cancel do
+  end do
+  !$omp end do
+
+  !$omp parallel do
+  do i = 1, N
+    a = 3.14
+    !$omp cancel do
+  end do
+  !$omp end parallel do
+
+  !$omp target
+  !$omp teams
+  !$omp distribute parallel do
+  do i = 1, N
+    a = 3.14
+    !$omp cancel do
+  end do
+  !$omp end distribute parallel do
+  !$omp end teams
+  !$omp end target
+
+  !$omp target
+  !$omp teams distribute parallel do
+  do i = 1, N
+    a = 3.14
+    !$omp cancel do
+  end do
+  !$omp end teams distribute parallel do
+  !$omp end target
+
+  !$omp target teams distribute parallel do
+  do i = 1, N
+    a = 3.14
+    !$omp cancel do
+  end do
+  !$omp end target teams distribute parallel do
+
+  !$omp target parallel do
+  do i = 1, N
+    a = 3.14
+    !$omp cancel do
+  end do
+  !$omp end target parallel do
+
+  !$omp parallel
+  do i = 1, N
+    a = 3.14
+    !ERROR: With DO clause, CANCEL construct cannot be closely nested inside PARALLEL construct
+    !$omp cancel do
+  end do
+  !$omp end parallel
+
+  !$omp parallel
+  do i = 1, N
+    a = 3.14
+    !$omp cancel parallel
+  end do
+  !$omp end parallel
+
+  !$omp target parallel
+  do i = 1, N
+    a = 3.14
+    !$omp cancel parallel
+  end do
+  !$omp end target parallel
+
+  !$omp target parallel do
+  do i = 1, N
+    a = 3.14
+    !ERROR: With PARALLEL clause, CANCEL construct cannot be closely nested inside TARGET PARALLEL DO construct
+    !$omp cancel parallel
+  end do
+  !$omp end target parallel do
+
+  !$omp do
+  do i = 1, N
+    a = 3.14
+    !ERROR: With PARALLEL clause, CANCEL construct cannot be closely nested inside DO construct
+    !$omp cancel parallel
+  end do
+  !$omp end do
+
+contains
+  subroutine sub1()
+    !$omp task
+    !$omp cancel taskgroup
+    a = 3.14
+    !$omp end task
+
+    !$omp taskloop
+    do i = 1, N
+      !$omp parallel
+      !$omp end parallel
+      !$omp cancel taskgroup
+      a = 3.14
+    end do
+    !$omp end taskloop
+
+    !$omp taskloop nogroup
+    do i = 1, N
+      !$omp cancel taskgroup
+      a = 3.14
+    end do
+
+    !$omp parallel
+    !ERROR: With TASKGROUP clause, CANCEL construct must be closely nested inside TASK or TASKLOOP construct and CANCEL region must be closely nested inside TASKGROUP region
+    !$omp cancel taskgroup
+    a = 3.14
+    !$omp end parallel
+
+    !$omp do
+    do i = 1, N
+      !$omp task
+      !$omp cancel taskgroup
+      a = 3.14
+      !$omp end task
+    end do
+    !$omp end do
+
+    !$omp parallel
+    !$omp taskgroup
+    !$omp task
+    !$omp cancel taskgroup
+    a = 3.14
+    !$omp end task
+    !$omp end taskgroup
+    !$omp end parallel
+
+    !$omp parallel
+    !$omp task
+    !ERROR: With TASKGROUP clause, CANCEL construct must be closely nested inside TASK or TASKLOOP construct and CANCEL region must be closely nested inside TASKGROUP region
+    !$omp cancel taskgroup
+    a = 3.14
+    !$omp end task
+    !$omp end parallel
+
+    !$omp parallel
+    !$omp do
+    do i = 1, N
+      !$omp task
+      !ERROR: With TASKGROUP clause, CANCEL construct must be closely nested inside TASK or TASKLOOP construct and CANCEL region must be closely nested inside TASKGROUP region
+      !$omp cancel taskgroup
+      a = 3.14
+      !$omp end task
+    end do
+    !$omp end do
+    !$omp end parallel
+
+    !$omp target parallel
+    !$omp task
+    !ERROR: With TASKGROUP clause, CANCEL construct must be closely nested inside TASK or TASKLOOP construct and CANCEL region must be closely nested inside TASKGROUP region
+    !$omp cancel taskgroup
+    a = 3.14
+    !$omp end task
+    !$omp end target parallel
+
+    !$omp parallel
+    !$omp taskloop private(j) nogroup
+    do i = 1, N
+      !ERROR: With TASKGROUP clause, CANCEL construct must be closely nested inside TASK or TASKLOOP construct and CANCEL region must be closely nested inside TASKGROUP region
+      !$omp cancel taskgroup
+      a = 3.14
+    end do
+    !$omp end taskloop
+    !$omp end parallel
+
+    !$omp parallel
+    !$omp taskloop
+    do i = 1, N
+      !$omp cancel taskgroup
+      a = 3.14
+    end do
+    !$omp end taskloop
+    !$omp end parallel
+
+    !$omp parallel
+    !$omp taskgroup
+    !$omp taskloop nogroup
+    do i = 1, N
+      !$omp cancel taskgroup
+      a = 3.14
+    end do
+    !$omp end taskloop
+    !$omp end taskgroup
+    !$omp end parallel
+
+    !$omp target parallel
+    !$omp taskloop nogroup
+    do i = 1, N
+      !ERROR: With TASKGROUP clause, CANCEL construct must be closely nested inside TASK or TASKLOOP construct and CANCEL region must be closely nested inside TASKGROUP region
+      !$omp cancel taskgroup
+      a = 3.14
+    end do
+    !$omp end taskloop
+    !$omp end target parallel
+  end subroutine sub1
+
+end program main

diff  --git a/flang/test/Semantics/omp-nested-cancellation-point.f90 b/flang/test/Semantics/omp-nested-cancellation-point.f90
new file mode 100644
index 0000000000000..a139bfae5d202
--- /dev/null
+++ b/flang/test/Semantics/omp-nested-cancellation-point.f90
@@ -0,0 +1,250 @@
+! RUN: %S/test_errors.sh %s %t %flang -fopenmp
+! REQUIRES: shell
+
+! OpenMP Version 5.0
+! Check OpenMP construct validity for the following directives:
+! 2.18.2 Cancellation Point Construct
+
+program main
+  integer :: i, N = 10
+  real :: a
+
+  !ERROR: CANCELLATION POINT TASKGROUP directive is not closely nested inside TASK or TASKLOOP
+  !$omp cancellation point taskgroup
+
+  !ERROR: CANCELLATION POINT SECTIONS directive is not closely nested inside SECTION or SECTIONS
+  !$omp cancellation point sections
+
+  !ERROR: CANCELLATION POINT DO directive is not closely nested inside the construct that matches the DO clause type
+  !$omp cancellation point do
+
+  !ERROR: CANCELLATION POINT PARALLEL directive is not closely nested inside the construct that matches the PARALLEL clause type
+  !$omp cancellation point parallel
+
+  !$omp parallel
+  !$omp sections
+  !$omp cancellation point sections
+  !$omp section
+  a = 3.14
+  !$omp end sections
+  !$omp end parallel
+
+  !$omp sections
+  !$omp section
+  !$omp cancellation point sections
+  a = 3.14
+  !$omp end sections
+
+  !$omp parallel
+  !ERROR: With SECTIONS clause, CANCELLATION POINT construct cannot be closely nested inside PARALLEL construct
+  !$omp cancellation point sections
+  a = 3.14
+  !$omp end parallel
+
+  !$omp parallel sections
+  !$omp cancellation point sections
+  a = 3.14
+  !$omp end parallel sections
+
+  !$omp do
+  do i = 1, N
+    a = 3.14
+    !$omp cancellation point do
+  end do
+  !$omp end do
+
+  !$omp parallel do
+  do i = 1, N
+    a = 3.14
+    !$omp cancellation point do
+  end do
+  !$omp end parallel do
+
+  !$omp target
+  !$omp teams
+  !$omp distribute parallel do
+  do i = 1, N
+    a = 3.14
+    !$omp cancellation point do
+  end do
+  !$omp end distribute parallel do
+  !$omp end teams
+  !$omp end target
+
+  !$omp target
+  !$omp teams distribute parallel do
+  do i = 1, N
+    a = 3.14
+    !$omp cancellation point do
+  end do
+  !$omp end teams distribute parallel do
+  !$omp end target
+
+  !$omp target teams distribute parallel do
+  do i = 1, N
+    a = 3.14
+    !$omp cancellation point do
+  end do
+  !$omp end target teams distribute parallel do
+
+  !$omp target parallel do
+  do i = 1, N
+    a = 3.14
+    !$omp cancellation point do
+  end do
+  !$omp end target parallel do
+
+  !$omp parallel
+  do i = 1, N
+    a = 3.14
+    !ERROR: With DO clause, CANCELLATION POINT construct cannot be closely nested inside PARALLEL construct
+    !$omp cancellation point do
+  end do
+  !$omp end parallel
+
+  !$omp parallel
+  do i = 1, N
+    a = 3.14
+    !$omp cancellation point parallel
+  end do
+  !$omp end parallel
+
+  !$omp target parallel
+  do i = 1, N
+    a = 3.14
+    !$omp cancellation point parallel
+  end do
+  !$omp end target parallel
+
+  !$omp target parallel do
+  do i = 1, N
+    a = 3.14
+    !ERROR: With PARALLEL clause, CANCELLATION POINT construct cannot be closely nested inside TARGET PARALLEL DO construct
+    !$omp cancellation point parallel
+  end do
+  !$omp end target parallel do
+
+  !$omp do
+  do i = 1, N
+    a = 3.14
+    !ERROR: With PARALLEL clause, CANCELLATION POINT construct cannot be closely nested inside DO construct
+    !$omp cancellation point parallel
+  end do
+  !$omp end do
+
+contains
+  subroutine sub1()
+    !$omp task
+    !$omp cancellation point taskgroup
+    a = 3.14
+    !$omp end task
+
+    !$omp taskloop
+    do i = 1, N
+      !$omp parallel
+      !$omp end parallel
+      !$omp cancellation point taskgroup
+      a = 3.14
+    end do
+    !$omp end taskloop
+
+    !$omp taskloop nogroup
+    do i = 1, N
+      !$omp cancellation point taskgroup
+      a = 3.14
+    end do
+
+    !$omp parallel
+    !ERROR: With TASKGROUP clause, CANCELLATION POINT construct must be closely nested inside TASK or TASKLOOP construct and CANCELLATION POINT region must be closely nested inside TASKGROUP region
+    !$omp cancellation point taskgroup
+    a = 3.14
+    !$omp end parallel
+
+    !$omp do
+    do i = 1, N
+      !$omp task
+      !$omp cancellation point taskgroup
+      a = 3.14
+      !$omp end task
+    end do
+    !$omp end do
+
+    !$omp parallel
+    !$omp taskgroup
+    !$omp task
+    !$omp cancellation point taskgroup
+    a = 3.14
+    !$omp end task
+    !$omp end taskgroup
+    !$omp end parallel
+
+    !$omp parallel
+    !$omp task
+    !ERROR: With TASKGROUP clause, CANCELLATION POINT construct must be closely nested inside TASK or TASKLOOP construct and CANCELLATION POINT region must be closely nested inside TASKGROUP region
+    !$omp cancellation point taskgroup
+    a = 3.14
+    !$omp end task
+    !$omp end parallel
+
+    !$omp parallel
+    !$omp do
+    do i = 1, N
+      !$omp task
+      !ERROR: With TASKGROUP clause, CANCELLATION POINT construct must be closely nested inside TASK or TASKLOOP construct and CANCELLATION POINT region must be closely nested inside TASKGROUP region
+      !$omp cancellation point taskgroup
+      a = 3.14
+      !$omp end task
+    end do
+    !$omp end do
+    !$omp end parallel
+
+    !$omp target parallel
+    !$omp task
+    !ERROR: With TASKGROUP clause, CANCELLATION POINT construct must be closely nested inside TASK or TASKLOOP construct and CANCELLATION POINT region must be closely nested inside TASKGROUP region
+    !$omp cancellation point taskgroup
+    a = 3.14
+    !$omp end task
+    !$omp end target parallel
+
+    !$omp parallel
+    !$omp taskloop private(j) nogroup
+    do i = 1, N
+      !ERROR: With TASKGROUP clause, CANCELLATION POINT construct must be closely nested inside TASK or TASKLOOP construct and CANCELLATION POINT region must be closely nested inside TASKGROUP region
+      !$omp cancellation point taskgroup
+      a = 3.14
+    end do
+    !$omp end taskloop
+    !$omp end parallel
+
+    !$omp parallel
+    !$omp taskloop
+    do i = 1, N
+      !$omp cancellation point taskgroup
+      a = 3.14
+    end do
+    !$omp end taskloop
+    !$omp end parallel
+
+    !$omp parallel
+    !$omp taskgroup
+    !$omp taskloop nogroup
+    do i = 1, N
+      !$omp cancellation point taskgroup
+      a = 3.14
+    end do
+    !$omp end taskloop
+    !$omp end taskgroup
+    !$omp end parallel
+
+    !$omp target parallel
+    !$omp taskloop nogroup
+    do i = 1, N
+      !ERROR: With TASKGROUP clause, CANCELLATION POINT construct must be closely nested inside TASK or TASKLOOP construct and CANCELLATION POINT region must be closely nested inside TASKGROUP region
+      !$omp cancellation point taskgroup
+      a = 3.14
+    end do
+    !$omp end taskloop
+    !$omp end target parallel
+  end subroutine sub1
+
+end program main


        


More information about the flang-commits mailing list