[flang-commits] [flang] 3883e26 - [flang][OpenMP] Add semantic check for target nesting

via flang-commits flang-commits at lists.llvm.org
Tue Aug 17 18:46:01 PDT 2021


Author: PeixinQiao
Date: 2021-08-18T09:40:52+08:00
New Revision: 3883e266f4abd33e19a7c656dde19b6f5c7fc134

URL: https://github.com/llvm/llvm-project/commit/3883e266f4abd33e19a7c656dde19b6f5c7fc134
DIFF: https://github.com/llvm/llvm-project/commit/3883e266f4abd33e19a7c656dde19b6f5c7fc134.diff

LOG: [flang][OpenMP] Add semantic check for target nesting

This patch implements the following check for TARGET construct:
```
OpenMP Version 5.0 Target construct restriction: If a target update,
target data, target enter data, or target exit data construct is
encountered during execution of a target region, the behavior is
unspecified.
```

Also add one test case for the check.

Reviewed By: kiranchandramohan, clementval

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

Added: 
    flang/test/Semantics/omp-nested-target.f90

Modified: 
    flang/lib/Semantics/check-omp-structure.cpp
    flang/lib/Semantics/check-omp-structure.h

Removed: 
    


################################################################################
diff  --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 366a6506a8ec4..a81914f7db278 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -288,6 +288,9 @@ void OmpStructureChecker::Enter(const parser::OpenMPConstruct &x) {
     if (GetDirectiveNest(SIMDNest) > 0) {
       CheckSIMDNest(x);
     }
+    if (GetDirectiveNest(TargetNest) > 0) {
+      CheckTargetNest(x);
+    }
   }
 }
 
@@ -473,6 +476,53 @@ void OmpStructureChecker::CheckSIMDNest(const parser::OpenMPConstruct &c) {
   }
 }
 
+void OmpStructureChecker::CheckTargetNest(const parser::OpenMPConstruct &c) {
+  // 2.12.5 Target Construct Restriction
+  bool eligibleTarget{true};
+  llvm::omp::Directive ineligibleTargetDir;
+  std::visit(
+      common::visitors{
+          [&](const parser::OpenMPBlockConstruct &c) {
+            const auto &beginBlockDir{
+                std::get<parser::OmpBeginBlockDirective>(c.t)};
+            const auto &beginDir{
+                std::get<parser::OmpBlockDirective>(beginBlockDir.t)};
+            if (beginDir.v == llvm::omp::Directive::OMPD_target_data) {
+              eligibleTarget = false;
+              ineligibleTargetDir = beginDir.v;
+            }
+          },
+          [&](const parser::OpenMPStandaloneConstruct &c) {
+            std::visit(
+                common::visitors{
+                    [&](const parser::OpenMPSimpleStandaloneConstruct &c) {
+                      const auto &dir{
+                          std::get<parser::OmpSimpleStandaloneDirective>(c.t)};
+                      if (dir.v == llvm::omp::Directive::OMPD_target_update ||
+                          dir.v ==
+                              llvm::omp::Directive::OMPD_target_enter_data ||
+                          dir.v ==
+                              llvm::omp::Directive::OMPD_target_exit_data) {
+                        eligibleTarget = false;
+                        ineligibleTargetDir = dir.v;
+                      }
+                    },
+                    [&](const auto &c) {},
+                },
+                c.u);
+          },
+          [&](const auto &c) {},
+      },
+      c.u);
+  if (!eligibleTarget) {
+    context_.Say(parser::FindSourceLocation(c),
+        "If %s directive is nested inside TARGET region, the behaviour "
+        "is unspecified"_en_US,
+        parser::ToUpperCaseLetters(
+            getDirectiveName(ineligibleTargetDir).str()));
+  }
+}
+
 std::int64_t OmpStructureChecker::GetOrdCollapseLevel(
     const parser::OpenMPLoopConstruct &x) {
   const auto &beginLoopDir{std::get<parser::OmpBeginLoopDirective>(x.t)};
@@ -616,6 +666,9 @@ void OmpStructureChecker::Enter(const parser::OpenMPBlockConstruct &x) {
   CheckMatching<parser::OmpBlockDirective>(beginDir, endDir);
 
   PushContextAndClauseSets(beginDir.source, beginDir.v);
+  if (GetContext().directive == llvm::omp::Directive::OMPD_target) {
+    EnterDirectiveNest(TargetNest);
+  }
 
   if (CurrentDirectiveIsNested()) {
     CheckIfDoOrderedClause(beginDir);
@@ -710,6 +763,9 @@ void OmpStructureChecker::Leave(const parser::OpenMPBlockConstruct &) {
   if (GetDirectiveNest(TargetBlockOnlyTeams)) {
     ExitDirectiveNest(TargetBlockOnlyTeams);
   }
+  if (GetContext().directive == llvm::omp::Directive::OMPD_target) {
+    ExitDirectiveNest(TargetNest);
+  }
   dirContext_.pop_back();
 }
 

diff  --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index 03cd1f8d3f298..bd0d8100ddd3d 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -226,6 +226,7 @@ class OmpStructureChecker
   void CheckCycleConstraints(const parser::OpenMPLoopConstruct &x);
   void CheckDistLinear(const parser::OpenMPLoopConstruct &x);
   void CheckSIMDNest(const parser::OpenMPConstruct &x);
+  void CheckTargetNest(const parser::OpenMPConstruct &x);
   void CheckCancellationNest(
       const parser::CharBlock &source, const parser::OmpCancelType::Type &type);
   std::int64_t GetOrdCollapseLevel(const parser::OpenMPLoopConstruct &x);
@@ -253,7 +254,12 @@ class OmpStructureChecker
   void ExitDirectiveNest(const int index) { directiveNest_[index]--; }
   int GetDirectiveNest(const int index) { return directiveNest_[index]; }
 
-  enum directiveNestType { SIMDNest, TargetBlockOnlyTeams, LastType };
+  enum directiveNestType {
+    SIMDNest,
+    TargetBlockOnlyTeams,
+    TargetNest,
+    LastType
+  };
   int directiveNest_[LastType + 1] = {0};
 };
 } // namespace Fortran::semantics

diff  --git a/flang/test/Semantics/omp-nested-target.f90 b/flang/test/Semantics/omp-nested-target.f90
new file mode 100644
index 0000000000000..da4d1619f1063
--- /dev/null
+++ b/flang/test/Semantics/omp-nested-target.f90
@@ -0,0 +1,54 @@
+! RUN: %S/test_errors.sh %s %t %flang_fc1 -fopenmp
+! REQUIRES: shell
+
+! OpenMP Version 5.0
+! Check OpenMP construct validity for the following directives:
+! 2.12.5 Target Construct
+
+program main
+  integer :: i, j, N = 10
+  real :: a, arrayA(512), arrayB(512), ai(10)
+  real, allocatable :: B(:)
+
+  !$omp target
+  !WARNING: If TARGET UPDATE directive is nested inside TARGET region, the behaviour is unspecified
+  !$omp target update from(arrayA) to(arrayB)
+  do i = 1, 512
+    arrayA(i) = arrayB(i)
+  end do
+  !$omp end target
+
+  !$omp parallel
+  !$omp target
+  !$omp parallel
+  !WARNING: If TARGET UPDATE directive is nested inside TARGET region, the behaviour is unspecified
+  !$omp target update from(arrayA) to(arrayB)
+  do i = 1, 512
+    arrayA(i) = arrayB(i)
+  end do
+  !$omp end parallel
+  !$omp end target
+  !$omp end parallel
+
+  !$omp target
+  !WARNING: If TARGET DATA directive is nested inside TARGET region, the behaviour is unspecified
+  !$omp target data map(to: a)
+  do i = 1, N
+    a = 3.14
+  end do
+  !$omp end target data
+  !$omp end target
+
+  allocate(B(N))
+  !$omp target
+  !WARNING: If TARGET ENTER DATA directive is nested inside TARGET region, the behaviour is unspecified
+  !$omp target enter data map(alloc:B)
+  !$omp end target
+
+  !$omp target
+  !WARNING: If TARGET EXIT DATA directive is nested inside TARGET region, the behaviour is unspecified
+  !$omp target exit data map(delete:B)
+  !$omp end target
+  deallocate(B)
+
+end program main


        


More information about the flang-commits mailing list