diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h index 1c4d2daef2a11..353260b2e5c02 100644 --- a/flang/include/flang/Parser/dump-parse-tree.h +++ b/flang/include/flang/Parser/dump-parse-tree.h @@ -588,6 +588,8 @@ class ParseTreeDumper { NODE(parser, OmpExpectation) NODE_ENUM(OmpExpectation, Value) NODE(parser, OmpFailClause) + NODE(parser, OmpFallbackModifier) + NODE_ENUM(OmpFallbackModifier, Value) NODE(parser, OmpFromClause) NODE(OmpFromClause, Modifier) NODE(parser, OmpGrainsizeClause) diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h index cd9429b9631d6..2f6b95b2fa2a8 100644 --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -4000,6 +4000,17 @@ struct OmpExpectation { WRAPPER_CLASS_BOILERPLATE(OmpExpectation, Value); }; +// Ref: [6.1:tbd] +// +// fallback-modifier -> +// FALLBACK(fallback-mode) // since 6.1 +// fallback-mode -> +// ABORT | DEFAULT_MEM | NULL // since 6.1 +struct OmpFallbackModifier { + ENUM_CLASS(Value, Abort, Default_Mem, Null); + WRAPPER_CLASS_BOILERPLATE(OmpFallbackModifier, Value); +}; + // REF: [5.1:217-220], [5.2:293-294] // // OmpInteropRuntimeIdentifier -> // since 5.2 @@ -4129,9 +4140,8 @@ struct OmpOrderModifier { // // prescriptiveness -> // STRICT // since 5.1 -// FALLBACK // since 6.1 struct OmpPrescriptiveness { - ENUM_CLASS(Value, Strict, Fallback) + ENUM_CLASS(Value, Strict) WRAPPER_CLASS_BOILERPLATE(OmpPrescriptiveness, Value); }; @@ -4512,7 +4522,7 @@ struct OmpDynamicAllocatorsClause { struct OmpDynGroupprivateClause { TUPLE_CLASS_BOILERPLATE(OmpDynGroupprivateClause); - MODIFIER_BOILERPLATE(OmpAccessGroup, OmpPrescriptiveness); + MODIFIER_BOILERPLATE(OmpAccessGroup, OmpFallbackModifier); std::tuple t; }; diff --git a/flang/include/flang/Semantics/openmp-modifiers.h b/flang/include/flang/Semantics/openmp-modifiers.h index bfa3aa4939cb1..283bf2a4c895e 100644 --- a/flang/include/flang/Semantics/openmp-modifiers.h +++ b/flang/include/flang/Semantics/openmp-modifiers.h @@ -67,6 +67,7 @@ template const OmpModifierDescriptor &OmpGetDescriptor(); #define DECLARE_DESCRIPTOR(name) \ template <> const OmpModifierDescriptor &OmpGetDescriptor() +DECLARE_DESCRIPTOR(parser::OmpAccessGroup); DECLARE_DESCRIPTOR(parser::OmpAlignment); DECLARE_DESCRIPTOR(parser::OmpAlignModifier); DECLARE_DESCRIPTOR(parser::OmpAllocatorComplexModifier); @@ -82,6 +83,7 @@ DECLARE_DESCRIPTOR(parser::OmpDependenceType); DECLARE_DESCRIPTOR(parser::OmpDeviceModifier); DECLARE_DESCRIPTOR(parser::OmpDirectiveNameModifier); DECLARE_DESCRIPTOR(parser::OmpExpectation); +DECLARE_DESCRIPTOR(parser::OmpFallbackModifier); DECLARE_DESCRIPTOR(parser::OmpInteropPreference); DECLARE_DESCRIPTOR(parser::OmpInteropType); DECLARE_DESCRIPTOR(parser::OmpIterator); diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp index 2575b7081039b..002b7c1888e73 100644 --- a/flang/lib/Lower/OpenMP/Clauses.cpp +++ b/flang/lib/Lower/OpenMP/Clauses.cpp @@ -396,8 +396,6 @@ makePrescriptiveness(parser::OmpPrescriptiveness::Value v) { switch (v) { case parser::OmpPrescriptiveness::Value::Strict: return clause::Prescriptiveness::Strict; - case parser::OmpPrescriptiveness::Value::Fallback: - return clause::Prescriptiveness::Fallback; } llvm_unreachable("Unexpected prescriptiveness"); } @@ -799,21 +797,31 @@ DynGroupprivate make(const parser::OmpClause::DynGroupprivate &inp, semantics::SemanticsContext &semaCtx) { // imp.v -> OmpDyngroupprivateClause CLAUSET_ENUM_CONVERT( // - convert, parser::OmpAccessGroup::Value, DynGroupprivate::AccessGroup, + makeAccessGroup, parser::OmpAccessGroup::Value, + DynGroupprivate::AccessGroup, // clang-format off MS(Cgroup, Cgroup) // clang-format on ); + CLAUSET_ENUM_CONVERT( // + makeFallback, parser::OmpFallbackModifier::Value, + DynGroupprivate::Fallback, + // clang-format off + MS(Abort, Abort) + MS(Default_Mem, Default_Mem) + MS(Null, Null) + // clang-format on + ); + auto &mods = semantics::OmpGetModifiers(inp.v); auto *m0 = semantics::OmpGetUniqueModifier(mods); - auto *m1 = semantics::OmpGetUniqueModifier(mods); + auto *m1 = semantics::OmpGetUniqueModifier(mods); auto &size = std::get(inp.v.t); - return DynGroupprivate{ - {/*AccessGroup=*/maybeApplyToV(convert, m0), - /*Prescriptiveness=*/maybeApplyToV(makePrescriptiveness, m1), - /*Size=*/makeExpr(size, semaCtx)}}; + return DynGroupprivate{{/*AccessGroup=*/maybeApplyToV(makeAccessGroup, m0), + /*Fallback=*/maybeApplyToV(makeFallback, m1), + /*Size=*/makeExpr(size, semaCtx)}}; } Enter make(const parser::OmpClause::Enter &inp, diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp index 4374acbbe51bf..e2da60ed19de8 100644 --- a/flang/lib/Parser/openmp-parsers.cpp +++ b/flang/lib/Parser/openmp-parsers.cpp @@ -791,6 +791,12 @@ TYPE_PARSER(construct(OmpDirectiveNameParser{})) TYPE_PARSER(construct( // "PRESENT" >> pure(OmpExpectation::Value::Present))) +TYPE_PARSER(construct("FALLBACK"_tok >> + parenthesized( // + "ABORT" >> pure(OmpFallbackModifier::Value::Abort) || + "DEFAULT_MEM" >> pure(OmpFallbackModifier::Value::Default_Mem) || + "NULL" >> pure(OmpFallbackModifier::Value::Null)))) + TYPE_PARSER(construct( construct(charLiteralConstant) || construct(scalarIntConstantExpr))) @@ -857,8 +863,7 @@ TYPE_PARSER(construct( "SIMD" >> pure(OmpOrderingModifier::Value::Simd))) TYPE_PARSER(construct( - "STRICT" >> pure(OmpPrescriptiveness::Value::Strict) || - "FALLBACK" >> pure(OmpPrescriptiveness::Value::Fallback))) + "STRICT" >> pure(OmpPrescriptiveness::Value::Strict))) TYPE_PARSER(construct( // "PRESENT" >> pure(OmpPresentModifier::Value::Present))) @@ -925,7 +930,7 @@ TYPE_PARSER( // sourced(construct( Parser{})) || sourced(construct( - Parser{}))) + Parser{}))) TYPE_PARSER( sourced(construct(Parser{}))) diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp index dc0f083c9fc95..53e74298f96ac 100644 --- a/flang/lib/Parser/unparse.cpp +++ b/flang/lib/Parser/unparse.cpp @@ -2286,6 +2286,11 @@ class UnparseVisitor { Walk(std::get(x.t)); Walk(": ", std::get>>(x.t)); } + void Unparse(const OmpFallbackModifier &x) { + Word("FALLBACK("); + Walk(x.v); + Put(")"); + } void Unparse(const OmpDynGroupprivateClause &x) { using Modifier = OmpDynGroupprivateClause::Modifier; Walk(std::get>>(x.t), ": "); @@ -2795,6 +2800,7 @@ class UnparseVisitor { OmpDeviceTypeClause, DeviceTypeDescription) // OMP device_type WALK_NESTED_ENUM(OmpReductionModifier, Value) // OMP reduction-modifier WALK_NESTED_ENUM(OmpExpectation, Value) // OMP motion-expectation + WALK_NESTED_ENUM(OmpFallbackModifier, Value) // OMP fallback-modifier WALK_NESTED_ENUM(OmpInteropType, Value) // OMP InteropType WALK_NESTED_ENUM(OmpOrderClause, Ordering) // OMP ordering WALK_NESTED_ENUM(OmpOrderModifier, Value) // OMP order-modifier diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index 91308281f2cb6..b6d9197cfe956 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -682,6 +682,13 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Hint &x) { } } +void OmpStructureChecker::Enter(const parser::OmpClause::DynGroupprivate &x) { + CheckAllowedClause(llvm::omp::Clause::OMPC_dyn_groupprivate); + parser::CharBlock source{GetContext().clauseSource}; + + OmpVerifyModifiers(x.v, llvm::omp::OMPC_dyn_groupprivate, source, context_); +} + void OmpStructureChecker::Enter(const parser::OmpDirectiveSpecification &x) { // OmpDirectiveSpecification exists on its own only in METADIRECTIVE. // In other cases it's a part of other constructs that handle directive @@ -3316,6 +3323,32 @@ void OmpStructureChecker::Leave(const parser::OmpClauseList &) { } } + // Default access-group for DYN_GROUPPRIVATE is "cgroup". On a given + // construct there can be at most one DYN_GROUPPRIVATE with a given + // access-group. + const parser::OmpClause + *accGrpClause[parser::OmpAccessGroup::Value_enumSize] = {nullptr}; + for (auto [_, clause] : + FindClauses(llvm::omp::Clause::OMPC_dyn_groupprivate)) { + auto &wrapper{std::get(clause->u)}; + auto &modifiers{OmpGetModifiers(wrapper.v)}; + auto accGrp{parser::OmpAccessGroup::Value::Cgroup}; + if (auto *ag{OmpGetUniqueModifier(modifiers)}) { + accGrp = ag->v; + } + auto &firstClause{accGrpClause[llvm::to_underlying(accGrp)]}; + if (firstClause) { + context_ + .Say(clause->source, + "The access-group modifier can only occur on a single clause in a construct"_err_en_US) + .Attach(firstClause->source, + "Previous clause with access-group modifier"_en_US); + break; + } else { + firstClause = clause; + } + } + CheckRequireAtLeastOneOf(); } @@ -5473,7 +5506,6 @@ CHECK_SIMPLE_CLAUSE(Default, OMPC_default) CHECK_SIMPLE_CLAUSE(Depobj, OMPC_depobj) CHECK_SIMPLE_CLAUSE(DeviceType, OMPC_device_type) CHECK_SIMPLE_CLAUSE(DistSchedule, OMPC_dist_schedule) -CHECK_SIMPLE_CLAUSE(DynGroupprivate, OMPC_dyn_groupprivate) CHECK_SIMPLE_CLAUSE(Exclusive, OMPC_exclusive) CHECK_SIMPLE_CLAUSE(Fail, OMPC_fail) CHECK_SIMPLE_CLAUSE(Filter, OMPC_filter) diff --git a/flang/lib/Semantics/openmp-modifiers.cpp b/flang/lib/Semantics/openmp-modifiers.cpp index 717fb0351ba5b..f191b4de2d579 100644 --- a/flang/lib/Semantics/openmp-modifiers.cpp +++ b/flang/lib/Semantics/openmp-modifiers.cpp @@ -74,6 +74,22 @@ unsigned OmpModifierDescriptor::since(llvm::omp::Clause id) const { // Note: The intent for these functions is to have them be automatically- // generated in the future. +template <> +const OmpModifierDescriptor &OmpGetDescriptor() { + static const OmpModifierDescriptor desc{ + /*name=*/"access-group", + /*props=*/ + { + {61, {OmpProperty::Unique}}, + }, + /*clauses=*/ + { + {61, {Clause::OMPC_dyn_groupprivate}}, + }, + }; + return desc; +} + template <> const OmpModifierDescriptor &OmpGetDescriptor() { static const OmpModifierDescriptor desc{ @@ -321,6 +337,22 @@ const OmpModifierDescriptor &OmpGetDescriptor() { return desc; } +template <> +const OmpModifierDescriptor &OmpGetDescriptor() { + static const OmpModifierDescriptor desc{ + /*name=*/"fallback-modifier", + /*props=*/ + { + {61, {OmpProperty::Unique}}, + }, + /*clauses=*/ + { + {61, {Clause::OMPC_dyn_groupprivate}}, + }, + }; + return desc; +} + template <> const OmpModifierDescriptor &OmpGetDescriptor() { static const OmpModifierDescriptor desc{ diff --git a/flang/test/Parser/OpenMP/dyn-groupprivate-clause.f90 b/flang/test/Parser/OpenMP/dyn-groupprivate-clause.f90 index 7d41efd348e50..599821dbe3377 100644 --- a/flang/test/Parser/OpenMP/dyn-groupprivate-clause.f90 +++ b/flang/test/Parser/OpenMP/dyn-groupprivate-clause.f90 @@ -26,21 +26,21 @@ subroutine f00(n) subroutine f01(n) implicit none integer :: n - !$omp target dyn_groupprivate(strict: n) + !$omp target dyn_groupprivate(fallback(abort): n) !$omp end target end !UNPARSE: SUBROUTINE f01 (n) !UNPARSE: IMPLICIT NONE !UNPARSE: INTEGER n -!UNPARSE: !$OMP TARGET DYN_GROUPPRIVATE(STRICT: n) +!UNPARSE: !$OMP TARGET DYN_GROUPPRIVATE(FALLBACK(ABORT): n) !UNPARSE: !$OMP END TARGET !UNPARSE: END SUBROUTINE !PARSE-TREE: OmpBeginDirective !PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = target !PARSE-TREE: | OmpClauseList -> OmpClause -> DynGroupprivate -> OmpDynGroupprivateClause -!PARSE-TREE: | | Modifier -> OmpPrescriptiveness -> Value = Strict +!PARSE-TREE: | | Modifier -> OmpFallbackModifier -> Value = Abort !PARSE-TREE: | | Scalar -> Integer -> Expr = 'n' !PARSE-TREE: | | | Designator -> DataRef -> Name = 'n' !PARSE-TREE: | Flags = None @@ -49,21 +49,21 @@ subroutine f01(n) subroutine f02(n) implicit none integer :: n - !$omp target dyn_groupprivate(fallback, cgroup: n) + !$omp target dyn_groupprivate(fallback(default_mem), cgroup: n) !$omp end target end !UNPARSE: SUBROUTINE f02 (n) !UNPARSE: IMPLICIT NONE !UNPARSE: INTEGER n -!UNPARSE: !$OMP TARGET DYN_GROUPPRIVATE(FALLBACK, CGROUP: n) +!UNPARSE: !$OMP TARGET DYN_GROUPPRIVATE(FALLBACK(DEFAULT_MEM), CGROUP: n) !UNPARSE: !$OMP END TARGET !UNPARSE: END SUBROUTINE !PARSE-TREE: OmpBeginDirective !PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = target !PARSE-TREE: | OmpClauseList -> OmpClause -> DynGroupprivate -> OmpDynGroupprivateClause -!PARSE-TREE: | | Modifier -> OmpPrescriptiveness -> Value = Fallback +!PARSE-TREE: | | Modifier -> OmpFallbackModifier -> Value = Default_Mem !PARSE-TREE: | | Modifier -> OmpAccessGroup -> Value = Cgroup !PARSE-TREE: | | Scalar -> Integer -> Expr = 'n' !PARSE-TREE: | | | Designator -> DataRef -> Name = 'n' diff --git a/flang/test/Semantics/OpenMP/dyn-groupprivate.f90 b/flang/test/Semantics/OpenMP/dyn-groupprivate.f90 new file mode 100644 index 0000000000000..f77a0b0d35f44 --- /dev/null +++ b/flang/test/Semantics/OpenMP/dyn-groupprivate.f90 @@ -0,0 +1,8 @@ +!RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=61 + +subroutine f00(x) + integer :: x + !ERROR: The access-group modifier can only occur on a single clause in a construct + !$omp target dyn_groupprivate(cgroup: x), dyn_groupprivate(10) + !$omp end target +end diff --git a/llvm/include/llvm/Frontend/OpenMP/ClauseT.h b/llvm/include/llvm/Frontend/OpenMP/ClauseT.h index 12dfb6c607bb9..67ebafc89cf99 100644 --- a/llvm/include/llvm/Frontend/OpenMP/ClauseT.h +++ b/llvm/include/llvm/Frontend/OpenMP/ClauseT.h @@ -241,7 +241,7 @@ ENUM(MotionExpectation, Present); // V5.2: [15.9.1] `task-dependence-type` modifier ENUM(DependenceType, Depobj, In, Inout, Inoutset, Mutexinoutset, Out, Sink, Source); -ENUM(Prescriptiveness, Strict, Fallback); +ENUM(Prescriptiveness, Strict); template // struct LoopIterationT { @@ -591,10 +591,10 @@ struct DynamicAllocatorsT { template // struct DynGroupprivateT { ENUM(AccessGroup, Cgroup); - using Prescriptiveness = type::Prescriptiveness; + ENUM(Fallback, Abort, Default_Mem, Null); using Size = E; using TupleTrait = std::true_type; - std::tuple t; + std::tuple t; }; // V5.2: [5.8.4] `enter` clause