https://github.com/kparzysz updated 
https://github.com/llvm/llvm-project/pull/163560

>From 404527f36421be7ac2bc12c4f55b6aa53a51f890 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <[email protected]>
Date: Sat, 11 Oct 2025 15:25:15 -0500
Subject: [PATCH 1/2] [flang][OpenMP] Frontend support for DEVICE_SAFESYNC

Add parsing and semantic checks for DEVICE_SAFESYNC clause. No lowering.
---
 flang/include/flang/Lower/OpenMP/Clauses.h   |  1 +
 flang/include/flang/Parser/dump-parse-tree.h |  1 +
 flang/include/flang/Parser/parse-tree.h      |  8 +++++++
 flang/lib/Lower/OpenMP/Clauses.cpp           | 12 ++++++++++
 flang/lib/Parser/openmp-parsers.cpp          |  3 +++
 flang/lib/Semantics/check-omp-structure.cpp  |  5 ++++
 flang/lib/Semantics/resolve-directives.cpp   |  1 +
 llvm/include/llvm/Frontend/OpenMP/ClauseT.h  | 25 +++++++++++++-------
 llvm/include/llvm/Frontend/OpenMP/OMP.td     |  4 ++++
 9 files changed, 52 insertions(+), 8 deletions(-)

diff --git a/flang/include/flang/Lower/OpenMP/Clauses.h 
b/flang/include/flang/Lower/OpenMP/Clauses.h
index 273e61166fd9d..74924661d9a03 100644
--- a/flang/include/flang/Lower/OpenMP/Clauses.h
+++ b/flang/include/flang/Lower/OpenMP/Clauses.h
@@ -214,6 +214,7 @@ using Depend = tomp::clause::DependT<TypeTy, IdTy, ExprTy>;
 using Destroy = tomp::clause::DestroyT<TypeTy, IdTy, ExprTy>;
 using Detach = tomp::clause::DetachT<TypeTy, IdTy, ExprTy>;
 using Device = tomp::clause::DeviceT<TypeTy, IdTy, ExprTy>;
+using DeviceSafesync = tomp::clause::DeviceSafesyncT<TypeTy, IdTy, ExprTy>;
 using DeviceType = tomp::clause::DeviceTypeT<TypeTy, IdTy, ExprTy>;
 using DistSchedule = tomp::clause::DistScheduleT<TypeTy, IdTy, ExprTy>;
 using Doacross = tomp::clause::DoacrossT<TypeTy, IdTy, ExprTy>;
diff --git a/flang/include/flang/Parser/dump-parse-tree.h 
b/flang/include/flang/Parser/dump-parse-tree.h
index 8854dc2267c8e..7377a3a4e3ca1 100644
--- a/flang/include/flang/Parser/dump-parse-tree.h
+++ b/flang/include/flang/Parser/dump-parse-tree.h
@@ -557,6 +557,7 @@ class ParseTreeDumper {
   NODE(OmpDeviceClause, Modifier)
   NODE(parser, OmpDeviceModifier)
   NODE_ENUM(OmpDeviceModifier, Value)
+  NODE(parser, OmpDeviceSafesyncClause)
   NODE(parser, OmpDeviceTypeClause)
   NODE_ENUM(OmpDeviceTypeClause, DeviceTypeDescription)
   NODE(parser, OmpDirectiveName)
diff --git a/flang/include/flang/Parser/parse-tree.h 
b/flang/include/flang/Parser/parse-tree.h
index 18b583669421a..079c0d642c32b 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -4406,6 +4406,14 @@ struct OmpDeviceClause {
   std::tuple<MODIFIERS(), ScalarIntExpr> t;
 };
 
+// Ref: [6.0:356-362]
+//
+// device-safesync-clause ->
+//    DEVICE_SAFESYNC [(scalar-logical-const-expr)] // since 6.0
+struct OmpDeviceSafesyncClause {
+  WRAPPER_CLASS_BOILERPLATE(OmpDeviceSafesyncClause, 
ScalarLogicalConstantExpr);
+};
+
 // Ref: [5.0:180-185], [5.1:210-216], [5.2:275]
 //
 // device-type-clause ->
diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp 
b/flang/lib/Lower/OpenMP/Clauses.cpp
index 60e569efa964a..c11a3dda7dc41 100644
--- a/flang/lib/Lower/OpenMP/Clauses.cpp
+++ b/flang/lib/Lower/OpenMP/Clauses.cpp
@@ -740,6 +740,18 @@ Device make(const parser::OmpClause::Device &inp,
                  /*DeviceDescription=*/makeExpr(t1, semaCtx)}};
 }
 
+DeviceSafesync make(const parser::OmpClause::DeviceSafesync &inp,
+                    semantics::SemanticsContext &semaCtx) {
+  // inp.v -> std::optional<parser::OmpDeviceSafesyncClause>
+  auto &&maybeRequired = maybeApply(
+      [&](const parser::OmpDeviceSafesyncClause &c) {
+        return makeExpr(c.v, semaCtx);
+      },
+      inp.v);
+
+  return DeviceSafesync{/*Required=*/std::move(maybeRequired)};
+}
+
 DeviceType make(const parser::OmpClause::DeviceType &inp,
                 semantics::SemanticsContext &semaCtx) {
   // inp.v -> parser::OmpDeviceTypeClause
diff --git a/flang/lib/Parser/openmp-parsers.cpp 
b/flang/lib/Parser/openmp-parsers.cpp
index 0a70930a0db33..63216384a6582 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -1150,6 +1150,9 @@ TYPE_PARSER( //
             construct<OmpDestroyClause>(Parser<OmpObject>{}))))) ||
     "DEVICE" >> construct<OmpClause>(construct<OmpClause::Device>(
                     parenthesized(Parser<OmpDeviceClause>{}))) ||
+    "DEVICE_SAFESYNC" >>
+        construct<OmpClause>(construct<OmpClause::DeviceSafesync>(
+            maybe(parenthesized(scalarLogicalConstantExpr)))) ||
     "DEVICE_TYPE" >> construct<OmpClause>(construct<OmpClause::DeviceType>(
                          parenthesized(Parser<OmpDeviceTypeClause>{}))) ||
     "DIST_SCHEDULE" >>
diff --git a/flang/lib/Semantics/check-omp-structure.cpp 
b/flang/lib/Semantics/check-omp-structure.cpp
index 1c27df18fba20..7b7dfb87763a5 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -1535,6 +1535,7 @@ void OmpStructureChecker::Enter(const 
parser::OpenMPRequiresConstruct &x) {
           [&](auto &&s) {
             using TypeS = llvm::remove_cvref_t<decltype(s)>;
             if constexpr ( //
+                std::is_same_v<TypeS, parser::OmpClause::DeviceSafesync> ||
                 std::is_same_v<TypeS, parser::OmpClause::DynamicAllocators> ||
                 std::is_same_v<TypeS, parser::OmpClause::ReverseOffload> ||
                 std::is_same_v<TypeS, parser::OmpClause::SelfMaps> ||
@@ -5155,6 +5156,10 @@ void OmpStructureChecker::Enter(
   CheckAllowedRequiresClause(llvm::omp::Clause::OMPC_atomic_default_mem_order);
 }
 
+void OmpStructureChecker::Enter(const parser::OmpClause::DeviceSafesync &x) {
+  CheckAllowedRequiresClause(llvm::omp::Clause::OMPC_device_safesync);
+}
+
 void OmpStructureChecker::Enter(const parser::OmpClause::DynamicAllocators &x) 
{
   CheckAllowedRequiresClause(llvm::omp::Clause::OMPC_dynamic_allocators);
 }
diff --git a/flang/lib/Semantics/resolve-directives.cpp 
b/flang/lib/Semantics/resolve-directives.cpp
index 7067ed3d99286..db061bdce18ea 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -586,6 +586,7 @@ class OmpAttributeVisitor : 
DirectiveAttributeVisitor<llvm::omp::Directive> {
               [&](auto &&s) {
                 using TypeS = llvm::remove_cvref_t<decltype(s)>;
                 if constexpr ( //
+                    std::is_same_v<TypeS, OmpClause::DeviceSafesync> ||
                     std::is_same_v<TypeS, OmpClause::DynamicAllocators> ||
                     std::is_same_v<TypeS, OmpClause::ReverseOffload> ||
                     std::is_same_v<TypeS, OmpClause::SelfMaps> ||
diff --git a/llvm/include/llvm/Frontend/OpenMP/ClauseT.h 
b/llvm/include/llvm/Frontend/OpenMP/ClauseT.h
index 9153dd1c56b7f..09cbb7f9fcf4e 100644
--- a/llvm/include/llvm/Frontend/OpenMP/ClauseT.h
+++ b/llvm/include/llvm/Frontend/OpenMP/ClauseT.h
@@ -541,6 +541,14 @@ struct DeviceT {
   std::tuple<OPT(DeviceModifier), DeviceDescription> t;
 };
 
+// [6.0:362]
+template <typename T, typename I, typename E> //
+struct DeviceSafesyncT {
+  using Requires = E;
+  using WrapperTrait = std::true_type;
+  OPT(Requires) v;
+};
+
 // V5.2: [13.1] `device_type` clause
 template <typename T, typename I, typename E> //
 struct DeviceTypeT {
@@ -1331,14 +1339,15 @@ using WrapperClausesT = std::variant<
     AtomicDefaultMemOrderT<T, I, E>, AtT<T, I, E>, BindT<T, I, E>,
     CollapseT<T, I, E>, ContainsT<T, I, E>, CopyinT<T, I, E>,
     CopyprivateT<T, I, E>, DefaultT<T, I, E>, DestroyT<T, I, E>,
-    DetachT<T, I, E>, DeviceTypeT<T, I, E>, DynamicAllocatorsT<T, I, E>,
-    EnterT<T, I, E>, ExclusiveT<T, I, E>, FailT<T, I, E>, FilterT<T, I, E>,
-    FinalT<T, I, E>, FirstprivateT<T, I, E>, HasDeviceAddrT<T, I, E>,
-    HintT<T, I, E>, HoldsT<T, I, E>, InclusiveT<T, I, E>, IndirectT<T, I, E>,
-    InitializerT<T, I, E>, IsDevicePtrT<T, I, E>, LinkT<T, I, E>,
-    MessageT<T, I, E>, NocontextT<T, I, E>, NontemporalT<T, I, E>,
-    NovariantsT<T, I, E>, NumTeamsT<T, I, E>, NumThreadsT<T, I, E>,
-    OrderedT<T, I, E>, PartialT<T, I, E>, PriorityT<T, I, E>, PrivateT<T, I, 
E>,
+    DetachT<T, I, E>, DeviceSafesyncT<T, I, E>, DeviceTypeT<T, I, E>,
+    DynamicAllocatorsT<T, I, E>, EnterT<T, I, E>, ExclusiveT<T, I, E>,
+    FailT<T, I, E>, FilterT<T, I, E>, FinalT<T, I, E>, FirstprivateT<T, I, E>,
+    HasDeviceAddrT<T, I, E>, HintT<T, I, E>, HoldsT<T, I, E>,
+    InclusiveT<T, I, E>, IndirectT<T, I, E>, InitializerT<T, I, E>,
+    IsDevicePtrT<T, I, E>, LinkT<T, I, E>, MessageT<T, I, E>,
+    NocontextT<T, I, E>, NontemporalT<T, I, E>, NovariantsT<T, I, E>,
+    NumTeamsT<T, I, E>, NumThreadsT<T, I, E>, OrderedT<T, I, E>,
+    PartialT<T, I, E>, PriorityT<T, I, E>, PrivateT<T, I, E>,
     ProcBindT<T, I, E>, ReverseOffloadT<T, I, E>, SafelenT<T, I, E>,
     SelfMapsT<T, I, E>, SeverityT<T, I, E>, SharedT<T, I, E>, SimdlenT<T, I, 
E>,
     SizesT<T, I, E>, PermutationT<T, I, E>, ThreadLimitT<T, I, E>,
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td 
b/llvm/include/llvm/Frontend/OpenMP/OMP.td
index edcf7a92c2a84..00c43d084b216 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMP.td
+++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td
@@ -163,6 +163,10 @@ def OMPC_Device : Clause<[Spelling<"device">]> {
   let clangClass = "OMPDeviceClause";
   let flangClass = "OmpDeviceClause";
 }
+def OMPC_DeviceSafesync : Clause<[Spelling<"device_safesync">]> {
+  let flangClass = "OmpDeviceSafesyncClause";
+  let isValueOptional = true;
+}
 def OMPC_DeviceType : Clause<[Spelling<"device_type">]> {
   let flangClass = "OmpDeviceTypeClause";
 }

>From a62b3282ef80dae789fc7852a16de9632bad6705 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <[email protected]>
Date: Thu, 16 Oct 2025 11:31:49 -0500
Subject: [PATCH 2/2] bug fix + parser test

---
 flang/test/Parser/OpenMP/requires.f90    | 13 +++++++++++--
 llvm/include/llvm/Frontend/OpenMP/OMP.td |  7 ++++---
 2 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/flang/test/Parser/OpenMP/requires.f90 
b/flang/test/Parser/OpenMP/requires.f90
index 8169403835705..ab4f4371480f7 100644
--- a/flang/test/Parser/OpenMP/requires.f90
+++ b/flang/test/Parser/OpenMP/requires.f90
@@ -1,5 +1,5 @@
-!RUN: %flang_fc1 -fdebug-unparse -fopenmp -fopenmp-version=50 %s | FileCheck 
--ignore-case --check-prefix="UNPARSE" %s
-!RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp -fopenmp-version=50 %s | 
FileCheck --check-prefix="PARSE-TREE" %s
+!RUN: %flang_fc1 -fdebug-unparse -fopenmp -fopenmp-version=60 %s | FileCheck 
--ignore-case --check-prefix="UNPARSE" %s
+!RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp -fopenmp-version=60 %s | 
FileCheck --check-prefix="PARSE-TREE" %s
 
 !$omp requires atomic_default_mem_order(seq_cst)
 
@@ -44,4 +44,13 @@
 !PARSE-TREE: | | | bool = 'false'
 !PARSE-TREE: | Flags = None
 
+!$omp requires device_safesync
+
+!UNPARSE: !$OMP REQUIRES DEVICE_SAFESYNC
+
+!PARSE-TREE: OpenMPDeclarativeConstruct -> OpenMPRequiresConstruct -> 
OmpDirectiveSpecification
+!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = requires
+!PARSE-TREE: | OmpClauseList -> OmpClause -> DeviceSafesync
+!PARSE-TREE: | Flags = None
+
 end
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td 
b/llvm/include/llvm/Frontend/OpenMP/OMP.td
index 00c43d084b216..0aa674f28dc39 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMP.td
+++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td
@@ -1022,16 +1022,17 @@ def OMP_Requires : Directive<[Spelling<"requires">]> {
   let allowedOnceClauses = [
     VersionedClause<OMPC_UnifiedAddress>,
     VersionedClause<OMPC_UnifiedSharedMemory>,
+    VersionedClause<OMPC_AtomicDefaultMemOrder>,
+    VersionedClause<OMPC_DeviceSafesync, 60>,
+    VersionedClause<OMPC_DynamicAllocators>, VersionedClause<OMPC_SelfMaps>,
     // OpenMP 5.2 Spec: If an implementation is not supporting a requirement
     // (reverse offload in this case) then it should give compile-time error
     // termination.
-    // Seeting supported version for reverse_offload to a distant future 
version
+    // Setting supported version for reverse_offload to a distant future 
version
     // 9.9 so that its partial support can be tested in the meantime.
     //
     // TODO: Correct this supprted version number whenever complete
     // implementation of reverse_offload is available.
-    VersionedClause<OMPC_AtomicDefaultMemOrder>,
-    VersionedClause<OMPC_DynamicAllocators>, VersionedClause<OMPC_SelfMaps>,
     VersionedClause<OMPC_ReverseOffload, 99>,
   ];
   let association = AS_None;

_______________________________________________
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits

Reply via email to