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; using Destroy = tomp::clause::DestroyT; using Detach = tomp::clause::DetachT; using Device = tomp::clause::DeviceT; +using DeviceSafesync = tomp::clause::DeviceSafesyncT; using DeviceType = tomp::clause::DeviceTypeT; using DistSchedule = tomp::clause::DistScheduleT; using Doacross = tomp::clause::DoacrossT; diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h index 35017909d9091..5677277a9b381 100644 --- a/flang/include/flang/Parser/dump-parse-tree.h +++ b/flang/include/flang/Parser/dump-parse-tree.h @@ -559,6 +559,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 bb3af9e75df3e..6dd4f2492cf22 100644 --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -4418,6 +4418,14 @@ struct OmpDeviceClause { std::tuple 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 ba34212dddba9..2a4ebf10bcafd 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 + 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 d677e14530215..56fcac3e741a9 100644 --- a/flang/lib/Parser/openmp-parsers.cpp +++ b/flang/lib/Parser/openmp-parsers.cpp @@ -1159,6 +1159,9 @@ TYPE_PARSER( // construct(Parser{}))))) || "DEVICE" >> construct(construct( parenthesized(Parser{}))) || + "DEVICE_SAFESYNC" >> + construct(construct( + maybe(parenthesized(scalarLogicalConstantExpr)))) || "DEVICE_TYPE" >> construct(construct( parenthesized(Parser{}))) || "DIST_SCHEDULE" >> diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index ea6fe43f07de8..e015e948bc701 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; if constexpr ( // + std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v || @@ -5194,6 +5195,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 { [&](auto &&s) { using TypeS = llvm::remove_cvref_t; if constexpr ( // + std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v || 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/ClauseT.h b/llvm/include/llvm/Frontend/OpenMP/ClauseT.h index 1a01fa66c5379..87b95200b2459 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 t; }; +// [6.0:362] +template // +struct DeviceSafesyncT { + using Requires = E; + using WrapperTrait = std::true_type; + OPT(Requires) v; +}; + // V5.2: [13.1] `device_type` clause template // struct DeviceTypeT { @@ -1332,14 +1340,15 @@ using WrapperClausesT = std::variant< AtomicDefaultMemOrderT, AtT, BindT, CollapseT, ContainsT, CopyinT, CopyprivateT, DefaultT, DestroyT, - DetachT, DeviceTypeT, DynamicAllocatorsT, - EnterT, ExclusiveT, FailT, FilterT, - FinalT, FirstprivateT, HasDeviceAddrT, - HintT, HoldsT, InclusiveT, IndirectT, - InitializerT, IsDevicePtrT, LinkT, - MessageT, NocontextT, NontemporalT, - NovariantsT, NumTeamsT, NumThreadsT, - OrderedT, PartialT, PriorityT, PrivateT, + DetachT, DeviceSafesyncT, DeviceTypeT, + DynamicAllocatorsT, EnterT, ExclusiveT, + FailT, FilterT, FinalT, FirstprivateT, + HasDeviceAddrT, HintT, HoldsT, + InclusiveT, IndirectT, InitializerT, + IsDevicePtrT, LinkT, MessageT, + NocontextT, NontemporalT, NovariantsT, + NumTeamsT, NumThreadsT, OrderedT, + PartialT, PriorityT, PrivateT, ProcBindT, ReverseOffloadT, SafelenT, SelfMapsT, SeverityT, SharedT, SimdlenT, SizesT, PermutationT, ThreadLimitT, diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td index edcf7a92c2a84..61a1a05f6e904 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"; } @@ -1018,6 +1022,7 @@ def OMP_Requires : Directive<[Spelling<"requires">]> { let allowedOnceClauses = [ VersionedClause, VersionedClause, + VersionedClause, // 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.