From 9fdd1d3d468a90696b29dd035017c6f9bf2db238 Mon Sep 17 00:00:00 2001 From: Akash Banerjee Date: Thu, 31 Jul 2025 15:56:16 +0100 Subject: [PATCH] [Flang] Add parser support for AUTOMAP modifier (#151511) Add parser support for the new AUTOMAP modifier for OpenMP Declare Target Enter clause introduced in OpenMP 6.0 section 7.9.7. --- flang/include/flang/Parser/dump-parse-tree.h | 4 +++ flang/include/flang/Parser/parse-tree.h | 21 ++++++++++++ .../flang/Semantics/openmp-modifiers.h | 1 + flang/lib/Lower/OpenMP/ClauseProcessor.cpp | 10 ++++-- flang/lib/Lower/OpenMP/Clauses.cpp | 15 +++++++-- flang/lib/Parser/openmp-parsers.cpp | 12 ++++++- flang/lib/Parser/unparse.cpp | 6 ++++ flang/lib/Semantics/check-omp-structure.cpp | 32 +++++++++++-------- flang/lib/Semantics/openmp-modifiers.cpp | 16 ++++++++++ flang/lib/Semantics/resolve-directives.cpp | 3 +- flang/lib/Semantics/resolve-names.cpp | 3 +- .../Parser/OpenMP/enter-automap-modifier.f90 | 16 ++++++++++ llvm/include/llvm/Frontend/OpenMP/ClauseT.h | 5 +-- llvm/include/llvm/Frontend/OpenMP/OMP.td | 2 +- 14 files changed, 122 insertions(+), 24 deletions(-) create mode 100644 flang/test/Parser/OpenMP/enter-automap-modifier.f90 diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h index ebac54f6e29b..91414437ae70 100644 --- a/flang/include/flang/Parser/dump-parse-tree.h +++ b/flang/include/flang/Parser/dump-parse-tree.h @@ -581,6 +581,8 @@ public: NODE(parser, OmpDependClause) NODE(OmpDependClause, TaskDep) NODE(OmpDependClause::TaskDep, Modifier) + NODE(parser, OmpAutomapModifier) + NODE_ENUM(OmpAutomapModifier, Value) NODE(parser, OmpDetachClause) NODE(parser, OmpDoacrossClause) NODE(parser, OmpDestroyClause) @@ -588,6 +590,8 @@ public: NODE(parser, OmpEndCriticalDirective) NODE(parser, OmpEndLoopDirective) NODE(parser, OmpEndSectionsDirective) + NODE(parser, OmpEnterClause) + NODE(OmpEnterClause, Modifier) NODE(parser, OmpFailClause) NODE(parser, OmpFromClause) NODE(OmpFromClause, Modifier) diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h index 806eb308a112..137552fc7dd7 100644 --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -3776,6 +3776,16 @@ struct OmpAlwaysModifier { WRAPPER_CLASS_BOILERPLATE(OmpAlwaysModifier, Value); }; +// Ref: [6.0:289-290] +// +// automap-modifier -> +// automap // since 6.0 +// +struct OmpAutomapModifier { + ENUM_CLASS(Value, Automap); + WRAPPER_CLASS_BOILERPLATE(OmpAutomapModifier, Value); +}; + // Ref: [5.2:252-254] // // chunk-modifier -> @@ -4360,6 +4370,17 @@ struct OmpDeviceTypeClause { WRAPPER_CLASS_BOILERPLATE(OmpDeviceTypeClause, DeviceTypeDescription); }; +// Ref: [5.2:158-159], [6.0:289-290] +// +// enter-clause -> +// ENTER(locator-list) | +// ENTER(automap-modifier: locator-list) | // since 6.0 +struct OmpEnterClause { + TUPLE_CLASS_BOILERPLATE(OmpEnterClause); + MODIFIER_BOILERPLATE(OmpAutomapModifier); + std::tuple t; +}; + // OMP 5.2 15.8.3 extended-atomic, fail-clause -> // FAIL(memory-order) struct OmpFailClause { diff --git a/flang/include/flang/Semantics/openmp-modifiers.h b/flang/include/flang/Semantics/openmp-modifiers.h index a9fe911ef880..e0eae984731c 100644 --- a/flang/include/flang/Semantics/openmp-modifiers.h +++ b/flang/include/flang/Semantics/openmp-modifiers.h @@ -72,6 +72,7 @@ DECLARE_DESCRIPTOR(parser::OmpAlignModifier); DECLARE_DESCRIPTOR(parser::OmpAllocatorComplexModifier); DECLARE_DESCRIPTOR(parser::OmpAllocatorSimpleModifier); DECLARE_DESCRIPTOR(parser::OmpAlwaysModifier); +DECLARE_DESCRIPTOR(parser::OmpAutomapModifier); DECLARE_DESCRIPTOR(parser::OmpChunkModifier); DECLARE_DESCRIPTOR(parser::OmpCloseModifier); DECLARE_DESCRIPTOR(parser::OmpContextSelector); diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp index 594f95ecdda6..8eabf4f49960 100644 --- a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp +++ b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp @@ -1519,10 +1519,14 @@ bool ClauseProcessor::processTo( bool ClauseProcessor::processEnter( llvm::SmallVectorImpl &result) const { return findRepeatableClause( - [&](const omp::clause::Enter &clause, const parser::CharBlock &) { + [&](const omp::clause::Enter &clause, const parser::CharBlock &source) { + mlir::Location currentLocation = converter.genLocation(source); + if (std::get>(clause.t)) + TODO(currentLocation, "Declare target enter AUTOMAP modifier"); // Case: declare target enter(func, var1, var2)... - gatherFuncAndVarSyms( - clause.v, mlir::omp::DeclareTargetCaptureClause::enter, result); + gatherFuncAndVarSyms(std::get(clause.t), + mlir::omp::DeclareTargetCaptureClause::enter, + result); }); } diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp index 686fba0154f4..7f75aae09def 100644 --- a/flang/lib/Lower/OpenMP/Clauses.cpp +++ b/flang/lib/Lower/OpenMP/Clauses.cpp @@ -772,8 +772,19 @@ Doacross make(const parser::OmpClause::Doacross &inp, Enter make(const parser::OmpClause::Enter &inp, semantics::SemanticsContext &semaCtx) { - // inp.v -> parser::OmpObjectList - return Enter{makeObjects(/*List=*/inp.v, semaCtx)}; + // inp.v -> parser::OmpEnterClause + CLAUSET_ENUM_CONVERT( // + convert, parser::OmpAutomapModifier::Value, Enter::Modifier, + // clang-format off + MS(Automap, Automap) + // clang-format on + ); + auto &mods = semantics::OmpGetModifiers(inp.v); + auto *mod = semantics::OmpGetUniqueModifier(mods); + auto &objList = std::get(inp.v.t); + + return Enter{{/*Modifier=*/maybeApplyToV(convert, mod), + /*List=*/makeObjects(objList, semaCtx)}}; } Exclusive make(const parser::OmpClause::Exclusive &inp, diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp index 8c780388b9cb..9b73dc84941f 100644 --- a/flang/lib/Parser/openmp-parsers.cpp +++ b/flang/lib/Parser/openmp-parsers.cpp @@ -482,6 +482,9 @@ TYPE_PARSER(construct(scalarIntExpr)) TYPE_PARSER(construct( // "ALWAYS" >> pure(OmpAlwaysModifier::Value::Always))) +TYPE_PARSER(construct( + "AUTOMAP" >> pure(OmpAutomapModifier::Value::Automap))) + TYPE_PARSER(construct( // "SIMD" >> pure(OmpChunkModifier::Value::Simd))) @@ -636,6 +639,9 @@ TYPE_PARSER(sourced(construct(sourced( TYPE_PARSER( sourced(construct(Parser{}))) +TYPE_PARSER( + sourced(construct(Parser{}))) + TYPE_PARSER(sourced(construct( sourced(construct(Parser{}) || construct(Parser{}) || @@ -771,6 +777,10 @@ TYPE_PARSER(construct( Parser{}) || construct(indirect(Parser{})))) +TYPE_PARSER(construct( + maybe(nonemptyList(Parser{}) / ":"), + Parser{})) + TYPE_PARSER(construct( "ACQ_REL" >> pure(common::OmpMemoryOrderType::Acq_Rel) || "ACQUIRE" >> pure(common::OmpMemoryOrderType::Acquire) || @@ -1059,7 +1069,7 @@ TYPE_PARSER( // "DYNAMIC_ALLOCATORS" >> construct(construct()) || "ENTER" >> construct(construct( - parenthesized(Parser{}))) || + parenthesized(Parser{}))) || "EXCLUSIVE" >> construct(construct( parenthesized(Parser{}))) || "FAIL" >> construct(construct( diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp index 1d4d53de1491..ef209ffbbc4a 100644 --- a/flang/lib/Parser/unparse.cpp +++ b/flang/lib/Parser/unparse.cpp @@ -2250,6 +2250,11 @@ public: Walk(std::get(x.t)); Walk(": ", std::get>>(x.t)); } + void Unparse(const OmpEnterClause &x) { + using Modifier = OmpEnterClause::Modifier; + Walk(std::get>>(x.t), ": "); + Walk(std::get(x.t)); + } void Unparse(const OmpFromClause &x) { using Modifier = OmpFromClause::Modifier; Walk(std::get>>(x.t), ": "); @@ -2986,6 +2991,7 @@ public: WALK_NESTED_ENUM(UseStmt, ModuleNature) // R1410 WALK_NESTED_ENUM(OmpAdjustArgsClause::OmpAdjustOp, Value) // OMP adjustop WALK_NESTED_ENUM(OmpAtClause, ActionTime) // OMP at + WALK_NESTED_ENUM(OmpAutomapModifier, Value) // OMP automap-modifier WALK_NESTED_ENUM(OmpBindClause, Binding) // OMP bind WALK_NESTED_ENUM(OmpProcBindClause, AffinityPolicy) // OMP proc_bind WALK_NESTED_ENUM(OmpDefaultClause, DataSharingAttribute) // OMP default diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index c191ad8d088d..20a86e9d8046 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -1569,9 +1569,10 @@ void OmpStructureChecker::Leave(const parser::OpenMPDeclareTargetConstruct &x) { }, [&](const parser::OmpClause::Enter &enterClause) { enterClauseFound = true; - CheckSymbolNames(dir.source, enterClause.v); - CheckVarIsNotPartOfAnotherVar(dir.source, enterClause.v); - CheckThreadprivateOrDeclareTargetVar(enterClause.v); + auto &objList{std::get(enterClause.v.t)}; + CheckSymbolNames(dir.source, objList); + CheckVarIsNotPartOfAnotherVar(dir.source, objList); + CheckThreadprivateOrDeclareTargetVar(objList); }, [&](const parser::OmpClause::DeviceType &deviceTypeClause) { deviceTypeClauseFound = true; @@ -4029,7 +4030,11 @@ void OmpStructureChecker::Enter(const parser::OmpClause::HasDeviceAddr &x) { void OmpStructureChecker::Enter(const parser::OmpClause::Enter &x) { CheckAllowedClause(llvm::omp::Clause::OMPC_enter); - const parser::OmpObjectList &objList{x.v}; + if (!OmpVerifyModifiers( + x.v, llvm::omp::OMPC_enter, GetContext().clauseSource, context_)) { + return; + } + const parser::OmpObjectList &objList{std::get(x.v.t)}; SymbolSourceMap symbols; GetSymbolsInObjectList(objList, symbols); for (const auto &[symbol, source] : symbols) { @@ -4489,17 +4494,18 @@ const parser::OmpObjectList *OmpStructureChecker::GetOmpObjectList( const parser::OmpClause &clause) { // Clauses with OmpObjectList as its data member - using MemberObjectListClauses = std::tuple; + using MemberObjectListClauses = + std::tuple; // Clauses with OmpObjectList in the tuple - using TupleObjectListClauses = std::tuple; + using TupleObjectListClauses = + std::tuple; // TODO:: Generate the tuples using TableGen. // Handle other constructs with OmpObjectList such as OpenMPThreadprivate. diff --git a/flang/lib/Semantics/openmp-modifiers.cpp b/flang/lib/Semantics/openmp-modifiers.cpp index 336ce4beb24b..af4000c4934e 100644 --- a/flang/lib/Semantics/openmp-modifiers.cpp +++ b/flang/lib/Semantics/openmp-modifiers.cpp @@ -156,6 +156,22 @@ const OmpModifierDescriptor &OmpGetDescriptor() { return desc; } +template <> +const OmpModifierDescriptor &OmpGetDescriptor() { + static const OmpModifierDescriptor desc{ + /*name=*/"automap-modifier", + /*props=*/ + { + {60, {OmpProperty::Unique}}, + }, + /*clauses=*/ + { + {60, {Clause::OMPC_enter}}, + }, + }; + return desc; +} + template <> const OmpModifierDescriptor &OmpGetDescriptor() { static const OmpModifierDescriptor desc{ diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp index aa006b1a353e..cb68369d2a28 100644 --- a/flang/lib/Semantics/resolve-directives.cpp +++ b/flang/lib/Semantics/resolve-directives.cpp @@ -2152,7 +2152,8 @@ bool OmpAttributeVisitor::Pre(const parser::OpenMPDeclareTargetConstruct &x) { ResolveOmpObjectList(linkClause->v, Symbol::Flag::OmpDeclareTarget); } else if (const auto *enterClause{ std::get_if(&clause.u)}) { - ResolveOmpObjectList(enterClause->v, Symbol::Flag::OmpDeclareTarget); + ResolveOmpObjectList(std::get(enterClause->v.t), + Symbol::Flag::OmpDeclareTarget); } } } diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index d08c669377cb..2611470183e9 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -1646,7 +1646,8 @@ public: populateDeclareTargetNames(linkClause->v); } else if (const auto *enterClause{ std::get_if(&clause.u)}) { - populateDeclareTargetNames(enterClause->v); + populateDeclareTargetNames( + std::get(enterClause->v.t)); } } } diff --git a/flang/test/Parser/OpenMP/enter-automap-modifier.f90 b/flang/test/Parser/OpenMP/enter-automap-modifier.f90 new file mode 100644 index 000000000000..1f361ca5c2f0 --- /dev/null +++ b/flang/test/Parser/OpenMP/enter-automap-modifier.f90 @@ -0,0 +1,16 @@ +!RUN: %flang_fc1 -fdebug-unparse -fopenmp -fopenmp-version=60 %s | FileCheck %s --check-prefix=UNPARSE +!RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp -fopenmp-version=60 %s | FileCheck %s --check-prefix=PARSE-TREE + +program automap + integer :: x + !$omp declare target enter(automap: x) +end program + +!UNPARSE: PROGRAM AUTOMAP +!UNPARSE: INTEGER x +!UNPARSE: !$OMP DECLARE TARGET ENTER(AUTOMAP: x) +!UNPARSE: END PROGRAM + +!PARSE-TREE: OmpClauseList -> OmpClause -> Enter -> OmpEnterClause +!PARSE-TREE-NEXT: | Modifier -> OmpAutomapModifier -> Value = Automap +!PARSE-TREE-NEXT: | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x' diff --git a/llvm/include/llvm/Frontend/OpenMP/ClauseT.h b/llvm/include/llvm/Frontend/OpenMP/ClauseT.h index 7919f7a8b0c3..ce1cedc188fb 100644 --- a/llvm/include/llvm/Frontend/OpenMP/ClauseT.h +++ b/llvm/include/llvm/Frontend/OpenMP/ClauseT.h @@ -578,8 +578,9 @@ struct DynamicAllocatorsT { template // struct EnterT { using List = ObjectListT; - using WrapperTrait = std::true_type; - List v; + ENUM(Modifier, Automap); + using TupleTrait = std::true_type; + std::tuple t; }; // V5.2: [5.6.2] `exclusive` clause diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td index 1b94657dfae1..f11eccc215bc 100644 --- a/llvm/include/llvm/Frontend/OpenMP/OMP.td +++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td @@ -179,7 +179,7 @@ def OMPC_DynamicAllocators : Clause<[Spelling<"dynamic_allocators">]> { let clangClass = "OMPDynamicAllocatorsClause"; } def OMPC_Enter : Clause<[Spelling<"enter">]> { - let flangClass = "OmpObjectList"; + let flangClass = "OmpEnterClause"; } def OMPC_Exclusive : Clause<[Spelling<"exclusive">]> { let clangClass = "OMPExclusiveClause";