[flang][OpenMP] Add semantic check for close nesting of `master` regions
authorArnamoy Bhattacharyya <arnamoy.bhattacharyya@huawei.com>
Thu, 13 May 2021 18:56:07 +0000 (14:56 -0400)
committerArnamoy Bhattacharyya <arnamoy.bhattacharyya@huawei.com>
Thu, 13 May 2021 18:58:37 +0000 (14:58 -0400)
This patch implements the following semantic check:
```
A master region may not be closely nested inside a work-sharing, loop, atomic, task, or taskloop region.
```

Adds a test case and also modifies a couple of existing test cases to include the check.

Reviewed By: kiranchandramohan

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

flang/lib/Semantics/check-omp-structure.cpp
flang/lib/Semantics/check-omp-structure.h
flang/test/Semantics/omp-nested-master.f90 [new file with mode: 0644]
flang/test/Semantics/omp-ordered-simd.f90

index 2903a41..b5658c6 100644 (file)
@@ -504,6 +504,9 @@ void OmpStructureChecker::Enter(const parser::OpenMPBlockConstruct &x) {
     if (llvm::omp::teamSet.test(GetContextParent().directive)) {
       HasInvalidTeamsNesting(beginDir.v, beginDir.source);
     }
+    if (GetContext().directive == llvm::omp::Directive::OMPD_master) {
+      CheckMasterNesting(x);
+    }
   }
 
   CheckNoBranching(block, beginDir.v, beginDir.source);
@@ -526,6 +529,20 @@ void OmpStructureChecker::Enter(const parser::OpenMPBlockConstruct &x) {
   }
 }
 
+void OmpStructureChecker::CheckMasterNesting(
+    const parser::OpenMPBlockConstruct &x) {
+  // A MASTER region may not be `closely nested` inside a worksharing, loop,
+  // task, taskloop, or atomic region.
+  // TODO:  Expand the check to include `LOOP` construct as well when it is
+  // supported.
+  if (IsCloselyNestedRegion(llvm::omp::nestedMasterErrSet)) {
+    context_.Say(parser::FindSourceLocation(x),
+        "`MASTER` region may not be closely nested inside of `WORKSHARING`, "
+        "`LOOP`, `TASK`, `TASKLOOP`,"
+        " or `ATOMIC` region."_err_en_US);
+  }
+}
+
 void OmpStructureChecker::CheckIfDoOrderedClause(
     const parser::OmpBlockDirective &blkDirective) {
   if (blkDirective.v == llvm::omp::OMPD_ordered) {
index fbbe8ae..1dfaa52 100644 (file)
@@ -93,6 +93,9 @@ static OmpDirectiveSet nestedWorkshareErrSet{
         Directive::OMPD_critical, Directive::OMPD_ordered,
         Directive::OMPD_atomic, Directive::OMPD_master} |
     workShareSet};
+static OmpDirectiveSet nestedMasterErrSet{
+    OmpDirectiveSet{llvm::omp::Directive::OMPD_atomic} | taskGeneratingSet |
+    workShareSet};
 static OmpClauseSet privateSet{
     Clause::OMPC_private, Clause::OMPC_firstprivate, Clause::OMPC_lastprivate};
 static OmpClauseSet privateReductionSet{
@@ -222,6 +225,7 @@ private:
   bool CheckIntrinsicOperator(
       const parser::DefinedOperator::IntrinsicOperator &);
   void CheckReductionTypeList(const parser::OmpClause::Reduction &);
+  void CheckMasterNesting(const parser::OpenMPBlockConstruct &x);
   void CheckReductionArraySection(const parser::OmpObjectList &ompObjectList);
   void CheckIntentInPointerAndDefinable(
       const parser::OmpObjectList &, const llvm::omp::Clause);
diff --git a/flang/test/Semantics/omp-nested-master.f90 b/flang/test/Semantics/omp-nested-master.f90
new file mode 100644 (file)
index 0000000..7353127
--- /dev/null
@@ -0,0 +1,149 @@
+! RUN: %S/test_errors.sh %s %t %flang_fc1 -fopenmp
+! OpenMP Version 4.5
+! Various checks with the nesting of MASTER construct
+
+program omp_nest_master
+  integer i, k, j
+  k = 0;
+
+  !$omp do
+  do i = 1, 10
+    k = k + 1
+    !ERROR: `MASTER` region may not be closely nested inside of `WORKSHARING`, `LOOP`, `TASK`, `TASKLOOP`, or `ATOMIC` region.
+    !$omp master
+    j = j -1
+    !$omp end master
+  end do
+
+  !$omp sections 
+  !ERROR: `MASTER` region may not be closely nested inside of `WORKSHARING`, `LOOP`, `TASK`, `TASKLOOP`, or `ATOMIC` region.
+    !$omp master
+    do i = 1, 10
+      k = k + 1
+    end do
+    !$omp end master
+  !$omp end sections
+
+  !$omp single 
+  !ERROR: `MASTER` region may not be closely nested inside of `WORKSHARING`, `LOOP`, `TASK`, `TASKLOOP`, or `ATOMIC` region.
+    !$omp master
+    do i = 1, 10
+      k = k + 1
+    end do
+    !$omp end master
+  !$omp end single
+
+
+
+  !$omp task
+  do i = 1, 10
+    k = k + 1
+    !ERROR: `MASTER` region may not be closely nested inside of `WORKSHARING`, `LOOP`, `TASK`, `TASKLOOP`, or `ATOMIC` region.
+    !$omp master
+    j = j -1
+    !$omp end master
+  end do
+  !$omp end task
+
+  !$omp taskloop
+  do i = 1, 10
+    k = k + 1
+    !ERROR: `MASTER` region may not be closely nested inside of `WORKSHARING`, `LOOP`, `TASK`, `TASKLOOP`, or `ATOMIC` region.
+    !$omp master
+    j = j -1
+    !$omp end master
+  end do
+  !$omp end taskloop
+
+  !$omp target parallel do simd
+  do i = 1, 10
+    k = k + 1
+    !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct and the `ORDERED` construct with the `SIMD` clause.
+    !ERROR: `MASTER` region may not be closely nested inside of `WORKSHARING`, `LOOP`, `TASK`, `TASKLOOP`, or `ATOMIC` region.
+    !$omp master
+    j = j -1
+    !$omp end master
+  end do
+  !$omp end target parallel do simd
+
+  !$omp critical
+  do i = 1, 10
+    k = k + 1
+    !$omp master
+    j = j -1
+    !$omp end master
+  end do
+  !$omp end critical
+
+  !$omp ordered
+  do i = 1, 10
+    k = k + 1
+    !$omp master
+    j = j -1
+    !$omp end master
+  end do
+  !$omp end ordered
+
+  !$omp ordered
+  do i = 1, 10
+    !$omp teams
+    !$omp distribute
+    do k =1, 10
+      print *, "hello"
+      !$omp master
+      j = j -1
+      !$omp end master
+    end do
+    !$omp end distribute
+    !$omp end teams
+  end do
+  !$omp end ordered
+
+  !$omp critical
+  do i = 1, 10
+    !$omp teams
+    !$omp distribute
+    do k =1, 10
+      print *, "hello"
+      !$omp master
+      j = j -1
+      !$omp end master
+    end do
+    !$omp end distribute
+    !$omp end teams
+  end do
+  !$omp end critical
+
+  !$omp taskloop
+  do i = 1, 10
+    !$omp teams
+    !$omp distribute
+    do k =1, 10
+      print *, "hello"
+      !ERROR: `MASTER` region may not be closely nested inside of `WORKSHARING`, `LOOP`, `TASK`, `TASKLOOP`, or `ATOMIC` region.
+      !$omp master
+      j = j -1
+      !$omp end master
+    end do
+    !$omp end distribute
+    !$omp end teams
+  end do
+  !$omp end taskloop
+
+  !$omp task
+  do i = 1, 10
+    !$omp teams
+    !$omp distribute
+    do k =1, 10
+      print *, "hello"
+      !ERROR: `MASTER` region may not be closely nested inside of `WORKSHARING`, `LOOP`, `TASK`, `TASKLOOP`, or `ATOMIC` region.
+      !$omp master
+      j = j -1
+      !$omp end master
+    end do
+    !$omp end distribute
+    !$omp end teams
+  end do
+  !$omp end task
+
+end program omp_nest_master
index 8350a9e..753ff78 100644 (file)
@@ -119,6 +119,7 @@ SUBROUTINE ORDERED_BAD(N)
 
   !$OMP TASK  
     C =  C - A * B
+    !ERROR: `MASTER` region may not be closely nested inside of `WORKSHARING`, `LOOP`, `TASK`, `TASKLOOP`, or `ATOMIC` region.
     !$OMP MASTER
     DO I = 1,N
       !ERROR: `ORDERED` region may not be closely nested inside of `CRITICAL`, `ORDERED`, explicit `TASK` or `TASKLOOP` region.
@@ -132,6 +133,7 @@ SUBROUTINE ORDERED_BAD(N)
   !$OMP TASKLOOP
   DO J= 1,N  
     C =  C - A * B
+    !ERROR: `MASTER` region may not be closely nested inside of `WORKSHARING`, `LOOP`, `TASK`, `TASKLOOP`, or `ATOMIC` region.
     !$OMP MASTER
     DO I = 1,N
       !ERROR: `ORDERED` region may not be closely nested inside of `CRITICAL`, `ORDERED`, explicit `TASK` or `TASKLOOP` region.