[flang-commits] [flang] [llvm] [flang][OpenMP] Sema checks, lowering with new format of MAP modifiers (PR #149137)
Krzysztof Parzyszek via flang-commits
flang-commits at lists.llvm.org
Mon Jul 21 08:57:08 PDT 2025
https://github.com/kparzysz updated https://github.com/llvm/llvm-project/pull/149137
>From 0929234481b4d6d015381fda490c05bbeff1e22f Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Wed, 16 Jul 2025 08:04:17 -0500
Subject: [PATCH 01/10] [flang][OpenMP] Parse OpenMP 6.0 map modifiers
OpenMP 6.0 has changed the modifiers on the MAP clause:
- map-type-modifier has been split into individual modifiers,
- map-type "delete" has become a modifier,
- new modifiers have been added.
This patch adds parsing support for all of the OpenMP 6.0 modifiers.
The old "map-type-modifier" is retained, but is no longer created in
parsing. It will remain to take advantage of the preexisting modifier
validation for older versions: when the OpenMP version is < 6.0,
the modifiers will be rewritten back as map-type-modifiers (or map-
type in case of "delete").
In this patch the modifiers will always be rewritten in the older
format to isolate these changes to parsing as much as possible.
---
flang/include/flang/Parser/dump-parse-tree.h | 14 ++
flang/include/flang/Parser/parse-tree.h | 138 +++++++++++++++---
.../flang/Semantics/openmp-modifiers.h | 7 +
flang/lib/Parser/openmp-parsers.cpp | 53 +++++--
flang/lib/Parser/unparse.cpp | 7 +
flang/lib/Semantics/canonicalize-omp.cpp | 48 +++++-
flang/lib/Semantics/canonicalize-omp.h | 9 +-
flang/lib/Semantics/openmp-modifiers.cpp | 115 +++++++++++++++
flang/lib/Semantics/resolve-directives.cpp | 2 +
flang/lib/Semantics/semantics.cpp | 3 +-
.../test/Parser/OpenMP/map-modifiers-v60.f90 | 113 ++++++++++++++
11 files changed, 466 insertions(+), 43 deletions(-)
create mode 100644 flang/test/Parser/OpenMP/map-modifiers-v60.f90
diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h
index 32b6ca45609b6..23e35d106c077 100644
--- a/flang/include/flang/Parser/dump-parse-tree.h
+++ b/flang/include/flang/Parser/dump-parse-tree.h
@@ -529,6 +529,8 @@ class ParseTreeDumper {
NODE(parser, OmpAlignClause)
NODE(parser, OmpAlignedClause)
NODE(OmpAlignedClause, Modifier)
+ NODE(parser, OmpAlwaysModifier)
+ NODE_ENUM(OmpAlwaysModifier, Value)
NODE(parser, OmpAtClause)
NODE_ENUM(OmpAtClause, ActionTime)
NODE_ENUM(OmpSeverityClause, Severity)
@@ -546,6 +548,8 @@ class ParseTreeDumper {
#include "llvm/Frontend/OpenMP/OMP.inc"
NODE(parser, OmpClauseList)
NODE(parser, OmpCancellationConstructTypeClause)
+ NODE(parser, OmpCloseModifier)
+ NODE_ENUM(OmpCloseModifier, Value)
NODE(parser, OmpContainsClause)
NODE(parser, OmpCriticalDirective)
NODE(parser, OmpErrorDirective)
@@ -561,6 +565,8 @@ class ParseTreeDumper {
NODE(parser, OmpDefaultmapClause)
NODE_ENUM(OmpDefaultmapClause, ImplicitBehavior)
NODE(OmpDefaultmapClause, Modifier)
+ NODE(parser, OmpDeleteModifier)
+ NODE_ENUM(OmpDeleteModifier, Value)
NODE(parser, OmpDependenceType)
NODE_ENUM(OmpDependenceType, Value)
NODE(parser, OmpTaskDependenceType)
@@ -628,6 +634,8 @@ class ParseTreeDumper {
NODE(OmpNumTasksClause, Modifier)
NODE(parser, OmpBindClause)
NODE_ENUM(OmpBindClause, Binding)
+ NODE(parser, OmpPresentModifier)
+ NODE_ENUM(OmpPresentModifier, Value)
NODE(parser, OmpProcBindClause)
NODE_ENUM(OmpProcBindClause, AffinityPolicy)
NODE(parser, OmpReductionModifier)
@@ -637,6 +645,10 @@ class ParseTreeDumper {
NODE(parser, OmpInReductionClause)
NODE(OmpInReductionClause, Modifier)
NODE(parser, OmpReductionCombiner)
+ NODE(parser, OmpRefModifier)
+ NODE_ENUM(OmpRefModifier, Value)
+ NODE(parser, OmpSelfModifier)
+ NODE_ENUM(OmpSelfModifier, Value)
NODE(parser, OmpTaskReductionClause)
NODE(OmpTaskReductionClause, Modifier)
NODE(parser, OmpInitializerProc)
@@ -673,6 +685,8 @@ class ParseTreeDumper {
NODE(parser, OmpSectionsDirective)
NODE(parser, OmpToClause)
NODE(OmpToClause, Modifier)
+ NODE(parser, OmpxHoldModifier)
+ NODE_ENUM(OmpxHoldModifier, Value)
NODE(parser, Only)
NODE(parser, OpenACCAtomicConstruct)
NODE(parser, OpenACCBlockConstruct)
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index cc1d032f94d4a..92a449d2f9d49 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -3756,6 +3756,19 @@ struct OmpAllocatorComplexModifier {
WRAPPER_CLASS_BOILERPLATE(OmpAllocatorComplexModifier, ScalarIntExpr);
};
+// Ref: [4.5:216-219], [5.0:315-324], [5.1:347-355], [5.2:150-158],
+// [6.0:279-288]
+//
+// always-modifier ->
+// ALWAYS // since 4.5
+//
+// Until 5.2, it was a part of map-type-modifier. Since 6.0 the
+// map-type-modifier has been split into individual modifiers.
+struct OmpAlwaysModifier {
+ ENUM_CLASS(Value, Always)
+ WRAPPER_CLASS_BOILERPLATE(OmpAlwaysModifier, Value);
+};
+
// Ref: [5.2:252-254]
//
// chunk-modifier ->
@@ -3767,17 +3780,29 @@ struct OmpChunkModifier {
WRAPPER_CLASS_BOILERPLATE(OmpChunkModifier, Value);
};
-// Ref: [5.0:47-49], [5.1:49-51], [5.2:67-69]
+// Ref: [4.5:216-219], [5.0:315-324], [5.1:347-355], [5.2:150-158],
+// [6.0:279-288]
//
-// iterator-specifier ->
-// [iterator-type] iterator-identifier
-// = range-specification | // since 5.0
-// [iterator-type ::] iterator-identifier
-// = range-specification // since 5.2
-struct OmpIteratorSpecifier {
- TUPLE_CLASS_BOILERPLATE(OmpIteratorSpecifier);
- CharBlock source;
- std::tuple<TypeDeclarationStmt, SubscriptTriplet> t;
+// close-modifier ->
+// CLOSE // since 5.0
+//
+// Until 5.2, it was a part of map-type-modifier. Since 6.0 the
+// map-type-modifier has been split into individual modifiers.
+struct OmpCloseModifier {
+ ENUM_CLASS(Value, Close)
+ WRAPPER_CLASS_BOILERPLATE(OmpCloseModifier, Value);
+};
+
+// Ref: [4.5:216-219], [5.0:315-324], [5.1:347-355], [5.2:150-158],
+// [6.0:279-288]
+//
+// delete-modifier ->
+// DELETE // since 6.0
+//
+// Until 5.2, it was a part of map-type.
+struct OmpDeleteModifier {
+ ENUM_CLASS(Value, Delete)
+ WRAPPER_CLASS_BOILERPLATE(OmpDeleteModifier, Value);
};
// Ref: [4.5:169-170], [5.0:255-256], [5.1:288-289]
@@ -3867,6 +3892,19 @@ struct OmpInteropType {
WRAPPER_CLASS_BOILERPLATE(OmpInteropType, Value);
};
+// Ref: [5.0:47-49], [5.1:49-51], [5.2:67-69]
+//
+// iterator-specifier ->
+// [iterator-type] iterator-identifier
+// = range-specification | // since 5.0
+// [iterator-type ::] iterator-identifier
+// = range-specification // since 5.2
+struct OmpIteratorSpecifier {
+ TUPLE_CLASS_BOILERPLATE(OmpIteratorSpecifier);
+ CharBlock source;
+ std::tuple<TypeDeclarationStmt, SubscriptTriplet> t;
+};
+
// Ref: [5.0:47-49], [5.1:49-51], [5.2:67-69]
//
// iterator-modifier ->
@@ -3901,21 +3939,28 @@ struct OmpMapper {
WRAPPER_CLASS_BOILERPLATE(OmpMapper, Name);
};
-// Ref: [4.5:216-219], [5.0:315-324], [5.1:347-355], [5.2:150-158]
+// Ref: [4.5:216-219], [5.0:315-324], [5.1:347-355], [5.2:150-158],
+// [6.0:279-288]
//
// map-type ->
-// ALLOC | DELETE | FROM | RELEASE | TO | TOFROM // since 4.5
+// ALLOC | DELETE | RELEASE | // since 4.5, until 5.2
+// FROM | TO | TOFROM | // since 4.5
+// STORAGE // since 6.0
+//
+// Since 6.0 DELETE is a separate delete-modifier.
struct OmpMapType {
- ENUM_CLASS(Value, Alloc, Delete, From, Release, To, Tofrom);
+ ENUM_CLASS(Value, Alloc, Delete, From, Release, Storage, To, Tofrom);
WRAPPER_CLASS_BOILERPLATE(OmpMapType, Value);
};
// Ref: [4.5:216-219], [5.0:315-324], [5.1:347-355], [5.2:150-158]
//
// map-type-modifier ->
-// ALWAYS | // since 4.5
-// CLOSE | // since 5.0
-// PRESENT // since 5.1
+// ALWAYS | // since 4.5, until 5.2
+// CLOSE | // since 5.0, until 5.2
+// PRESENT // since 5.1, until 5.2
+// Since 6.0 the map-type-modifier has been split into individual modifiers.
+//
struct OmpMapTypeModifier {
ENUM_CLASS(Value, Always, Close, Present, Ompx_Hold)
WRAPPER_CLASS_BOILERPLATE(OmpMapTypeModifier, Value);
@@ -3954,6 +3999,19 @@ struct OmpPrescriptiveness {
WRAPPER_CLASS_BOILERPLATE(OmpPrescriptiveness, Value);
};
+// Ref: [4.5:216-219], [5.0:315-324], [5.1:347-355], [5.2:150-158],
+// [6.0:279-288]
+//
+// present-modifier ->
+// PRESENT // since 5.1
+//
+// Until 5.2, it was a part of map-type-modifier. Since 6.0 the
+// map-type-modifier has been split into individual modifiers.
+struct OmpPresentModifier {
+ ENUM_CLASS(Value, Present)
+ WRAPPER_CLASS_BOILERPLATE(OmpPresentModifier, Value);
+};
+
// Ref: [5.0:300-302], [5.1:332-334], [5.2:134-137]
//
// reduction-modifier ->
@@ -3963,6 +4021,26 @@ struct OmpReductionModifier {
WRAPPER_CLASS_BOILERPLATE(OmpReductionModifier, Value);
};
+// Ref: [6.0:279-288]
+//
+// ref-modifier ->
+// REF_PTEE | REF_PTR | REF_PTR_PTEE // since 6.0
+//
+struct OmpRefModifier {
+ ENUM_CLASS(Value, Ref_Ptee, Ref_Ptr, Ref_Ptr_Ptee)
+ WRAPPER_CLASS_BOILERPLATE(OmpRefModifier, Value);
+};
+
+// Ref: [6.0:279-288]
+//
+// self-modifier ->
+// SELF // since 6.0
+//
+struct OmpSelfModifier {
+ ENUM_CLASS(Value, Self)
+ WRAPPER_CLASS_BOILERPLATE(OmpSelfModifier, Value);
+};
+
// Ref: [5.2:117-120]
//
// step-complex-modifier ->
@@ -4001,6 +4079,18 @@ struct OmpVariableCategory {
WRAPPER_CLASS_BOILERPLATE(OmpVariableCategory, Value);
};
+// Extension
+//
+// ompx-hold-modifier ->
+// OMPX_HOLD // since 4.5
+//
+// Until 5.2, it was a part of map-type-modifier. Since 6.0 the
+// map-type-modifier has been split into individual modifiers.
+struct OmpxHoldModifier {
+ ENUM_CLASS(Value, Ompx_Hold)
+ WRAPPER_CLASS_BOILERPLATE(OmpxHoldModifier, Value);
+};
+
// context-selector
using OmpContextSelector = traits::OmpContextSelectorSpecification;
} // namespace modifier
@@ -4376,13 +4466,25 @@ struct OmpLinearClause {
// map-clause ->
// MAP([modifier...:] locator-list) // since 4.5
// modifier ->
-// map-type-modifier | // since 4.5
+// map-type-modifier [replaced] | // since 4.5, until 5.2
+// always-modifier | // since 6.0
+// close-modifier | // since 6.0
+// delete-modifier | // since 6.0
+// present-modifier | // since 6.0
+// ref-modifier | // since 6.0
+// self-modifier | // since 6.0
// mapper | // since 5.0
// iterator | // since 5.1
// map-type // since 4.5
+// ompx-hold-modifier | // since 6.0
+//
+// Since 6.0 the map-type-modifier has been split into individual modifiers,
+// and delete-modifier has been split from map-type.
struct OmpMapClause {
TUPLE_CLASS_BOILERPLATE(OmpMapClause);
- MODIFIER_BOILERPLATE(OmpMapTypeModifier, OmpMapper, OmpIterator, OmpMapType);
+ MODIFIER_BOILERPLATE(OmpAlwaysModifier, OmpCloseModifier, OmpDeleteModifier,
+ OmpMapTypeModifier, OmpPresentModifier, OmpRefModifier, OmpSelfModifier,
+ OmpMapper, OmpIterator, OmpMapType, OmpxHoldModifier);
std::tuple<MODIFIERS(), OmpObjectList, /*CommaSeparated=*/bool> t;
};
diff --git a/flang/include/flang/Semantics/openmp-modifiers.h b/flang/include/flang/Semantics/openmp-modifiers.h
index 4fbd80f989e72..a9fe911ef8807 100644
--- a/flang/include/flang/Semantics/openmp-modifiers.h
+++ b/flang/include/flang/Semantics/openmp-modifiers.h
@@ -71,8 +71,11 @@ DECLARE_DESCRIPTOR(parser::OmpAlignment);
DECLARE_DESCRIPTOR(parser::OmpAlignModifier);
DECLARE_DESCRIPTOR(parser::OmpAllocatorComplexModifier);
DECLARE_DESCRIPTOR(parser::OmpAllocatorSimpleModifier);
+DECLARE_DESCRIPTOR(parser::OmpAlwaysModifier);
DECLARE_DESCRIPTOR(parser::OmpChunkModifier);
+DECLARE_DESCRIPTOR(parser::OmpCloseModifier);
DECLARE_DESCRIPTOR(parser::OmpContextSelector);
+DECLARE_DESCRIPTOR(parser::OmpDeleteModifier);
DECLARE_DESCRIPTOR(parser::OmpDependenceType);
DECLARE_DESCRIPTOR(parser::OmpDeviceModifier);
DECLARE_DESCRIPTOR(parser::OmpDirectiveNameModifier);
@@ -88,12 +91,16 @@ DECLARE_DESCRIPTOR(parser::OmpMapTypeModifier);
DECLARE_DESCRIPTOR(parser::OmpOrderModifier);
DECLARE_DESCRIPTOR(parser::OmpOrderingModifier);
DECLARE_DESCRIPTOR(parser::OmpPrescriptiveness);
+DECLARE_DESCRIPTOR(parser::OmpPresentModifier);
DECLARE_DESCRIPTOR(parser::OmpReductionIdentifier);
DECLARE_DESCRIPTOR(parser::OmpReductionModifier);
+DECLARE_DESCRIPTOR(parser::OmpRefModifier);
+DECLARE_DESCRIPTOR(parser::OmpSelfModifier);
DECLARE_DESCRIPTOR(parser::OmpStepComplexModifier);
DECLARE_DESCRIPTOR(parser::OmpStepSimpleModifier);
DECLARE_DESCRIPTOR(parser::OmpTaskDependenceType);
DECLARE_DESCRIPTOR(parser::OmpVariableCategory);
+DECLARE_DESCRIPTOR(parser::OmpxHoldModifier);
#undef DECLARE_DESCRIPTOR
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index 76c9499410017..d349d8ceb0bb5 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -274,6 +274,10 @@ TYPE_PARSER( //
construct<OmpTypeSpecifier>(Parser<DeclarationTypeSpec>{}) ||
construct<OmpTypeSpecifier>(Parser<TypeSpec>{}))
+// 2.15.3.6 REDUCTION (reduction-identifier: variable-name-list)
+TYPE_PARSER(construct<OmpReductionIdentifier>(Parser<DefinedOperator>{}) ||
+ construct<OmpReductionIdentifier>(Parser<ProcedureDesignator>{}))
+
TYPE_PARSER(construct<OmpReductionSpecifier>( //
Parser<OmpReductionIdentifier>{},
":"_tok >> nonemptyList(Parser<OmpTypeSpecifier>{}),
@@ -442,9 +446,18 @@ TYPE_PARSER(construct<OmpAllocatorComplexModifier>(
TYPE_PARSER(construct<OmpAllocatorSimpleModifier>(scalarIntExpr))
+TYPE_PARSER(construct<OmpAlwaysModifier>( //
+ "ALWAYS" >> pure(OmpAlwaysModifier::Value::Always)))
+
TYPE_PARSER(construct<OmpChunkModifier>( //
"SIMD" >> pure(OmpChunkModifier::Value::Simd)))
+TYPE_PARSER(construct<OmpCloseModifier>( //
+ "CLOSE" >> pure(OmpCloseModifier::Value::Close)))
+
+TYPE_PARSER(construct<OmpDeleteModifier>( //
+ "DELETE" >> pure(OmpDeleteModifier::Value::Delete)))
+
TYPE_PARSER(construct<OmpDependenceType>(
"SINK" >> pure(OmpDependenceType::Value::Sink) ||
"SOURCE" >> pure(OmpDependenceType::Value::Source)))
@@ -502,26 +515,16 @@ TYPE_PARSER(construct<OmpLinearModifier>( //
TYPE_PARSER(construct<OmpMapper>( //
"MAPPER"_tok >> parenthesized(Parser<ObjectName>{})))
-// map-type -> ALLOC | DELETE | FROM | RELEASE | TO | TOFROM
+// map-type -> ALLOC | DELETE | FROM | RELEASE | STORAGE | TO | TOFROM
TYPE_PARSER(construct<OmpMapType>( //
"ALLOC" >> pure(OmpMapType::Value::Alloc) ||
- "DELETE" >> pure(OmpMapType::Value::Delete) ||
+ // Parse "DELETE" as OmpDeleteModifier
"FROM" >> pure(OmpMapType::Value::From) ||
"RELEASE" >> pure(OmpMapType::Value::Release) ||
+ "STORAGE" >> pure(OmpMapType::Value::Storage) ||
"TO"_id >> pure(OmpMapType::Value::To) ||
"TOFROM" >> pure(OmpMapType::Value::Tofrom)))
-// map-type-modifier -> ALWAYS | CLOSE | OMPX_HOLD | PRESENT
-TYPE_PARSER(construct<OmpMapTypeModifier>(
- "ALWAYS" >> pure(OmpMapTypeModifier::Value::Always) ||
- "CLOSE" >> pure(OmpMapTypeModifier::Value::Close) ||
- "OMPX_HOLD" >> pure(OmpMapTypeModifier::Value::Ompx_Hold) ||
- "PRESENT" >> pure(OmpMapTypeModifier::Value::Present)))
-
-// 2.15.3.6 REDUCTION (reduction-identifier: variable-name-list)
-TYPE_PARSER(construct<OmpReductionIdentifier>(Parser<DefinedOperator>{}) ||
- construct<OmpReductionIdentifier>(Parser<ProcedureDesignator>{}))
-
TYPE_PARSER(construct<OmpOrderModifier>(
"REPRODUCIBLE" >> pure(OmpOrderModifier::Value::Reproducible) ||
"UNCONSTRAINED" >> pure(OmpOrderModifier::Value::Unconstrained)))
@@ -534,11 +537,22 @@ TYPE_PARSER(construct<OmpOrderingModifier>(
TYPE_PARSER(construct<OmpPrescriptiveness>(
"STRICT" >> pure(OmpPrescriptiveness::Value::Strict)))
+TYPE_PARSER(construct<OmpPresentModifier>( //
+ "PRESENT" >> pure(OmpPresentModifier::Value::Present)))
+
TYPE_PARSER(construct<OmpReductionModifier>(
"INSCAN" >> pure(OmpReductionModifier::Value::Inscan) ||
"TASK" >> pure(OmpReductionModifier::Value::Task) ||
"DEFAULT" >> pure(OmpReductionModifier::Value::Default)))
+TYPE_PARSER(construct<OmpRefModifier>( //
+ "REF_PTEE" >> pure(OmpRefModifier::Value::Ref_Ptee) ||
+ "REF_PTR"_id >> pure(OmpRefModifier::Value::Ref_Ptr) ||
+ "REF_PTR_PTEE" >> pure(OmpRefModifier::Value::Ref_Ptr_Ptee)))
+
+TYPE_PARSER(construct<OmpSelfModifier>( //
+ "SELF" >> pure(OmpSelfModifier::Value::Self)))
+
TYPE_PARSER(construct<OmpStepComplexModifier>( //
"STEP" >> parenthesized(scalarIntExpr)))
@@ -559,6 +573,9 @@ TYPE_PARSER(construct<OmpVariableCategory>(
"POINTER" >> pure(OmpVariableCategory::Value::Pointer) ||
"SCALAR" >> pure(OmpVariableCategory::Value::Scalar)))
+TYPE_PARSER(construct<OmpxHoldModifier>( //
+ "OMPX_HOLD" >> pure(OmpxHoldModifier::Value::Ompx_Hold)))
+
// This could be auto-generated.
TYPE_PARSER(
sourced(construct<OmpAffinityClause::Modifier>(Parser<OmpIterator>{})))
@@ -611,10 +628,16 @@ TYPE_PARSER(sourced(
construct<OmpLinearClause::Modifier>(Parser<OmpStepSimpleModifier>{})))
TYPE_PARSER(sourced(construct<OmpMapClause::Modifier>(
- sourced(construct<OmpMapClause::Modifier>(Parser<OmpMapTypeModifier>{}) ||
+ sourced(construct<OmpMapClause::Modifier>(Parser<OmpAlwaysModifier>{}) ||
+ construct<OmpMapClause::Modifier>(Parser<OmpCloseModifier>{}) ||
+ construct<OmpMapClause::Modifier>(Parser<OmpDeleteModifier>{}) ||
+ construct<OmpMapClause::Modifier>(Parser<OmpPresentModifier>{}) ||
+ construct<OmpMapClause::Modifier>(Parser<OmpRefModifier>{}) ||
+ construct<OmpMapClause::Modifier>(Parser<OmpSelfModifier>{}) ||
construct<OmpMapClause::Modifier>(Parser<OmpMapper>{}) ||
construct<OmpMapClause::Modifier>(Parser<OmpIterator>{}) ||
- construct<OmpMapClause::Modifier>(Parser<OmpMapType>{})))))
+ construct<OmpMapClause::Modifier>(Parser<OmpMapType>{}) ||
+ construct<OmpMapClause::Modifier>(Parser<OmpxHoldModifier>{})))))
TYPE_PARSER(
sourced(construct<OmpOrderClause::Modifier>(Parser<OmpOrderModifier>{})))
diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index fbe89c668fc13..8ed16905b5099 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -3007,8 +3007,15 @@ class UnparseVisitor {
WALK_NESTED_ENUM(OmpPrescriptiveness, Value) // OMP prescriptiveness
WALK_NESTED_ENUM(OmpMapType, Value) // OMP map-type
WALK_NESTED_ENUM(OmpMapTypeModifier, Value) // OMP map-type-modifier
+ WALK_NESTED_ENUM(OmpAlwaysModifier, Value)
+ WALK_NESTED_ENUM(OmpCloseModifier, Value)
+ WALK_NESTED_ENUM(OmpDeleteModifier, Value)
+ WALK_NESTED_ENUM(OmpPresentModifier, Value)
+ WALK_NESTED_ENUM(OmpRefModifier, Value)
+ WALK_NESTED_ENUM(OmpSelfModifier, Value)
WALK_NESTED_ENUM(OmpTraitSelectorName, Value)
WALK_NESTED_ENUM(OmpTraitSetSelectorName, Value)
+ WALK_NESTED_ENUM(OmpxHoldModifier, Value)
#undef WALK_NESTED_ENUM
void Unparse(const ReductionOperator::Operator x) {
diff --git a/flang/lib/Semantics/canonicalize-omp.cpp b/flang/lib/Semantics/canonicalize-omp.cpp
index cf05d8463277f..46aaab19ded0a 100644
--- a/flang/lib/Semantics/canonicalize-omp.cpp
+++ b/flang/lib/Semantics/canonicalize-omp.cpp
@@ -27,7 +27,8 @@ class CanonicalizationOfOmp {
public:
template <typename T> bool Pre(T &) { return true; }
template <typename T> void Post(T &) {}
- CanonicalizationOfOmp(parser::Messages &messages) : messages_{messages} {}
+ CanonicalizationOfOmp(SemanticsContext &context)
+ : context_{context}, messages_{context.messages()} {}
void Post(parser::Block &block) {
for (auto it{block.begin()}; it != block.end(); ++it) {
@@ -88,6 +89,8 @@ class CanonicalizationOfOmp {
CanonicalizeUtilityConstructs(spec);
}
+ void Post(parser::OmpMapClause &map) { CanonicalizeMapModifiers(map); }
+
private:
template <typename T> T *GetConstructIf(parser::ExecutionPartConstruct &x) {
if (auto *y{std::get_if<parser::ExecutableConstruct>(&x.u)}) {
@@ -390,16 +393,53 @@ class CanonicalizationOfOmp {
omps.erase(rlast.base(), omps.end());
}
+ // Map clause modifiers are parsed as per OpenMP 6.0 spec. That spec has
+ // changed properties of some of the modifiers, for example it has expanded
+ // map-type-modifier into 3 individual modifiers (one for each of the
+ // possible values of the original modifier), and the "map-type" modifier
+ // is no longer ultimate.
+ // To utilize the modifier validation framework for semantic checks,
+ // if the specified OpenMP version is less than 6.0, rewrite the affected
+ // modifiers back into the pre-6.0 forms.
+ void CanonicalizeMapModifiers(parser::OmpMapClause &map) {
+ // Omp{Always, Close, Present, xHold}Modifier -> OmpMapTypeModifier
+ // OmpDeleteModifier -> OmpMapType
+ using Modifier = parser::OmpMapClause::Modifier;
+ using Modifiers = std::optional<std::list<Modifier>>;
+ auto &modifiers{std::get<Modifiers>(map.t)};
+ if (!modifiers) {
+ return;
+ }
+
+ using MapTypeModifier = parser::OmpMapTypeModifier;
+ using MapType = parser::OmpMapType;
+
+ for (auto &mod : *modifiers) {
+ if (std::holds_alternative<parser::OmpAlwaysModifier>(mod.u)) {
+ mod.u = MapTypeModifier(MapTypeModifier::Value::Always);
+ } else if (std::holds_alternative<parser::OmpCloseModifier>(mod.u)) {
+ mod.u = MapTypeModifier(MapTypeModifier::Value::Close);
+ } else if (std::holds_alternative<parser::OmpPresentModifier>(mod.u)) {
+ mod.u = MapTypeModifier(MapTypeModifier::Value::Present);
+ } else if (std::holds_alternative<parser::OmpxHoldModifier>(mod.u)) {
+ mod.u = MapTypeModifier(MapTypeModifier::Value::Ompx_Hold);
+ } else if (std::holds_alternative<parser::OmpDeleteModifier>(mod.u)) {
+ mod.u = MapType(MapType::Value::Delete);
+ }
+ }
+ }
+
// Mapping from the specification parts to the blocks that follow in the
// same construct. This is for converting utility constructs to executable
// constructs.
std::map<parser::SpecificationPart *, parser::Block *> blockForSpec_;
+ SemanticsContext &context_;
parser::Messages &messages_;
};
-bool CanonicalizeOmp(parser::Messages &messages, parser::Program &program) {
- CanonicalizationOfOmp omp{messages};
+bool CanonicalizeOmp(SemanticsContext &context, parser::Program &program) {
+ CanonicalizationOfOmp omp{context};
Walk(program, omp);
- return !messages.AnyFatalError();
+ return !context.messages().AnyFatalError();
}
} // namespace Fortran::semantics
diff --git a/flang/lib/Semantics/canonicalize-omp.h b/flang/lib/Semantics/canonicalize-omp.h
index c45d6bbbf9062..3251218da35ed 100644
--- a/flang/lib/Semantics/canonicalize-omp.h
+++ b/flang/lib/Semantics/canonicalize-omp.h
@@ -11,11 +11,12 @@
namespace Fortran::parser {
struct Program;
-class Messages;
-} // namespace Fortran::parser
+}
namespace Fortran::semantics {
-bool CanonicalizeOmp(parser::Messages &messages, parser::Program &program);
-}
+class SemanticsContext;
+
+bool CanonicalizeOmp(SemanticsContext &context, parser::Program &program);
+} // namespace Fortran::semantics
#endif // FORTRAN_SEMANTICS_CANONICALIZE_OMP_H_
diff --git a/flang/lib/Semantics/openmp-modifiers.cpp b/flang/lib/Semantics/openmp-modifiers.cpp
index c84e832ee52a1..336ce4beb24ba 100644
--- a/flang/lib/Semantics/openmp-modifiers.cpp
+++ b/flang/lib/Semantics/openmp-modifiers.cpp
@@ -140,6 +140,22 @@ OmpGetDescriptor<parser::OmpAllocatorSimpleModifier>() {
return desc;
}
+template <>
+const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpAlwaysModifier>() {
+ static const OmpModifierDescriptor desc{
+ /*name=*/"always-modifier",
+ /*props=*/
+ {
+ {45, {OmpProperty::Unique}},
+ },
+ /*clauses=*/
+ {
+ {45, {Clause::OMPC_map}},
+ },
+ };
+ return desc;
+}
+
template <>
const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpChunkModifier>() {
static const OmpModifierDescriptor desc{
@@ -156,6 +172,22 @@ const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpChunkModifier>() {
return desc;
}
+template <>
+const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpCloseModifier>() {
+ static const OmpModifierDescriptor desc{
+ /*name=*/"close-modifier",
+ /*props=*/
+ {
+ {50, {OmpProperty::Unique}},
+ },
+ /*clauses=*/
+ {
+ {50, {Clause::OMPC_map}},
+ },
+ };
+ return desc;
+}
+
template <>
const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpContextSelector>() {
static const OmpModifierDescriptor desc{
@@ -173,6 +205,23 @@ const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpContextSelector>() {
return desc;
}
+template <>
+const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpDeleteModifier>() {
+ static const OmpModifierDescriptor desc{
+ /*name=*/"delete-modifier",
+ /*props=*/
+ {
+ {45, {OmpProperty::Unique, OmpProperty::Ultimate}},
+ {60, {OmpProperty::Unique}},
+ },
+ /*clauses=*/
+ {
+ {45, {Clause::OMPC_map}},
+ },
+ };
+ return desc;
+}
+
template <>
const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpDependenceType>() {
static const OmpModifierDescriptor desc{
@@ -347,6 +396,7 @@ const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpMapType>() {
/*props=*/
{
{45, {OmpProperty::Ultimate}},
+ {60, {OmpProperty::Unique}},
},
/*clauses=*/
{
@@ -367,6 +417,7 @@ const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpMapTypeModifier>() {
/*clauses=*/
{
{45, {Clause::OMPC_map}},
+ {60, {}},
},
};
return desc;
@@ -420,6 +471,22 @@ const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpPrescriptiveness>() {
return desc;
}
+template <>
+const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpPresentModifier>() {
+ static const OmpModifierDescriptor desc{
+ /*name=*/"present-modifier",
+ /*props=*/
+ {
+ {51, {OmpProperty::Unique}},
+ },
+ /*clauses=*/
+ {
+ {51, {Clause::OMPC_map}},
+ },
+ };
+ return desc;
+}
+
template <>
const OmpModifierDescriptor &
OmpGetDescriptor<parser::OmpReductionIdentifier>() {
@@ -456,6 +523,38 @@ const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpReductionModifier>() {
return desc;
}
+template <>
+const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpRefModifier>() {
+ static const OmpModifierDescriptor desc{
+ /*name=*/"ref-modifier",
+ /*props=*/
+ {
+ {60, {OmpProperty::Unique}},
+ },
+ /*clauses=*/
+ {
+ {60, {Clause::OMPC_map}},
+ },
+ };
+ return desc;
+}
+
+template <>
+const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpSelfModifier>() {
+ static const OmpModifierDescriptor desc{
+ /*name=*/"self-modifier",
+ /*props=*/
+ {
+ {60, {OmpProperty::Unique}},
+ },
+ /*clauses=*/
+ {
+ {60, {Clause::OMPC_map}},
+ },
+ };
+ return desc;
+}
+
template <>
const OmpModifierDescriptor &
OmpGetDescriptor<parser::OmpStepComplexModifier>() {
@@ -522,4 +621,20 @@ const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpVariableCategory>() {
};
return desc;
}
+
+template <>
+const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpxHoldModifier>() {
+ static const OmpModifierDescriptor desc{
+ /*name=*/"ompx-hold-modifier",
+ /*props=*/
+ {
+ {45, {OmpProperty::Unique}},
+ },
+ /*clauses=*/
+ {
+ {45, {Clause::OMPC_map}},
+ },
+ };
+ return desc;
+}
} // namespace Fortran::semantics
diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index 151f4ccae634e..0b860314b4a1f 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -734,6 +734,8 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
case parser::OmpMapType::Value::Delete:
ompFlag = Symbol::Flag::OmpMapDelete;
break;
+ default:
+ break;
}
}
const auto &ompObjList{std::get<parser::OmpObjectList>(x.t)};
diff --git a/flang/lib/Semantics/semantics.cpp b/flang/lib/Semantics/semantics.cpp
index ab78605d01f4c..d0a5b200d0d8e 100644
--- a/flang/lib/Semantics/semantics.cpp
+++ b/flang/lib/Semantics/semantics.cpp
@@ -643,8 +643,7 @@ bool Semantics::Perform() {
return ValidateLabels(context_, program_) &&
parser::CanonicalizeDo(program_) && // force line break
CanonicalizeAcc(context_.messages(), program_) &&
- CanonicalizeOmp(context_.messages(), program_) &&
- CanonicalizeCUDA(program_) &&
+ CanonicalizeOmp(context_, program_) && CanonicalizeCUDA(program_) &&
PerformStatementSemantics(context_, program_) &&
CanonicalizeDirectives(context_.messages(), program_) &&
ModFileWriter{context_}
diff --git a/flang/test/Parser/OpenMP/map-modifiers-v60.f90 b/flang/test/Parser/OpenMP/map-modifiers-v60.f90
new file mode 100644
index 0000000000000..bc80886780d46
--- /dev/null
+++ b/flang/test/Parser/OpenMP/map-modifiers-v60.f90
@@ -0,0 +1,113 @@
+!RUN: %flang_fc1 -fdebug-unparse-no-sema -fopenmp -fopenmp-version=60 %s | FileCheck --ignore-case --check-prefix="UNPARSE" %s
+!RUN: %flang_fc1 -fdebug-dump-parse-tree-no-sema -fopenmp -fopenmp-version=60 %s | FileCheck --check-prefix="PARSE-TREE" %s
+
+subroutine f00(x)
+ integer :: x
+ !$omp target map(always, close, delete, present, ompx_hold: x)
+ x = x + 1
+ !$omp end target
+end
+
+!UNPARSE: SUBROUTINE f00 (x)
+!UNPARSE: INTEGER x
+!UNPARSE: !$OMP TARGET MAP(ALWAYS, CLOSE, DELETE, PRESENT, OMPX_HOLD: x)
+!UNPARSE: x = x+1
+!UNPARSE: !$OMP END TARGET
+!UNPARSE: END SUBROUTINE
+
+!PARSE-TREE: OmpBeginBlockDirective
+!PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = target
+!PARSE-TREE: | OmpClauseList -> OmpClause -> Map -> OmpMapClause
+!PARSE-TREE: | | Modifier -> OmpAlwaysModifier -> Value = Always
+!PARSE-TREE: | | Modifier -> OmpCloseModifier -> Value = Close
+!PARSE-TREE: | | Modifier -> OmpDeleteModifier -> Value = Delete
+!PARSE-TREE: | | Modifier -> OmpPresentModifier -> Value = Present
+!PARSE-TREE: | | Modifier -> OmpxHoldModifier -> Value = Ompx_Hold
+!PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x'
+!PARSE-TREE: | | bool = 'true'
+
+subroutine f01(x)
+ integer :: x
+ !$omp target map(self, storage: x)
+ x = x + 1
+ !$omp end target
+end
+
+!UNPARSE: !$OMP TARGET MAP(SELF, STORAGE: x)
+!UNPARSE: x = x+1
+!UNPARSE: !$OMP END TARGET
+!UNPARSE: END SUBROUTINE
+
+!PARSE-TREE: OmpBeginBlockDirective
+!PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = target
+!PARSE-TREE: | OmpClauseList -> OmpClause -> Map -> OmpMapClause
+!PARSE-TREE: | | Modifier -> OmpSelfModifier -> Value = Self
+!PARSE-TREE: | | Modifier -> OmpMapType -> Value = Storage
+!PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x'
+!PARSE-TREE: | | bool = 'true'
+
+subroutine f02(x)
+ integer, pointer :: x
+ !$omp target map(ref_ptr, to: x)
+ x = x + 1
+ !$omp end target
+end
+
+!UNPARSE: SUBROUTINE f02 (x)
+!UNPARSE: INTEGER, POINTER :: x
+!UNPARSE: !$OMP TARGET MAP(REF_PTR, TO: x)
+!UNPARSE: x = x+1
+!UNPARSE: !$OMP END TARGET
+!UNPARSE: END SUBROUTINE
+
+!PARSE-TREE: OmpBeginBlockDirective
+!PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = target
+!PARSE-TREE: | OmpClauseList -> OmpClause -> Map -> OmpMapClause
+!PARSE-TREE: | | Modifier -> OmpRefModifier -> Value = Ref_Ptr
+!PARSE-TREE: | | Modifier -> OmpMapType -> Value = To
+!PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x'
+!PARSE-TREE: | | bool = 'true'
+
+subroutine f03(x)
+ integer, pointer :: x
+ !$omp target map(ref_ptee, to: x)
+ x = x + 1
+ !$omp end target
+end
+
+!UNPARSE: SUBROUTINE f03 (x)
+!UNPARSE: INTEGER, POINTER :: x
+!UNPARSE: !$OMP TARGET MAP(REF_PTEE, TO: x)
+!UNPARSE: x = x+1
+!UNPARSE: !$OMP END TARGET
+!UNPARSE: END SUBROUTINE
+
+!PARSE-TREE: OmpBeginBlockDirective
+!PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = target
+!PARSE-TREE: | OmpClauseList -> OmpClause -> Map -> OmpMapClause
+!PARSE-TREE: | | Modifier -> OmpRefModifier -> Value = Ref_Ptee
+!PARSE-TREE: | | Modifier -> OmpMapType -> Value = To
+!PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x'
+!PARSE-TREE: | | bool = 'true'
+
+subroutine f04(x)
+ integer, pointer :: x
+ !$omp target map(ref_ptr_ptee, to: x)
+ x = x + 1
+ !$omp end target
+end
+
+!UNPARSE: SUBROUTINE f04 (x)
+!UNPARSE: INTEGER, POINTER :: x
+!UNPARSE: !$OMP TARGET MAP(REF_PTR_PTEE, TO: x)
+!UNPARSE: x = x+1
+!UNPARSE: !$OMP END TARGET
+!UNPARSE: END SUBROUTINE
+
+!PARSE-TREE: OmpBeginBlockDirective
+!PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = target
+!PARSE-TREE: | OmpClauseList -> OmpClause -> Map -> OmpMapClause
+!PARSE-TREE: | | Modifier -> OmpRefModifier -> Value = Ref_Ptr_Ptee
+!PARSE-TREE: | | Modifier -> OmpMapType -> Value = To
+!PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x'
+!PARSE-TREE: | | bool = 'true'
>From acc1a7d3da0d2bd5a60096a9f5dc27338342b952 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Wed, 16 Jul 2025 08:04:17 -0500
Subject: [PATCH 02/10] [flang][OpenMP] Sema checks, lowering with new format
of MAP modifiers
OpenMP 6.0 has changed the modifiers on the MAP clause. Previous patch
has introduced parsing support for them. This patch introduces processing
of the new forms in semantic checks and in lowering. This only applies
to existing modifiers, which were updated in the 6.0 spec. Any of the
newly introduced modifiers (SELF and REF) are ignored.
---
flang/lib/Lower/OpenMP/ClauseProcessor.cpp | 16 +--
flang/lib/Lower/OpenMP/Clauses.cpp | 113 ++++++++++++------
flang/lib/Semantics/canonicalize-omp.cpp | 5 +
flang/lib/Semantics/check-omp-structure.cpp | 107 +++++++++++------
flang/lib/Semantics/check-omp-structure.h | 4 +-
flang/lib/Semantics/openmp-utils.cpp | 25 ++++
flang/lib/Semantics/openmp-utils.h | 3 +
flang/lib/Semantics/resolve-directives.cpp | 50 ++++++--
.../Semantics/OpenMP/combined-constructs.f90 | 8 +-
.../Semantics/OpenMP/device-constructs.f90 | 6 +-
llvm/include/llvm/Frontend/OpenMP/ClauseT.h | 9 +-
.../Frontend/OpenMP/ConstructDecompositionT.h | 5 +-
llvm/include/llvm/Frontend/OpenMP/OMP.h | 2 +
llvm/lib/Frontend/OpenMP/OMP.cpp | 14 +++
14 files changed, 260 insertions(+), 107 deletions(-)
diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
index 74087d42a8e6e..ec71014c36093 100644
--- a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
+++ b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
@@ -1315,7 +1315,8 @@ bool ClauseProcessor::processMap(
const parser::CharBlock &source) {
using Map = omp::clause::Map;
mlir::Location clauseLocation = converter.genLocation(source);
- const auto &[mapType, typeMods, mappers, iterator, objects] = clause.t;
+ const auto &[mapType, typeMods, refMod, mappers, iterator, objects] =
+ clause.t;
llvm::omp::OpenMPOffloadMappingFlags mapTypeBits =
llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE;
std::string mapperIdName = "__implicit_mapper";
@@ -1342,16 +1343,13 @@ bool ClauseProcessor::processMap(
mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO |
llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
break;
- case Map::MapType::Alloc:
- case Map::MapType::Release:
+ case Map::MapType::Storage:
// alloc and release is the default map_type for the Target Data
// Ops, i.e. if no bits for map_type is supplied then alloc/release
- // is implicitly assumed based on the target directive. Default
- // value for Target Data and Enter Data is alloc and for Exit Data
- // it is release.
+ // (aka storage in 6.0+) is implicitly assumed based on the target
+ // directive. Default value for Target Data and Enter Data is alloc
+ // and for Exit Data it is release.
break;
- case Map::MapType::Delete:
- mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_DELETE;
}
if (typeMods) {
@@ -1362,6 +1360,8 @@ bool ClauseProcessor::processMap(
mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
if (llvm::is_contained(*typeMods, Map::MapTypeModifier::Close))
mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_CLOSE;
+ if (llvm::is_contained(*typeMods, Map::MapTypeModifier::Delete))
+ mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_DELETE;
if (llvm::is_contained(*typeMods, Map::MapTypeModifier::OmpxHold))
mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
}
diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp
index 22a07219d3a50..18e49719b6013 100644
--- a/flang/lib/Lower/OpenMP/Clauses.cpp
+++ b/flang/lib/Lower/OpenMP/Clauses.cpp
@@ -1001,64 +1001,105 @@ Map make(const parser::OmpClause::Map &inp,
semantics::SemanticsContext &semaCtx) {
// inp.v -> parser::OmpMapClause
CLAUSET_ENUM_CONVERT( //
- convert1, parser::OmpMapType::Value, Map::MapType,
+ convert1, parser::OmpMapTypeModifier::Value, Map::MapTypeModifier,
// clang-format off
- MS(Alloc, Alloc)
- MS(Delete, Delete)
- MS(From, From)
- MS(Release, Release)
- MS(To, To)
- MS(Tofrom, Tofrom)
+ MS(Always, Always)
+ MS(Close, Close)
+ MS(Ompx_Hold, OmpxHold)
+ MS(Present, Present)
// clang-format on
);
CLAUSET_ENUM_CONVERT( //
- convert2, parser::OmpMapTypeModifier::Value, Map::MapTypeModifier,
+ convert2, parser::OmpRefModifier::Value, Map::RefModifier,
// clang-format off
- MS(Always, Always)
- MS(Close, Close)
- MS(Ompx_Hold, OmpxHold)
- MS(Present, Present)
+ MS(Ref_Ptee, RefPtee)
+ MS(Ref_Ptr, RefPtr)
+ MS(Ref_Ptr_Ptee, RefPtrPtee)
// clang-format on
);
+ // Treat always, close, present, self, delete modifiers as map-type-
+ // modifiers.
auto &mods = semantics::OmpGetModifiers(inp.v);
- auto *t1 = semantics::OmpGetUniqueModifier<parser::OmpMapper>(mods);
- auto *t2 = semantics::OmpGetUniqueModifier<parser::OmpIterator>(mods);
- auto *t3 = semantics::OmpGetUniqueModifier<parser::OmpMapType>(mods);
- auto &t4 = std::get<parser::OmpObjectList>(inp.v.t);
- auto mappers = [&]() -> std::optional<List<Mapper>> {
- if (t1)
- return List<Mapper>{Mapper{makeObject(t1->v, semaCtx)}};
- return std::nullopt;
- }();
-
- auto iterator = [&]() -> std::optional<Iterator> {
- if (t2)
- return makeIterator(*t2, semaCtx);
- return std::nullopt;
- }();
+ auto *t1 = semantics::OmpGetUniqueModifier<parser::OmpMapType>(mods);
+ auto &t2 = std::get<parser::OmpObjectList>(inp.v.t);
auto type = [&]() -> std::optional<Map::MapType> {
- if (t3)
- return convert1(t3->v);
- return std::nullopt;
+ std::optional<Map::MapType> type;
+ if (t1) {
+ switch (t1->v) {
+ case parser::OmpMapType::Value::Alloc:
+ case parser::OmpMapType::Value::Delete:
+ case parser::OmpMapType::Value::Release:
+ case parser::OmpMapType::Value::Storage:
+ type = Map::MapType::Storage;
+ break;
+ case parser::OmpMapType::Value::From:
+ type = Map::MapType::From;
+ break;
+ case parser::OmpMapType::Value::To:
+ type = Map::MapType::To;
+ break;
+ case parser::OmpMapType::Value::Tofrom:
+ type = Map::MapType::Tofrom;
+ break;
+ default:
+ break;
+ }
+ }
+ return type;
}();
- Map::MapTypeModifiers typeMods;
+ llvm::DenseSet<Map::MapTypeModifier> modSet;
+ if (t1 && t1->v == parser::OmpMapType::Value::Delete)
+ modSet.insert(Map::MapTypeModifier::Delete);
+
for (auto *typeMod :
semantics::OmpGetRepeatableModifier<parser::OmpMapTypeModifier>(mods)) {
- typeMods.push_back(convert2(typeMod->v));
+ modSet.insert(convert1(typeMod->v));
}
+ if (semantics::OmpGetUniqueModifier<parser::OmpAlwaysModifier>(mods))
+ modSet.insert(Map::MapTypeModifier::Always);
+ if (semantics::OmpGetUniqueModifier<parser::OmpCloseModifier>(mods))
+ modSet.insert(Map::MapTypeModifier::Close);
+ if (semantics::OmpGetUniqueModifier<parser::OmpDeleteModifier>(mods))
+ modSet.insert(Map::MapTypeModifier::Delete);
+ if (semantics::OmpGetUniqueModifier<parser::OmpPresentModifier>(mods))
+ modSet.insert(Map::MapTypeModifier::Present);
+ if (semantics::OmpGetUniqueModifier<parser::OmpSelfModifier>(mods))
+ modSet.insert(Map::MapTypeModifier::Self);
+ if (semantics::OmpGetUniqueModifier<parser::OmpxHoldModifier>(mods))
+ modSet.insert(Map::MapTypeModifier::OmpxHold);
+
std::optional<Map::MapTypeModifiers> maybeTypeMods{};
- if (!typeMods.empty())
- maybeTypeMods = std::move(typeMods);
+ if (!modSet.empty())
+ maybeTypeMods = Map::MapTypeModifiers(modSet.begin(), modSet.end());
+
+ auto refMod = [&]() -> std::optional<Map::RefModifier> {
+ if (auto *t = semantics::OmpGetUniqueModifier<parser::OmpRefModifier>(mods))
+ return convert2(t->v);
+ return std::nullopt;
+ }();
+
+ auto mappers = [&]() -> std::optional<List<Mapper>> {
+ if (auto *t = semantics::OmpGetUniqueModifier<parser::OmpMapper>(mods))
+ return List<Mapper>{Mapper{makeObject(t->v, semaCtx)}};
+ return std::nullopt;
+ }();
+
+ auto iterator = [&]() -> std::optional<Iterator> {
+ if (auto *t = semantics::OmpGetUniqueModifier<parser::OmpIterator>(mods))
+ return makeIterator(*t, semaCtx);
+ return std::nullopt;
+ }();
return Map{{/*MapType=*/std::move(type),
/*MapTypeModifiers=*/std::move(maybeTypeMods),
- /*Mapper=*/std::move(mappers), /*Iterator=*/std::move(iterator),
- /*LocatorList=*/makeObjects(t4, semaCtx)}};
+ /*RefModifier=*/std::move(refMod), /*Mapper=*/std::move(mappers),
+ /*Iterator=*/std::move(iterator),
+ /*LocatorList=*/makeObjects(t2, semaCtx)}};
}
Match make(const parser::OmpClause::Match &inp,
diff --git a/flang/lib/Semantics/canonicalize-omp.cpp b/flang/lib/Semantics/canonicalize-omp.cpp
index 46aaab19ded0a..77e2fd6ca5097 100644
--- a/flang/lib/Semantics/canonicalize-omp.cpp
+++ b/flang/lib/Semantics/canonicalize-omp.cpp
@@ -402,6 +402,11 @@ class CanonicalizationOfOmp {
// if the specified OpenMP version is less than 6.0, rewrite the affected
// modifiers back into the pre-6.0 forms.
void CanonicalizeMapModifiers(parser::OmpMapClause &map) {
+ unsigned version{context_.langOptions().OpenMPVersion};
+ if (version >= 60) {
+ return;
+ }
+
// Omp{Always, Close, Present, xHold}Modifier -> OmpMapTypeModifier
// OmpDeleteModifier -> OmpMapType
using Modifier = parser::OmpMapClause::Modifier;
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 2425265e196c6..94dee3d7afe21 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -37,6 +37,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Frontend/OpenMP/OMP.h"
@@ -3399,23 +3400,22 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Detach &x) {
}
}
-void OmpStructureChecker::CheckAllowedMapTypes(
- const parser::OmpMapType::Value &type,
- const std::list<parser::OmpMapType::Value> &allowedMapTypeList) {
- if (!llvm::is_contained(allowedMapTypeList, type)) {
- std::string commaSeparatedMapTypes;
- llvm::interleave(
- allowedMapTypeList.begin(), allowedMapTypeList.end(),
- [&](const parser::OmpMapType::Value &mapType) {
- commaSeparatedMapTypes.append(parser::ToUpperCaseLetters(
- parser::OmpMapType::EnumToString(mapType)));
- },
- [&] { commaSeparatedMapTypes.append(", "); });
- context_.Say(GetContext().clauseSource,
- "Only the %s map types are permitted "
- "for MAP clauses on the %s directive"_err_en_US,
- commaSeparatedMapTypes, ContextDirectiveAsFortran());
+void OmpStructureChecker::CheckAllowedMapTypes(parser::OmpMapType::Value type,
+ llvm::ArrayRef<parser::OmpMapType::Value> allowed) {
+ if (llvm::is_contained(allowed, type)) {
+ return;
}
+
+ llvm::SmallVector<std::string> names;
+ llvm::transform(
+ allowed, std::back_inserter(names), [](parser::OmpMapType::Value val) {
+ return parser::ToUpperCaseLetters(
+ parser::OmpMapType::EnumToString(val));
+ });
+ llvm::sort(names);
+ context_.Say(GetContext().clauseSource,
+ "Only the %s map types are permitted for MAP clauses on the %s directive"_err_en_US,
+ llvm::join(names, ", "), ContextDirectiveAsFortran());
}
void OmpStructureChecker::Enter(const parser::OmpClause::Map &x) {
@@ -3436,27 +3436,62 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Map &x) {
CheckIteratorModifier(*iter);
}
if (auto *type{OmpGetUniqueModifier<parser::OmpMapType>(modifiers)}) {
+ using Directive = llvm::omp::Directive;
using Value = parser::OmpMapType::Value;
- switch (GetContext().directive) {
- case llvm::omp::Directive::OMPD_target:
- case llvm::omp::Directive::OMPD_target_teams:
- case llvm::omp::Directive::OMPD_target_teams_distribute:
- case llvm::omp::Directive::OMPD_target_teams_distribute_simd:
- case llvm::omp::Directive::OMPD_target_teams_distribute_parallel_do:
- case llvm::omp::Directive::OMPD_target_teams_distribute_parallel_do_simd:
- case llvm::omp::Directive::OMPD_target_data:
- CheckAllowedMapTypes(
- type->v, {Value::To, Value::From, Value::Tofrom, Value::Alloc});
- break;
- case llvm::omp::Directive::OMPD_target_enter_data:
- CheckAllowedMapTypes(type->v, {Value::To, Value::Alloc});
- break;
- case llvm::omp::Directive::OMPD_target_exit_data:
- CheckAllowedMapTypes(
- type->v, {Value::From, Value::Release, Value::Delete});
- break;
- default:
- break;
+
+ static auto isValidForVersion{
+ [](parser::OmpMapType::Value t, unsigned version) {
+ switch (t) {
+ case parser::OmpMapType::Value::Alloc:
+ case parser::OmpMapType::Value::Delete:
+ case parser::OmpMapType::Value::Release:
+ return version < 60;
+ case parser::OmpMapType::Value::Storage:
+ return version >= 60;
+ default:
+ return true;
+ }
+ }};
+
+ llvm::SmallVector<parser::OmpMapType::Value> mapEnteringTypes{[&]() {
+ llvm::SmallVector<parser::OmpMapType::Value> result;
+ for (size_t i{0}; i != parser::OmpMapType::Value_enumSize; ++i) {
+ auto t{static_cast<parser::OmpMapType::Value>(i)};
+ if (isValidForVersion(t, version) && IsMapEnteringType(t)) {
+ result.push_back(t);
+ }
+ }
+ return result;
+ }()};
+ llvm::SmallVector<parser::OmpMapType::Value> mapExitingTypes{[&]() {
+ llvm::SmallVector<parser::OmpMapType::Value> result;
+ for (size_t i{0}; i != parser::OmpMapType::Value_enumSize; ++i) {
+ auto t{static_cast<parser::OmpMapType::Value>(i)};
+ if (isValidForVersion(t, version) && IsMapExitingType(t)) {
+ result.push_back(t);
+ }
+ }
+ return result;
+ }()};
+
+ llvm::omp::Directive dir{GetContext().directive};
+ llvm::ArrayRef<llvm::omp::Directive> leafs{
+ llvm::omp::getLeafConstructsOrSelf(dir)};
+
+ if (llvm::is_contained(leafs, Directive::OMPD_target) ||
+ llvm::is_contained(leafs, Directive::OMPD_target_data)) {
+ if (version >= 60) {
+ // Map types listed in the decay table. [6.0:276]
+ CheckAllowedMapTypes(
+ type->v, {Value::Storage, Value::From, Value::To, Value::Tofrom});
+ } else {
+ CheckAllowedMapTypes(
+ type->v, {Value::Alloc, Value::From, Value::To, Value::Tofrom});
+ }
+ } else if (llvm::is_contained(leafs, Directive::OMPD_target_enter_data)) {
+ CheckAllowedMapTypes(type->v, mapEnteringTypes);
+ } else if (llvm::is_contained(leafs, Directive::OMPD_target_exit_data)) {
+ CheckAllowedMapTypes(type->v, mapExitingTypes);
}
}
diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index 6a877a5d0a7c0..f4a291dc255c8 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -179,8 +179,8 @@ class OmpStructureChecker
void HasInvalidDistributeNesting(const parser::OpenMPLoopConstruct &x);
void HasInvalidLoopBinding(const parser::OpenMPLoopConstruct &x);
// specific clause related
- void CheckAllowedMapTypes(const parser::OmpMapType::Value &,
- const std::list<parser::OmpMapType::Value> &);
+ void CheckAllowedMapTypes(
+ parser::OmpMapType::Value, llvm::ArrayRef<parser::OmpMapType::Value>);
const std::list<parser::OmpTraitProperty> &GetTraitPropertyList(
const parser::OmpTraitSelector &);
diff --git a/flang/lib/Semantics/openmp-utils.cpp b/flang/lib/Semantics/openmp-utils.cpp
index f43d2cc75620e..da14507aa9fe6 100644
--- a/flang/lib/Semantics/openmp-utils.cpp
+++ b/flang/lib/Semantics/openmp-utils.cpp
@@ -143,6 +143,31 @@ bool IsVarOrFunctionRef(const MaybeExpr &expr) {
}
}
+bool IsMapEnteringType(parser::OmpMapType::Value type) {
+ switch (type) {
+ case parser::OmpMapType::Value::Alloc:
+ case parser::OmpMapType::Value::Storage:
+ case parser::OmpMapType::Value::To:
+ case parser::OmpMapType::Value::Tofrom:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool IsMapExitingType(parser::OmpMapType::Value type) {
+ switch (type) {
+ case parser::OmpMapType::Value::Delete:
+ case parser::OmpMapType::Value::From:
+ case parser::OmpMapType::Value::Release:
+ case parser::OmpMapType::Value::Storage:
+ case parser::OmpMapType::Value::Tofrom:
+ return true;
+ default:
+ return false;
+ }
+}
+
std::optional<SomeExpr> GetEvaluateExpr(const parser::Expr &parserExpr) {
const parser::TypedExpr &typedExpr{parserExpr.typedExpr};
// ForwardOwningPointer typedExpr
diff --git a/flang/lib/Semantics/openmp-utils.h b/flang/lib/Semantics/openmp-utils.h
index a96c008fb26e7..001fbeb45ceec 100644
--- a/flang/lib/Semantics/openmp-utils.h
+++ b/flang/lib/Semantics/openmp-utils.h
@@ -59,6 +59,9 @@ bool IsExtendedListItem(const Symbol &sym);
bool IsVariableListItem(const Symbol &sym);
bool IsVarOrFunctionRef(const MaybeExpr &expr);
+bool IsMapEnteringType(parser::OmpMapType::Value type);
+bool IsMapExitingType(parser::OmpMapType::Value type);
+
std::optional<SomeExpr> GetEvaluateExpr(const parser::Expr &parserExpr);
std::optional<evaluate::DynamicType> GetDynamicType(
const parser::Expr &parserExpr);
diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index 0b860314b4a1f..cbd14bc259d38 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -712,7 +712,15 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
void Post(const parser::EorLabel &eorLabel) { CheckSourceLabel(eorLabel.v); }
void Post(const parser::OmpMapClause &x) {
- Symbol::Flag ompFlag = Symbol::Flag::OmpMapToFrom;
+ unsigned version{context_.langOptions().OpenMPVersion};
+ llvm::omp::Directive id{GetContext().directive};
+ std::optional<Symbol::Flag> ompFlag;
+ // Expand "storage" into either "alloc" or "release", depending on the
+ // type of the construct.
+ Symbol::Flag ompFlagForStorage = llvm::omp::isMapEnteringConstruct(id)
+ ? Symbol::Flag::OmpMapAlloc
+ : Symbol::Flag::OmpMapRelease;
+
auto &mods{OmpGetModifiers(x)};
if (auto *mapType{OmpGetUniqueModifier<parser::OmpMapType>(mods)}) {
switch (mapType->v) {
@@ -734,10 +742,29 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
case parser::OmpMapType::Value::Delete:
ompFlag = Symbol::Flag::OmpMapDelete;
break;
- default:
+ case parser::OmpMapType::Value::Storage:
+ ompFlag = ompFlagForStorage;
break;
}
}
+ if (!ompFlag) {
+ if (version >= 60) {
+ // [6.0:275:12-15]
+ // When a map-type is not specified for a clause on which it may be
+ // specified, the map-type defaults to storage if the delete-modifier
+ // is present on the clause or if the list item for which the map-type
+ // is not specified is an assumed-size array.
+ if (OmpGetUniqueModifier<parser::OmpDeleteModifier>(mods)) {
+ ompFlag = ompFlagForStorage;
+ }
+ // Otherwise, if delete-modifier is absent, leave ompFlag unset.
+ } else {
+ // [5.2:151:10]
+ // If a map-type is not specified, the map-type defaults to tofrom.
+ ompFlag = Symbol::Flag::OmpMapToFrom;
+ }
+ }
+
const auto &ompObjList{std::get<parser::OmpObjectList>(x.t)};
for (const auto &ompObj : ompObjList.v) {
common::visit(
@@ -746,15 +773,14 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
if (const auto *name{
semantics::getDesignatorNameIfDataRef(designator)}) {
if (name->symbol) {
- name->symbol->set(ompFlag);
- AddToContextObjectWithDSA(*name->symbol, ompFlag);
- }
- if (name->symbol &&
- semantics::IsAssumedSizeArray(*name->symbol)) {
- context_.Say(designator.source,
- "Assumed-size whole arrays may not appear on the %s "
- "clause"_err_en_US,
- "MAP");
+ name->symbol->set(ompFlag.value_or(ompFlagForStorage));
+ AddToContextObjectWithDSA(*name->symbol, *ompFlag);
+ if (semantics::IsAssumedSizeArray(*name->symbol)) {
+ context_.Say(designator.source,
+ "Assumed-size whole arrays may not appear on the %s "
+ "clause"_err_en_US,
+ "MAP");
+ }
}
}
},
@@ -762,7 +788,7 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
},
ompObj.u);
- ResolveOmpObject(ompObj, ompFlag);
+ ResolveOmpObject(ompObj, ompFlag.value_or(ompFlagForStorage));
}
}
diff --git a/flang/test/Semantics/OpenMP/combined-constructs.f90 b/flang/test/Semantics/OpenMP/combined-constructs.f90
index 4f2a4a4f501b9..2298d33ef33eb 100644
--- a/flang/test/Semantics/OpenMP/combined-constructs.f90
+++ b/flang/test/Semantics/OpenMP/combined-constructs.f90
@@ -207,7 +207,7 @@ program main
enddo
!$omp end target teams
- !ERROR: Only the TO, FROM, TOFROM, ALLOC map types are permitted for MAP clauses on the TARGET TEAMS directive
+ !ERROR: Only the ALLOC, FROM, TO, TOFROM map types are permitted for MAP clauses on the TARGET TEAMS directive
!$omp target teams map(delete:a)
do i = 1, N
a(i) = 3.14
@@ -307,7 +307,7 @@ program main
enddo
!$omp end target teams distribute
- !ERROR: Only the TO, FROM, TOFROM, ALLOC map types are permitted for MAP clauses on the TARGET TEAMS DISTRIBUTE directive
+ !ERROR: Only the ALLOC, FROM, TO, TOFROM map types are permitted for MAP clauses on the TARGET TEAMS DISTRIBUTE directive
!$omp target teams distribute map(delete:a)
do i = 1, N
a(i) = 3.14
@@ -400,7 +400,7 @@ program main
enddo
!$omp end target teams distribute parallel do
- !ERROR: Only the TO, FROM, TOFROM, ALLOC map types are permitted for MAP clauses on the TARGET TEAMS DISTRIBUTE PARALLEL DO directive
+ !ERROR: Only the ALLOC, FROM, TO, TOFROM map types are permitted for MAP clauses on the TARGET TEAMS DISTRIBUTE PARALLEL DO directive
!$omp target teams distribute parallel do map(delete:a)
do i = 1, N
a(i) = 3.14
@@ -500,7 +500,7 @@ program main
enddo
!$omp end target teams distribute parallel do simd
- !ERROR: Only the TO, FROM, TOFROM, ALLOC map types are permitted for MAP clauses on the TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD directive
+ !ERROR: Only the ALLOC, FROM, TO, TOFROM map types are permitted for MAP clauses on the TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD directive
!$omp target teams distribute parallel do simd map(delete:a)
do i = 1, N
a(i) = 3.14
diff --git a/flang/test/Semantics/OpenMP/device-constructs.f90 b/flang/test/Semantics/OpenMP/device-constructs.f90
index 6f545b9021966..431e0f88e3237 100644
--- a/flang/test/Semantics/OpenMP/device-constructs.f90
+++ b/flang/test/Semantics/OpenMP/device-constructs.f90
@@ -123,7 +123,7 @@ program main
enddo
!$omp end target
- !ERROR: Only the TO, FROM, TOFROM, ALLOC map types are permitted for MAP clauses on the TARGET directive
+ !ERROR: Only the ALLOC, FROM, TO, TOFROM map types are permitted for MAP clauses on the TARGET directive
!$omp target map(delete:a)
do i = 1, N
a = 3.14
@@ -160,7 +160,7 @@ program main
!ERROR: At most one IF clause can appear on the TARGET ENTER DATA directive
!$omp target enter data map(to:a) if(.true.) if(.false.)
- !ERROR: Only the TO, ALLOC map types are permitted for MAP clauses on the TARGET ENTER DATA directive
+ !ERROR: Only the ALLOC, TO, TOFROM map types are permitted for MAP clauses on the TARGET ENTER DATA directive
!$omp target enter data map(from:a)
!$omp target exit data map(delete:a)
@@ -168,7 +168,7 @@ program main
!ERROR: At most one DEVICE clause can appear on the TARGET EXIT DATA directive
!$omp target exit data map(from:a) device(0) device(1)
- !ERROR: Only the FROM, RELEASE, DELETE map types are permitted for MAP clauses on the TARGET EXIT DATA directive
+ !ERROR: Only the DELETE, FROM, RELEASE, TOFROM map types are permitted for MAP clauses on the TARGET EXIT DATA directive
!$omp target exit data map(to:a)
!$omp target update if(.true.) device(1) to(a) from(b) depend(inout:c) nowait
diff --git a/llvm/include/llvm/Frontend/OpenMP/ClauseT.h b/llvm/include/llvm/Frontend/OpenMP/ClauseT.h
index de888ff86fe91..7919f7a8b0c34 100644
--- a/llvm/include/llvm/Frontend/OpenMP/ClauseT.h
+++ b/llvm/include/llvm/Frontend/OpenMP/ClauseT.h
@@ -779,16 +779,17 @@ struct LinkT {
template <typename T, typename I, typename E> //
struct MapT {
using LocatorList = ObjectListT<I, E>;
- ENUM(MapType, To, From, Tofrom, Alloc, Release, Delete);
- ENUM(MapTypeModifier, Always, Close, Present, OmpxHold);
+ ENUM(MapType, To, From, Tofrom, Storage);
+ ENUM(MapTypeModifier, Always, Close, Delete, Present, Self, OmpxHold);
+ ENUM(RefModifier, RefPtee, RefPtr, RefPtrPtee);
// See note at the definition of the MapperT type.
using Mappers = ListT<type::MapperT<I, E>>; // Not a spec name
using Iterator = type::IteratorT<T, I, E>;
using MapTypeModifiers = ListT<MapTypeModifier>; // Not a spec name
using TupleTrait = std::true_type;
- std::tuple<OPT(MapType), OPT(MapTypeModifiers), OPT(Mappers), OPT(Iterator),
- LocatorList>
+ std::tuple<OPT(MapType), OPT(MapTypeModifiers), OPT(RefModifier),
+ OPT(Mappers), OPT(Iterator), LocatorList>
t;
};
diff --git a/llvm/include/llvm/Frontend/OpenMP/ConstructDecompositionT.h b/llvm/include/llvm/Frontend/OpenMP/ConstructDecompositionT.h
index 611bfe3f8aced..047baa3a79f5d 100644
--- a/llvm/include/llvm/Frontend/OpenMP/ConstructDecompositionT.h
+++ b/llvm/include/llvm/Frontend/OpenMP/ConstructDecompositionT.h
@@ -708,6 +708,7 @@ bool ConstructDecompositionT<C, H>::applyClause(
tomp::clause::MapT<TypeTy, IdTy, ExprTy>{
{/*MapType=*/MapType::Tofrom,
/*MapTypeModifier=*/std::nullopt,
+ /*RefModifier=*/std::nullopt,
/*Mapper=*/std::nullopt, /*Iterator=*/std::nullopt,
/*LocatorList=*/std::move(tofrom)}});
dirTarget->clauses.push_back(map);
@@ -969,8 +970,8 @@ bool ConstructDecompositionT<C, H>::applyClause(
llvm::omp::Clause::OMPC_map,
tomp::clause::MapT<TypeTy, IdTy, ExprTy>{
{/*MapType=*/MapType::Tofrom, /*MapTypeModifier=*/std::nullopt,
- /*Mapper=*/std::nullopt, /*Iterator=*/std::nullopt,
- /*LocatorList=*/std::move(tofrom)}});
+ /*RefModifier=*/std::nullopt, /*Mapper=*/std::nullopt,
+ /*Iterator=*/std::nullopt, /*LocatorList=*/std::move(tofrom)}});
dirTarget->clauses.push_back(map);
applied = true;
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.h b/llvm/include/llvm/Frontend/OpenMP/OMP.h
index d44c33301bde7..a8b4503147034 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMP.h
+++ b/llvm/include/llvm/Frontend/OpenMP/OMP.h
@@ -64,6 +64,8 @@ static constexpr inline bool isPrivatizingClause(Clause C) {
}
}
+LLVM_ABI bool isMapEnteringConstruct(Directive D);
+
static constexpr unsigned FallbackVersion = 52;
LLVM_ABI ArrayRef<unsigned> getOpenMPVersions();
diff --git a/llvm/lib/Frontend/OpenMP/OMP.cpp b/llvm/lib/Frontend/OpenMP/OMP.cpp
index 555e2a61e411e..c23fb400666d6 100644
--- a/llvm/lib/Frontend/OpenMP/OMP.cpp
+++ b/llvm/lib/Frontend/OpenMP/OMP.cpp
@@ -189,6 +189,20 @@ bool isCombinedConstruct(Directive D) {
return !getLeafConstructs(D).empty() && !isCompositeConstruct(D);
}
+bool isMapEnteringConstruct(Directive D) {
+ for (Directive L : getLeafConstructsOrSelf(D)) {
+ switch (L) {
+ case OMPD_target:
+ case OMPD_target_data:
+ case OMPD_target_enter_data:
+ return true;
+ default:
+ break;
+ }
+ }
+ return false;
+}
+
ArrayRef<unsigned> getOpenMPVersions() {
static unsigned Versions[]{31, 40, 45, 50, 51, 52, 60};
return Versions;
>From 0733ec13ae69e2ec3d462987c279ef083890e95c Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Wed, 16 Jul 2025 11:41:55 -0500
Subject: [PATCH 03/10] Simplify converting MapType, NFC
---
flang/lib/Lower/OpenMP/Clauses.cpp | 47 +++++++++++++-----------------
1 file changed, 20 insertions(+), 27 deletions(-)
diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp
index 18e49719b6013..ece4a8eaac8cd 100644
--- a/flang/lib/Lower/OpenMP/Clauses.cpp
+++ b/flang/lib/Lower/OpenMP/Clauses.cpp
@@ -1001,7 +1001,20 @@ Map make(const parser::OmpClause::Map &inp,
semantics::SemanticsContext &semaCtx) {
// inp.v -> parser::OmpMapClause
CLAUSET_ENUM_CONVERT( //
- convert1, parser::OmpMapTypeModifier::Value, Map::MapTypeModifier,
+ convert1, parser::OmpMapType::Value, Map::MapType,
+ // clang-format off
+ MS(Alloc, Storage)
+ MS(Delete, Storage)
+ MS(Release, Storage)
+ MS(Storage, Storage)
+ MS(From, From)
+ MS(To, To)
+ MS(Tofrom, Tofrom)
+ // clang-format on
+ );
+
+ CLAUSET_ENUM_CONVERT( //
+ convert2, parser::OmpMapTypeModifier::Value, Map::MapTypeModifier,
// clang-format off
MS(Always, Always)
MS(Close, Close)
@@ -1011,7 +1024,7 @@ Map make(const parser::OmpClause::Map &inp,
);
CLAUSET_ENUM_CONVERT( //
- convert2, parser::OmpRefModifier::Value, Map::RefModifier,
+ convert3, parser::OmpRefModifier::Value, Map::RefModifier,
// clang-format off
MS(Ref_Ptee, RefPtee)
MS(Ref_Ptr, RefPtr)
@@ -1027,29 +1040,9 @@ Map make(const parser::OmpClause::Map &inp,
auto &t2 = std::get<parser::OmpObjectList>(inp.v.t);
auto type = [&]() -> std::optional<Map::MapType> {
- std::optional<Map::MapType> type;
- if (t1) {
- switch (t1->v) {
- case parser::OmpMapType::Value::Alloc:
- case parser::OmpMapType::Value::Delete:
- case parser::OmpMapType::Value::Release:
- case parser::OmpMapType::Value::Storage:
- type = Map::MapType::Storage;
- break;
- case parser::OmpMapType::Value::From:
- type = Map::MapType::From;
- break;
- case parser::OmpMapType::Value::To:
- type = Map::MapType::To;
- break;
- case parser::OmpMapType::Value::Tofrom:
- type = Map::MapType::Tofrom;
- break;
- default:
- break;
- }
- }
- return type;
+ if (t1)
+ return convert1(t1->v);
+ return std::nullopt;
}();
llvm::DenseSet<Map::MapTypeModifier> modSet;
@@ -1058,7 +1051,7 @@ Map make(const parser::OmpClause::Map &inp,
for (auto *typeMod :
semantics::OmpGetRepeatableModifier<parser::OmpMapTypeModifier>(mods)) {
- modSet.insert(convert1(typeMod->v));
+ modSet.insert(convert2(typeMod->v));
}
if (semantics::OmpGetUniqueModifier<parser::OmpAlwaysModifier>(mods))
modSet.insert(Map::MapTypeModifier::Always);
@@ -1079,7 +1072,7 @@ Map make(const parser::OmpClause::Map &inp,
auto refMod = [&]() -> std::optional<Map::RefModifier> {
if (auto *t = semantics::OmpGetUniqueModifier<parser::OmpRefModifier>(mods))
- return convert2(t->v);
+ return convert3(t->v);
return std::nullopt;
}();
>From a7476b1ca983ecf0244b71ab873d3775343e5c46 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Wed, 16 Jul 2025 12:43:14 -0500
Subject: [PATCH 04/10] Fix unit test
---
.../Frontend/OpenMPDecompositionTest.cpp | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/llvm/unittests/Frontend/OpenMPDecompositionTest.cpp b/llvm/unittests/Frontend/OpenMPDecompositionTest.cpp
index 6189d0954891b..95c26b10c9a0c 100644
--- a/llvm/unittests/Frontend/OpenMPDecompositionTest.cpp
+++ b/llvm/unittests/Frontend/OpenMPDecompositionTest.cpp
@@ -431,8 +431,8 @@ TEST_F(OpenMPDecompositionTest, Firstprivate3) {
std::string Dir0 = stringify(Dec.output[0]);
std::string Dir1 = stringify(Dec.output[1]);
std::string Dir2 = stringify(Dec.output[2]);
- ASSERT_EQ(Dir0, "target map(2, , , , (x))"); // (12), (27)
- ASSERT_EQ(Dir1, "teams shared(x)"); // (6), (17)
+ ASSERT_EQ(Dir0, "target map(2, , , , , (x))"); // (12), (27)
+ ASSERT_EQ(Dir1, "teams shared(x)"); // (6), (17)
ASSERT_EQ(Dir2, "distribute firstprivate(x) lastprivate(, (x))"); // (5), (21)
}
@@ -574,9 +574,9 @@ TEST_F(OpenMPDecompositionTest, Lastprivate3) {
std::string Dir0 = stringify(Dec.output[0]);
std::string Dir1 = stringify(Dec.output[1]);
std::string Dir2 = stringify(Dec.output[2]);
- ASSERT_EQ(Dir0, "target map(2, , , , (x))"); // (21), (27)
- ASSERT_EQ(Dir1, "parallel shared(x)"); // (22)
- ASSERT_EQ(Dir2, "do lastprivate(, (x))"); // (21)
+ ASSERT_EQ(Dir0, "target map(2, , , , , (x))"); // (21), (27)
+ ASSERT_EQ(Dir1, "parallel shared(x)"); // (22)
+ ASSERT_EQ(Dir2, "do lastprivate(, (x))"); // (21)
}
// SHARED
@@ -984,9 +984,9 @@ TEST_F(OpenMPDecompositionTest, Reduction7) {
std::string Dir0 = stringify(Dec.output[0]);
std::string Dir1 = stringify(Dec.output[1]);
std::string Dir2 = stringify(Dec.output[2]);
- ASSERT_EQ(Dir0, "target map(2, , , , (x))"); // (36), (10)
- ASSERT_EQ(Dir1, "parallel shared(x)"); // (36), (1), (4)
- ASSERT_EQ(Dir2, "do reduction(, (3), (x))"); // (36)
+ ASSERT_EQ(Dir0, "target map(2, , , , , (x))"); // (36), (10)
+ ASSERT_EQ(Dir1, "parallel shared(x)"); // (36), (1), (4)
+ ASSERT_EQ(Dir2, "do reduction(, (3), (x))"); // (36)
}
// IF
>From faff0d32746640c34988a65552e277198748fcf2 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Mon, 21 Jul 2025 08:49:18 -0500
Subject: [PATCH 05/10] Don't pass SemanticsContext to CanonicalizeOmp yet
---
flang/lib/Semantics/canonicalize-omp.cpp | 10 ++++------
flang/lib/Semantics/canonicalize-omp.h | 5 +++--
flang/lib/Semantics/semantics.cpp | 3 ++-
3 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/flang/lib/Semantics/canonicalize-omp.cpp b/flang/lib/Semantics/canonicalize-omp.cpp
index 46aaab19ded0a..bba4d72a702e9 100644
--- a/flang/lib/Semantics/canonicalize-omp.cpp
+++ b/flang/lib/Semantics/canonicalize-omp.cpp
@@ -27,8 +27,7 @@ class CanonicalizationOfOmp {
public:
template <typename T> bool Pre(T &) { return true; }
template <typename T> void Post(T &) {}
- CanonicalizationOfOmp(SemanticsContext &context)
- : context_{context}, messages_{context.messages()} {}
+ CanonicalizationOfOmp(parser::Messages &messages) : messages_{messages} {}
void Post(parser::Block &block) {
for (auto it{block.begin()}; it != block.end(); ++it) {
@@ -433,13 +432,12 @@ class CanonicalizationOfOmp {
// same construct. This is for converting utility constructs to executable
// constructs.
std::map<parser::SpecificationPart *, parser::Block *> blockForSpec_;
- SemanticsContext &context_;
parser::Messages &messages_;
};
-bool CanonicalizeOmp(SemanticsContext &context, parser::Program &program) {
- CanonicalizationOfOmp omp{context};
+bool CanonicalizeOmp(parser::Messages &messages, parser::Program &program) {
+ CanonicalizationOfOmp omp{messages};
Walk(program, omp);
- return !context.messages().AnyFatalError();
+ return !messages.AnyFatalError();
}
} // namespace Fortran::semantics
diff --git a/flang/lib/Semantics/canonicalize-omp.h b/flang/lib/Semantics/canonicalize-omp.h
index 3251218da35ed..23350c522a775 100644
--- a/flang/lib/Semantics/canonicalize-omp.h
+++ b/flang/lib/Semantics/canonicalize-omp.h
@@ -11,12 +11,13 @@
namespace Fortran::parser {
struct Program;
-}
+class Messages;
+} // namespace Fortran::parser
namespace Fortran::semantics {
class SemanticsContext;
-bool CanonicalizeOmp(SemanticsContext &context, parser::Program &program);
+bool CanonicalizeOmp(parser::Messages &messages, parser::Program &program);
} // namespace Fortran::semantics
#endif // FORTRAN_SEMANTICS_CANONICALIZE_OMP_H_
diff --git a/flang/lib/Semantics/semantics.cpp b/flang/lib/Semantics/semantics.cpp
index 6db11aaf56c2a..b15ed057b52f2 100644
--- a/flang/lib/Semantics/semantics.cpp
+++ b/flang/lib/Semantics/semantics.cpp
@@ -642,7 +642,8 @@ bool Semantics::Perform() {
return ValidateLabels(context_, program_) &&
parser::CanonicalizeDo(program_) && // force line break
CanonicalizeAcc(context_.messages(), program_) &&
- CanonicalizeOmp(context_, program_) && CanonicalizeCUDA(program_) &&
+ CanonicalizeOmp(context_.messages(), program_) &&
+ CanonicalizeCUDA(program_) &&
PerformStatementSemantics(context_, program_) &&
CanonicalizeDirectives(context_.messages(), program_) &&
ModFileWriter{context_}
>From 724cc8306faae084c4a6ff8295073bd65bc0f609 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Mon, 21 Jul 2025 08:54:34 -0500
Subject: [PATCH 06/10] Pass SemanticsContext to CanonicalizeOmp
---
flang/lib/Semantics/canonicalize-omp.cpp | 10 ++++++----
flang/lib/Semantics/canonicalize-omp.h | 5 ++---
flang/lib/Semantics/semantics.cpp | 3 +--
3 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/flang/lib/Semantics/canonicalize-omp.cpp b/flang/lib/Semantics/canonicalize-omp.cpp
index 9b74a153b233e..77e2fd6ca5097 100644
--- a/flang/lib/Semantics/canonicalize-omp.cpp
+++ b/flang/lib/Semantics/canonicalize-omp.cpp
@@ -27,7 +27,8 @@ class CanonicalizationOfOmp {
public:
template <typename T> bool Pre(T &) { return true; }
template <typename T> void Post(T &) {}
- CanonicalizationOfOmp(parser::Messages &messages) : messages_{messages} {}
+ CanonicalizationOfOmp(SemanticsContext &context)
+ : context_{context}, messages_{context.messages()} {}
void Post(parser::Block &block) {
for (auto it{block.begin()}; it != block.end(); ++it) {
@@ -437,12 +438,13 @@ class CanonicalizationOfOmp {
// same construct. This is for converting utility constructs to executable
// constructs.
std::map<parser::SpecificationPart *, parser::Block *> blockForSpec_;
+ SemanticsContext &context_;
parser::Messages &messages_;
};
-bool CanonicalizeOmp(parser::Messages &messages, parser::Program &program) {
- CanonicalizationOfOmp omp{messages};
+bool CanonicalizeOmp(SemanticsContext &context, parser::Program &program) {
+ CanonicalizationOfOmp omp{context};
Walk(program, omp);
- return !messages.AnyFatalError();
+ return !context.messages().AnyFatalError();
}
} // namespace Fortran::semantics
diff --git a/flang/lib/Semantics/canonicalize-omp.h b/flang/lib/Semantics/canonicalize-omp.h
index 23350c522a775..3251218da35ed 100644
--- a/flang/lib/Semantics/canonicalize-omp.h
+++ b/flang/lib/Semantics/canonicalize-omp.h
@@ -11,13 +11,12 @@
namespace Fortran::parser {
struct Program;
-class Messages;
-} // namespace Fortran::parser
+}
namespace Fortran::semantics {
class SemanticsContext;
-bool CanonicalizeOmp(parser::Messages &messages, parser::Program &program);
+bool CanonicalizeOmp(SemanticsContext &context, parser::Program &program);
} // namespace Fortran::semantics
#endif // FORTRAN_SEMANTICS_CANONICALIZE_OMP_H_
diff --git a/flang/lib/Semantics/semantics.cpp b/flang/lib/Semantics/semantics.cpp
index b15ed057b52f2..6db11aaf56c2a 100644
--- a/flang/lib/Semantics/semantics.cpp
+++ b/flang/lib/Semantics/semantics.cpp
@@ -642,8 +642,7 @@ bool Semantics::Perform() {
return ValidateLabels(context_, program_) &&
parser::CanonicalizeDo(program_) && // force line break
CanonicalizeAcc(context_.messages(), program_) &&
- CanonicalizeOmp(context_.messages(), program_) &&
- CanonicalizeCUDA(program_) &&
+ CanonicalizeOmp(context_, program_) && CanonicalizeCUDA(program_) &&
PerformStatementSemantics(context_, program_) &&
CanonicalizeDirectives(context_.messages(), program_) &&
ModFileWriter{context_}
>From 3886bbcd0477b5932b1c9dc1303bbe3a940bd179 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Mon, 21 Jul 2025 09:20:25 -0500
Subject: [PATCH 07/10] Invent OmpMapStorage for map flags
We're using "storage" instead of "alloc"/"release" in lowering, this will
make things more consistent.
---
flang/include/flang/Semantics/symbol.h | 5 ++---
flang/lib/Semantics/resolve-directives.cpp | 26 +++++++---------------
flang/lib/Semantics/symbol.cpp | 3 +--
3 files changed, 11 insertions(+), 23 deletions(-)
diff --git a/flang/include/flang/Semantics/symbol.h b/flang/include/flang/Semantics/symbol.h
index b319e2c7e5e74..5bde9f39ca0b0 100644
--- a/flang/include/flang/Semantics/symbol.h
+++ b/flang/include/flang/Semantics/symbol.h
@@ -812,9 +812,8 @@ class Symbol {
// OpenMP data-sharing attribute
OmpShared, OmpPrivate, OmpLinear, OmpFirstPrivate, OmpLastPrivate,
// OpenMP data-mapping attribute
- OmpMapTo, OmpMapFrom, OmpMapToFrom, OmpMapAlloc, OmpMapRelease,
- OmpMapDelete, OmpUseDevicePtr, OmpUseDeviceAddr, OmpIsDevicePtr,
- OmpHasDeviceAddr,
+ OmpMapTo, OmpMapFrom, OmpMapToFrom, OmpMapStorage, OmpMapDelete,
+ OmpUseDevicePtr, OmpUseDeviceAddr, OmpIsDevicePtr, OmpHasDeviceAddr,
// OpenMP data-copying attribute
OmpCopyIn, OmpCopyPrivate,
// OpenMP miscellaneous flags
diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index e02ff97dc6917..4c3e509b5a36d 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -728,13 +728,7 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
void Post(const parser::OmpMapClause &x) {
unsigned version{context_.langOptions().OpenMPVersion};
- llvm::omp::Directive id{GetContext().directive};
std::optional<Symbol::Flag> ompFlag;
- // Expand "storage" into either "alloc" or "release", depending on the
- // type of the construct.
- Symbol::Flag ompFlagForStorage = llvm::omp::isMapEnteringConstruct(id)
- ? Symbol::Flag::OmpMapAlloc
- : Symbol::Flag::OmpMapRelease;
auto &mods{OmpGetModifiers(x)};
if (auto *mapType{OmpGetUniqueModifier<parser::OmpMapType>(mods)}) {
@@ -749,17 +743,13 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
ompFlag = Symbol::Flag::OmpMapToFrom;
break;
case parser::OmpMapType::Value::Alloc:
- ompFlag = Symbol::Flag::OmpMapAlloc;
- break;
case parser::OmpMapType::Value::Release:
- ompFlag = Symbol::Flag::OmpMapRelease;
+ case parser::OmpMapType::Value::Storage:
+ ompFlag = Symbol::Flag::OmpMapStorage;
break;
case parser::OmpMapType::Value::Delete:
ompFlag = Symbol::Flag::OmpMapDelete;
break;
- case parser::OmpMapType::Value::Storage:
- ompFlag = ompFlagForStorage;
- break;
}
}
if (!ompFlag) {
@@ -770,7 +760,7 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
// is present on the clause or if the list item for which the map-type
// is not specified is an assumed-size array.
if (OmpGetUniqueModifier<parser::OmpDeleteModifier>(mods)) {
- ompFlag = ompFlagForStorage;
+ ompFlag = Symbol::Flag::OmpMapStorage;
}
// Otherwise, if delete-modifier is absent, leave ompFlag unset.
} else {
@@ -788,7 +778,8 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
if (const auto *name{
semantics::getDesignatorNameIfDataRef(designator)}) {
if (name->symbol) {
- name->symbol->set(ompFlag.value_or(ompFlagForStorage));
+ name->symbol->set(
+ ompFlag.value_or(Symbol::Flag::OmpMapStorage));
AddToContextObjectWithDSA(*name->symbol, *ompFlag);
if (semantics::IsAssumedSizeArray(*name->symbol)) {
context_.Say(designator.source,
@@ -803,7 +794,7 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
},
ompObj.u);
- ResolveOmpObject(ompObj, ompFlag.value_or(ompFlagForStorage));
+ ResolveOmpObject(ompObj, ompFlag.value_or(Symbol::Flag::OmpMapStorage));
}
}
@@ -2802,9 +2793,8 @@ void OmpAttributeVisitor::ResolveOmpObject(
}
Symbol::Flag dataMappingAttributeFlags[] = {
Symbol::Flag::OmpMapTo, Symbol::Flag::OmpMapFrom,
- Symbol::Flag::OmpMapToFrom, Symbol::Flag::OmpMapAlloc,
- Symbol::Flag::OmpMapRelease, Symbol::Flag::OmpMapDelete,
- Symbol::Flag::OmpIsDevicePtr,
+ Symbol::Flag::OmpMapToFrom, Symbol::Flag::OmpMapStorage,
+ Symbol::Flag::OmpMapDelete, Symbol::Flag::OmpIsDevicePtr,
Symbol::Flag::OmpHasDeviceAddr};
Symbol::Flag dataSharingAttributeFlags[] = {
diff --git a/flang/lib/Semantics/symbol.cpp b/flang/lib/Semantics/symbol.cpp
index 0380207927ad3..2259cfcf23ece 100644
--- a/flang/lib/Semantics/symbol.cpp
+++ b/flang/lib/Semantics/symbol.cpp
@@ -861,8 +861,7 @@ std::string Symbol::OmpFlagToClauseName(Symbol::Flag ompFlag) {
case Symbol::Flag::OmpMapTo:
case Symbol::Flag::OmpMapFrom:
case Symbol::Flag::OmpMapToFrom:
- case Symbol::Flag::OmpMapAlloc:
- case Symbol::Flag::OmpMapRelease:
+ case Symbol::Flag::OmpMapStorage:
case Symbol::Flag::OmpMapDelete:
clauseName = "MAP";
break;
>From 20bc43526e52676b4571fe85c3fad35cad70a115 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Mon, 21 Jul 2025 09:31:44 -0500
Subject: [PATCH 08/10] Add testcase for using v60 modifiers in v52
---
.../Semantics/OpenMP/map-modifiers-v60.f90 | 35 +++++++++++++++++++
1 file changed, 35 insertions(+)
create mode 100644 flang/test/Semantics/OpenMP/map-modifiers-v60.f90
diff --git a/flang/test/Semantics/OpenMP/map-modifiers-v60.f90 b/flang/test/Semantics/OpenMP/map-modifiers-v60.f90
new file mode 100644
index 0000000000000..b3f2e5171d6d6
--- /dev/null
+++ b/flang/test/Semantics/OpenMP/map-modifiers-v60.f90
@@ -0,0 +1,35 @@
+!RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=52 -Werror
+
+subroutine f00(x)
+ integer :: x
+!WARNING: 'self-modifier' modifier is not supported in OpenMP v5.2, try -fopenmp-version=60
+ !$omp target map(self: x)
+ x = x + 1
+ !$omp end target
+end
+
+subroutine f01(x)
+ integer, pointer :: x
+!WARNING: 'ref-modifier' modifier is not supported in OpenMP v5.2, try -fopenmp-version=60
+ !$omp target map(ref_ptr: x)
+ x = x + 1
+ !$omp end target
+end
+
+subroutine f02(x)
+ integer, pointer :: x
+!WARNING: 'ref-modifier' modifier is not supported in OpenMP v5.2, try -fopenmp-version=60
+ !$omp target map(ref_ptee: x)
+ x = x + 1
+ !$omp end target
+end
+
+subroutine f03(x)
+ integer, pointer :: x
+!WARNING: 'ref-modifier' modifier is not supported in OpenMP v5.2, try -fopenmp-version=60
+ !$omp target map(ref_ptr_ptee: x)
+ x = x + 1
+ !$omp end target
+end
+
+
>From 7d232c536a47aa705107db336259e4470335e350 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Mon, 21 Jul 2025 09:35:48 -0500
Subject: [PATCH 09/10] Clearer names for enum-converting functions for map
modifiers
---
flang/lib/Lower/OpenMP/Clauses.cpp | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp
index ece4a8eaac8cd..686fba0154f44 100644
--- a/flang/lib/Lower/OpenMP/Clauses.cpp
+++ b/flang/lib/Lower/OpenMP/Clauses.cpp
@@ -1001,7 +1001,7 @@ Map make(const parser::OmpClause::Map &inp,
semantics::SemanticsContext &semaCtx) {
// inp.v -> parser::OmpMapClause
CLAUSET_ENUM_CONVERT( //
- convert1, parser::OmpMapType::Value, Map::MapType,
+ convertMapType, parser::OmpMapType::Value, Map::MapType,
// clang-format off
MS(Alloc, Storage)
MS(Delete, Storage)
@@ -1014,7 +1014,8 @@ Map make(const parser::OmpClause::Map &inp,
);
CLAUSET_ENUM_CONVERT( //
- convert2, parser::OmpMapTypeModifier::Value, Map::MapTypeModifier,
+ convertMapTypeMod, parser::OmpMapTypeModifier::Value,
+ Map::MapTypeModifier,
// clang-format off
MS(Always, Always)
MS(Close, Close)
@@ -1024,7 +1025,7 @@ Map make(const parser::OmpClause::Map &inp,
);
CLAUSET_ENUM_CONVERT( //
- convert3, parser::OmpRefModifier::Value, Map::RefModifier,
+ convertRefMod, parser::OmpRefModifier::Value, Map::RefModifier,
// clang-format off
MS(Ref_Ptee, RefPtee)
MS(Ref_Ptr, RefPtr)
@@ -1041,7 +1042,7 @@ Map make(const parser::OmpClause::Map &inp,
auto type = [&]() -> std::optional<Map::MapType> {
if (t1)
- return convert1(t1->v);
+ return convertMapType(t1->v);
return std::nullopt;
}();
@@ -1051,7 +1052,7 @@ Map make(const parser::OmpClause::Map &inp,
for (auto *typeMod :
semantics::OmpGetRepeatableModifier<parser::OmpMapTypeModifier>(mods)) {
- modSet.insert(convert2(typeMod->v));
+ modSet.insert(convertMapTypeMod(typeMod->v));
}
if (semantics::OmpGetUniqueModifier<parser::OmpAlwaysModifier>(mods))
modSet.insert(Map::MapTypeModifier::Always);
@@ -1072,7 +1073,7 @@ Map make(const parser::OmpClause::Map &inp,
auto refMod = [&]() -> std::optional<Map::RefModifier> {
if (auto *t = semantics::OmpGetUniqueModifier<parser::OmpRefModifier>(mods))
- return convert3(t->v);
+ return convertRefMod(t->v);
return std::nullopt;
}();
>From dd339d61a4e10e88edf2c569af7be3fd9684beea Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Mon, 21 Jul 2025 09:57:08 -0500
Subject: [PATCH 10/10] Remove now unused isMapEnteringConstruct
---
llvm/include/llvm/Frontend/OpenMP/OMP.h | 2 --
llvm/lib/Frontend/OpenMP/OMP.cpp | 14 --------------
2 files changed, 16 deletions(-)
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.h b/llvm/include/llvm/Frontend/OpenMP/OMP.h
index 48217384afca6..9d0a55432e1ae 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMP.h
+++ b/llvm/include/llvm/Frontend/OpenMP/OMP.h
@@ -68,8 +68,6 @@ static constexpr inline bool isPrivatizingClause(Clause C) {
}
}
-LLVM_ABI bool isMapEnteringConstruct(Directive D);
-
static constexpr unsigned FallbackVersion = 52;
LLVM_ABI ArrayRef<unsigned> getOpenMPVersions();
diff --git a/llvm/lib/Frontend/OpenMP/OMP.cpp b/llvm/lib/Frontend/OpenMP/OMP.cpp
index c23fb400666d6..555e2a61e411e 100644
--- a/llvm/lib/Frontend/OpenMP/OMP.cpp
+++ b/llvm/lib/Frontend/OpenMP/OMP.cpp
@@ -189,20 +189,6 @@ bool isCombinedConstruct(Directive D) {
return !getLeafConstructs(D).empty() && !isCompositeConstruct(D);
}
-bool isMapEnteringConstruct(Directive D) {
- for (Directive L : getLeafConstructsOrSelf(D)) {
- switch (L) {
- case OMPD_target:
- case OMPD_target_data:
- case OMPD_target_enter_data:
- return true;
- default:
- break;
- }
- }
- return false;
-}
-
ArrayRef<unsigned> getOpenMPVersions() {
static unsigned Versions[]{31, 40, 45, 50, 51, 52, 60};
return Versions;
More information about the flang-commits
mailing list