[flang-commits] [flang] [llvm] [Flang][OpenMP] Add semantic checks for order clause (PR #115281)

Thirumalai Shaktivel via flang-commits flang-commits at lists.llvm.org
Thu Nov 7 02:23:16 PST 2024


https://github.com/Thirumalai-Shaktivel updated https://github.com/llvm/llvm-project/pull/115281

>From d184299bff1934db7ad4874a2fd9f857082417b7 Mon Sep 17 00:00:00 2001
From: Thirumalai-Shaktivel <thirumalaishaktivel at gmail.com>
Date: Thu, 7 Nov 2024 10:22:41 +0000
Subject: [PATCH] [LLVM-Flang][OpenMP] Add semantic checks for order clause

Fix:
- Move the order clause to allowedOnceClauses list in the
`OMP_DistributeParallelDoSimd` and `OMP_TargetParallelDoSimd`
definitions

OpenMP 5.2:
10.3 Order clause restrictions
- A region that corresponds to a construct with an order clause that
  specifies concurrent may not contain calls to procedures that
  contain OpenMP directives.
- A region that corresponds to a construct with an order clause that
  specifies concurrent may not contain OpenMP runtime API calls.

OpenMP 5.1:
2.11.3 order Clause restriction:
- At most one order clause may appear on a construct.
---
 flang/lib/Semantics/check-omp-structure.cpp   | 39 +++++++++++
 flang/lib/Semantics/check-omp-structure.h     |  4 ++
 .../test/Semantics/OpenMP/order-clause02.f90  | 64 +++++++++++++++++++
 llvm/include/llvm/Frontend/OpenMP/OMP.td      |  8 ++-
 4 files changed, 113 insertions(+), 2 deletions(-)
 create mode 100644 flang/test/Semantics/OpenMP/order-clause02.f90

diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 014604627f2cd1..3c12afb82db9e5 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -598,6 +598,45 @@ void OmpStructureChecker::Enter(const parser::OpenMPLoopConstruct &x) {
     CheckDistLinear(x);
   }
 }
+
+void OmpStructureChecker::CheckSymbolsForOrderClause(
+    const parser::Name &name, bool checkAPICall) {
+  if (!dirContext_.empty() &&
+      (llvm::omp::allDoSet | llvm::omp::allSimdSet |
+          llvm::omp::allDistributeSet)
+          .test(GetContext().directive)) {
+    if (const auto *clause{FindClause(llvm::omp::Clause::OMPC_order)}) {
+      const auto &orderClause{std::get<parser::OmpClause::Order>(clause->u)};
+      if (std::get<parser::OmpOrderClause::Type>(orderClause.v.t) ==
+          parser::OmpOrderClause::Type::Concurrent) {
+        if (checkAPICall &&
+            llvm::StringRef(name.ToString()).starts_with_insensitive("omp_")) {
+          context_.Say(name.source,
+              "The OpenMP runtime API calls are not allowed in "
+              "the `order(concurrent)` clause region"_err_en_US);
+        } else if (name.symbol->test(Symbol::Flag::OmpThreadprivate)) {
+          context_.Say(name.source,
+              "A THREADPRIVATE variable cannot appear in an "
+              "`order(concurrent)` clause region, the behavior "
+              "is unspecified"_err_en_US);
+        }
+      }
+    }
+  }
+}
+
+// OpenMP 5.2: 10.3 Order clause restrictions
+void OmpStructureChecker::Enter(const parser::ProcedureDesignator &x) {
+  const auto &name{std::get<parser::Name>(x.u)};
+  CheckSymbolsForOrderClause(name, true);
+}
+
+// OpenMP 5.2: 10.3 Order clause restrictions
+void OmpStructureChecker::Enter(const parser::Designator &x) {
+  const auto name{parser::Unwrap<parser::Name>(x.u)};
+  CheckSymbolsForOrderClause(*name, false);
+}
+
 const parser::Name OmpStructureChecker::GetLoopIndex(
     const parser::DoConstruct *x) {
   using Bounds = parser::LoopControl::Bounds;
diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index d9236be8bced4f..1ae5bfae1a58d4 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -131,6 +131,9 @@ class OmpStructureChecker
   void Enter(const parser::OmpAtomicCapture &);
   void Leave(const parser::OmpAtomic &);
 
+  void Enter(const parser::ProcedureDesignator &);
+  void Enter(const parser::Designator &);
+
 #define GEN_FLANG_CLAUSE_CHECK_ENTER
 #include "llvm/Frontend/OpenMP/OMP.inc"
 
@@ -230,6 +233,7 @@ class OmpStructureChecker
       const parser::OmpObjectList &ompObjectList);
   void CheckPredefinedAllocatorRestriction(
       const parser::CharBlock &source, const parser::Name &name);
+  void CheckSymbolsForOrderClause(const parser::Name &name, bool checkAPICall);
   bool isPredefinedAllocator{false};
 
   void CheckAllowedRequiresClause(llvmOmpClause clause);
diff --git a/flang/test/Semantics/OpenMP/order-clause02.f90 b/flang/test/Semantics/OpenMP/order-clause02.f90
new file mode 100644
index 00000000000000..c39fb27d657fcc
--- /dev/null
+++ b/flang/test/Semantics/OpenMP/order-clause02.f90
@@ -0,0 +1,64 @@
+! REQUIRES: openmp_runtime
+! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags -fopenmp-version=50
+! OpenMP Version 5.2
+! Various checks for the order clause
+! 10.3 `order` Clause
+
+! Case 1
+subroutine omp_order_runtime_api_call_01()
+    use omp_lib
+    integer :: i
+    !$omp do order(concurrent)
+    do i = 1, 5
+        !ERROR: The OpenMP runtime API calls are not allowed in the `order(concurrent)` clause region
+        print*, omp_get_thread_num()
+    end do
+    !$omp end do
+end subroutine omp_order_runtime_api_call_01
+
+subroutine omp_order_runtime_api_call_02()
+    use omp_lib
+    integer :: i, num_threads
+    !$omp do order(concurrent)
+    do i = 1, 5
+        !ERROR: The OpenMP runtime API calls are not allowed in the `order(concurrent)` clause region
+        call omp_set_num_threads(num_threads)
+    end do
+    !$omp end do
+end subroutine omp_order_runtime_api_call_02
+
+! Case 2
+subroutine test_order_threadprivate()
+    integer :: i, j = 1, x
+    !$omp threadprivate(j)
+    !$omp parallel do order(concurrent)
+    do i = 1, 5
+        !ERROR: A THREADPRIVATE variable cannot appear in an `order(concurrent)` clause region, the behavior is unspecified
+        j = x + 1
+    end do
+    !$omp end parallel do
+end subroutine
+
+! Case 3
+subroutine omp_order_duplicate_01()
+    implicit none
+    integer :: i, j
+    !ERROR: At most one ORDER clause can appear on the TARGET PARALLEL DO SIMD directive
+    !$OMP target parallel do simd ORDER(concurrent) ORDER(concurrent)
+    do i = 1, 5
+        j = j + 1
+    end do
+    !$omp end target parallel do simd
+end subroutine
+
+subroutine omp_order_duplicate_02()
+    integer :: i, j
+    !$omp teams
+    !ERROR: At most one ORDER clause can appear on the DISTRIBUTE PARALLEL DO SIMD directive
+    !$omp distribute parallel do simd order(concurrent) order(concurrent)
+    do i = 1, 5
+        j = j + 1
+    end do
+    !$omp end distribute parallel do simd
+    !$omp end teams
+end subroutine
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td
index 36834939d9b451..29f6e65f43b38a 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMP.td
+++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td
@@ -1235,7 +1235,6 @@ def OMP_DistributeParallelDoSimd : Directive<"distribute parallel do simd"> {
     VersionedClause<OMPC_Linear>,
     VersionedClause<OMPC_NonTemporal>,
     VersionedClause<OMPC_NumThreads>,
-    VersionedClause<OMPC_Order, 50>,
     VersionedClause<OMPC_Private>,
     VersionedClause<OMPC_ProcBind>,
     VersionedClause<OMPC_Reduction>,
@@ -1244,6 +1243,9 @@ def OMP_DistributeParallelDoSimd : Directive<"distribute parallel do simd"> {
     VersionedClause<OMPC_Shared>,
     VersionedClause<OMPC_SimdLen>,
   ];
+  let allowedOnceClauses = [
+    VersionedClause<OMPC_Order, 50>,
+  ];
   let leafConstructs = [OMP_Distribute, OMP_Parallel, OMP_Do, OMP_Simd];
   let category = CA_Executable;
 }
@@ -1908,7 +1910,6 @@ def OMP_TargetParallelDoSimd : Directive<"target parallel do simd"> {
     VersionedClause<OMPC_NonTemporal>,
     VersionedClause<OMPC_NoWait>,
     VersionedClause<OMPC_NumThreads>,
-    VersionedClause<OMPC_Order, 50>,
     VersionedClause<OMPC_Ordered>,
     VersionedClause<OMPC_Private>,
     VersionedClause<OMPC_ProcBind>,
@@ -1919,6 +1920,9 @@ def OMP_TargetParallelDoSimd : Directive<"target parallel do simd"> {
     VersionedClause<OMPC_SimdLen>,
     VersionedClause<OMPC_UsesAllocators>,
   ];
+  let allowedOnceClauses = [
+    VersionedClause<OMPC_Order, 50>
+  ];
   let leafConstructs = [OMP_Target, OMP_Parallel, OMP_Do, OMP_Simd];
   let category = CA_Executable;
 }



More information about the flang-commits mailing list