[flang] [llvm] [Flang] Add parser support for AUTOMAP modifier (PR #151020)
Akash Banerjee via llvm-commits
llvm-commits at lists.llvm.org
Mon Jul 28 11:52:56 PDT 2025
https://github.com/TIFitis updated https://github.com/llvm/llvm-project/pull/151020
>From 732b2db252285b37c83994577ac3e67b02524441 Mon Sep 17 00:00:00 2001
From: Akash Banerjee <Akash.Banerjee at amd.com>
Date: Mon, 28 Jul 2025 19:05:25 +0100
Subject: [PATCH 1/2] [Flang] Add parser support for AUTOMAP modifier
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 | 39 +++++++++++--------
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, 126 insertions(+), 27 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 23e35d106c077..69acd31f3753f 100644
--- a/flang/include/flang/Parser/dump-parse-tree.h
+++ b/flang/include/flang/Parser/dump-parse-tree.h
@@ -581,6 +581,8 @@ class ParseTreeDumper {
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 @@ class ParseTreeDumper {
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 3a28f6f9731c3..c438ed63de798 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -3769,6 +3769,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 ->
@@ -4350,6 +4360,17 @@ struct OmpDeviceTypeClause {
WRAPPER_CLASS_BOILERPLATE(OmpDeviceTypeClause, DeviceTypeDescription);
};
+// Ref: [5.2:158-159], [6.0:289-290]
+//
+// enter-clause ->
+// ENTER(locator-list) |
+// FROM(automap-modifier: locator-list) | // since 6.0
+struct OmpEnterClause {
+ TUPLE_CLASS_BOILERPLATE(OmpEnterClause);
+ MODIFIER_BOILERPLATE(OmpAutomapModifier);
+ std::tuple<MODIFIERS(), OmpObjectList> 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 a9fe911ef8807..e0eae984731c7 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 594f95ecdda63..8eabf4f499604 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<DeclareTargetCapturePair> &result) const {
return findRepeatableClause<omp::clause::Enter>(
- [&](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<std::optional<omp::clause::Enter::Modifier>>(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<ObjectList>(clause.t),
+ mlir::omp::DeclareTargetCaptureClause::enter,
+ result);
});
}
diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp
index 686fba0154f44..46fed427923da 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<parser::OmpAutomapModifier>(mods);
+ auto &objList = std::get<parser::OmpObjectList>(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 1c626148a03ae..7fd51c63eb9d6 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -449,6 +449,9 @@ TYPE_PARSER(construct<OmpAllocatorSimpleModifier>(scalarIntExpr))
TYPE_PARSER(construct<OmpAlwaysModifier>( //
"ALWAYS" >> pure(OmpAlwaysModifier::Value::Always)))
+TYPE_PARSER(construct<OmpAutomapModifier>(
+ "AUTOMAP" >> pure(OmpAutomapModifier::Value::Automap)))
+
TYPE_PARSER(construct<OmpChunkModifier>( //
"SIMD" >> pure(OmpChunkModifier::Value::Simd)))
@@ -601,6 +604,13 @@ TYPE_PARSER(sourced(construct<OmpDependClause::TaskDep::Modifier>(sourced(
TYPE_PARSER(
sourced(construct<OmpDeviceClause::Modifier>(Parser<OmpDeviceModifier>{})))
+TYPE_PARSER(sourced(construct<OmpEnterClause::Modifier>(
+ Parser<OmpAutomapModifier>{})))
+
+TYPE_PARSER(construct<OmpEnterClause>(
+ maybe(nonemptyList(Parser<OmpEnterClause::Modifier>{}) / ":"),
+ Parser<OmpObjectList>{}))
+
TYPE_PARSER(sourced(construct<OmpFromClause::Modifier>(
sourced(construct<OmpFromClause::Modifier>(Parser<OmpExpectation>{}) ||
construct<OmpFromClause::Modifier>(Parser<OmpMapper>{}) ||
@@ -1023,7 +1033,7 @@ TYPE_PARSER( //
"DYNAMIC_ALLOCATORS" >>
construct<OmpClause>(construct<OmpClause::DynamicAllocators>()) ||
"ENTER" >> construct<OmpClause>(construct<OmpClause::Enter>(
- parenthesized(Parser<OmpObjectList>{}))) ||
+ parenthesized(Parser<OmpEnterClause>{}))) ||
"EXCLUSIVE" >> construct<OmpClause>(construct<OmpClause::Exclusive>(
parenthesized(Parser<OmpObjectList>{}))) ||
"FAIL" >> construct<OmpClause>(construct<OmpClause::Fail>(
diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index fc15d46a8c727..3c14e154edc69 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -2250,6 +2250,11 @@ class UnparseVisitor {
Walk(std::get<OmpObjectList>(x.t));
Walk(": ", std::get<std::optional<std::list<Modifier>>>(x.t));
}
+ void Unparse(const OmpEnterClause &x) {
+ using Modifier = OmpEnterClause::Modifier;
+ Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ": ");
+ Walk(std::get<OmpObjectList>(x.t));
+ }
void Unparse(const OmpFromClause &x) {
using Modifier = OmpFromClause::Modifier;
Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ": ");
@@ -2986,6 +2991,7 @@ class UnparseVisitor {
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 d214d222e7c90..2472ff99f73d4 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -1568,9 +1568,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<parser::OmpObjectList>(enterClause.v.t)};
+ CheckSymbolNames(dir.source, objList);
+ CheckVarIsNotPartOfAnotherVar(dir.source, objList);
+ CheckThreadprivateOrDeclareTargetVar(objList);
},
[&](const parser::OmpClause::DeviceType &deviceTypeClause) {
deviceTypeClauseFound = true;
@@ -2428,8 +2429,8 @@ void OmpStructureChecker::Leave(const parser::OmpClauseList &) {
&objs,
std::string clause) {
for (const auto &obj : objs.v) {
- if (const parser::Name *
- objName{parser::Unwrap<parser::Name>(obj)}) {
+ if (const parser::Name *objName{
+ parser::Unwrap<parser::Name>(obj)}) {
if (&objName->symbol->GetUltimate() == eventHandleSym) {
context_.Say(GetContext().clauseSource,
"A variable: `%s` that appears in a DETACH clause cannot appear on %s clause on the same construct"_err_en_US,
@@ -3000,7 +3001,8 @@ void OmpStructureChecker::CheckReductionModifier(
if (modifier.v == ReductionModifier::Value::Task) {
// "Task" is only allowed on worksharing or "parallel" directive.
static llvm::omp::Directive worksharing[]{
- llvm::omp::Directive::OMPD_do, llvm::omp::Directive::OMPD_scope,
+ llvm::omp::Directive::OMPD_do,
+ llvm::omp::Directive::OMPD_scope,
llvm::omp::Directive::OMPD_sections,
// There are more worksharing directives, but they do not apply:
// "for" is C++ only,
@@ -4028,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<parser::OmpObjectList>(x.v.t)};
SymbolSourceMap symbols;
GetSymbolsInObjectList(objList, symbols);
for (const auto &[symbol, source] : symbols) {
@@ -4488,17 +4494,18 @@ const parser::OmpObjectList *OmpStructureChecker::GetOmpObjectList(
const parser::OmpClause &clause) {
// Clauses with OmpObjectList as its data member
- using MemberObjectListClauses = std::tuple<parser::OmpClause::Copyprivate,
- parser::OmpClause::Copyin, parser::OmpClause::Enter,
- parser::OmpClause::Firstprivate, parser::OmpClause::Link,
- parser::OmpClause::Private, parser::OmpClause::Shared,
- parser::OmpClause::UseDevicePtr, parser::OmpClause::UseDeviceAddr>;
+ using MemberObjectListClauses =
+ std::tuple<parser::OmpClause::Copyprivate, parser::OmpClause::Copyin,
+ parser::OmpClause::Firstprivate, parser::OmpClause::Link,
+ parser::OmpClause::Private, parser::OmpClause::Shared,
+ parser::OmpClause::UseDevicePtr, parser::OmpClause::UseDeviceAddr>;
// Clauses with OmpObjectList in the tuple
- using TupleObjectListClauses = std::tuple<parser::OmpClause::Aligned,
- parser::OmpClause::Allocate, parser::OmpClause::From,
- parser::OmpClause::Lastprivate, parser::OmpClause::Map,
- parser::OmpClause::Reduction, parser::OmpClause::To>;
+ using TupleObjectListClauses =
+ std::tuple<parser::OmpClause::Aligned, parser::OmpClause::Allocate,
+ parser::OmpClause::From, parser::OmpClause::Lastprivate,
+ parser::OmpClause::Map, parser::OmpClause::Reduction,
+ parser::OmpClause::To, parser::OmpClause::Enter>;
// 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 336ce4beb24ba..af4000c4934ea 100644
--- a/flang/lib/Semantics/openmp-modifiers.cpp
+++ b/flang/lib/Semantics/openmp-modifiers.cpp
@@ -156,6 +156,22 @@ const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpAlwaysModifier>() {
return desc;
}
+template <>
+const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpAutomapModifier>() {
+ static const OmpModifierDescriptor desc{
+ /*name=*/"automap-modifier",
+ /*props=*/
+ {
+ {60, {OmpProperty::Unique}},
+ },
+ /*clauses=*/
+ {
+ {60, {Clause::OMPC_enter}},
+ },
+ };
+ return desc;
+}
+
template <>
const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpChunkModifier>() {
static const OmpModifierDescriptor desc{
diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index 4c3e509b5a36d..cbd232a884af8 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<parser::OmpClause::Enter>(&clause.u)}) {
- ResolveOmpObjectList(enterClause->v, Symbol::Flag::OmpDeclareTarget);
+ ResolveOmpObjectList(std::get<parser::OmpObjectList>(enterClause->v.t),
+ Symbol::Flag::OmpDeclareTarget);
}
}
}
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index d08c669377cb2..2611470183e96 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -1646,7 +1646,8 @@ class OmpVisitor : public virtual DeclarationVisitor {
populateDeclareTargetNames(linkClause->v);
} else if (const auto *enterClause{
std::get_if<parser::OmpClause::Enter>(&clause.u)}) {
- populateDeclareTargetNames(enterClause->v);
+ populateDeclareTargetNames(
+ std::get<parser::OmpObjectList>(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 0000000000000..1f361ca5c2f06
--- /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 7919f7a8b0c34..ce1cedc188fbf 100644
--- a/llvm/include/llvm/Frontend/OpenMP/ClauseT.h
+++ b/llvm/include/llvm/Frontend/OpenMP/ClauseT.h
@@ -578,8 +578,9 @@ struct DynamicAllocatorsT {
template <typename T, typename I, typename E> //
struct EnterT {
using List = ObjectListT<I, E>;
- using WrapperTrait = std::true_type;
- List v;
+ ENUM(Modifier, Automap);
+ using TupleTrait = std::true_type;
+ std::tuple<OPT(Modifier), List> 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 1b94657dfae1e..f11eccc215bc2 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";
>From 7e76c064a8b32bc09a7718d0f63fef80811acaff Mon Sep 17 00:00:00 2001
From: Akash Banerjee <akash.banerjee at amd.com>
Date: Mon, 28 Jul 2025 19:52:48 +0100
Subject: [PATCH 2/2] Fix comment
Co-authored-by: Copilot <175728472+Copilot at users.noreply.github.com>
---
flang/include/flang/Parser/parse-tree.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index c438ed63de798..a822cae393a3a 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -4364,7 +4364,7 @@ struct OmpDeviceTypeClause {
//
// enter-clause ->
// ENTER(locator-list) |
-// FROM(automap-modifier: locator-list) | // since 6.0
+// ENTER(automap-modifier: locator-list) | // since 6.0
struct OmpEnterClause {
TUPLE_CLASS_BOILERPLATE(OmpEnterClause);
MODIFIER_BOILERPLATE(OmpAutomapModifier);
More information about the llvm-commits
mailing list