From 0929234481b4d6d015381fda490c05bbeff1e22f Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Wed, 16 Jul 2025 08:04:17 -0500 Subject: [PATCH 1/3] [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 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 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 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(Parser{}) || construct(Parser{})) +// 2.15.3.6 REDUCTION (reduction-identifier: variable-name-list) +TYPE_PARSER(construct(Parser{}) || + construct(Parser{})) + TYPE_PARSER(construct( // Parser{}, ":"_tok >> nonemptyList(Parser{}), @@ -442,9 +446,18 @@ TYPE_PARSER(construct( TYPE_PARSER(construct(scalarIntExpr)) +TYPE_PARSER(construct( // + "ALWAYS" >> pure(OmpAlwaysModifier::Value::Always))) + TYPE_PARSER(construct( // "SIMD" >> pure(OmpChunkModifier::Value::Simd))) +TYPE_PARSER(construct( // + "CLOSE" >> pure(OmpCloseModifier::Value::Close))) + +TYPE_PARSER(construct( // + "DELETE" >> pure(OmpDeleteModifier::Value::Delete))) + TYPE_PARSER(construct( "SINK" >> pure(OmpDependenceType::Value::Sink) || "SOURCE" >> pure(OmpDependenceType::Value::Source))) @@ -502,26 +515,16 @@ TYPE_PARSER(construct( // TYPE_PARSER(construct( // "MAPPER"_tok >> parenthesized(Parser{}))) -// map-type -> ALLOC | DELETE | FROM | RELEASE | TO | TOFROM +// map-type -> ALLOC | DELETE | FROM | RELEASE | STORAGE | TO | TOFROM TYPE_PARSER(construct( // "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( - "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(Parser{}) || - construct(Parser{})) - TYPE_PARSER(construct( "REPRODUCIBLE" >> pure(OmpOrderModifier::Value::Reproducible) || "UNCONSTRAINED" >> pure(OmpOrderModifier::Value::Unconstrained))) @@ -534,11 +537,22 @@ TYPE_PARSER(construct( TYPE_PARSER(construct( "STRICT" >> pure(OmpPrescriptiveness::Value::Strict))) +TYPE_PARSER(construct( // + "PRESENT" >> pure(OmpPresentModifier::Value::Present))) + TYPE_PARSER(construct( "INSCAN" >> pure(OmpReductionModifier::Value::Inscan) || "TASK" >> pure(OmpReductionModifier::Value::Task) || "DEFAULT" >> pure(OmpReductionModifier::Value::Default))) +TYPE_PARSER(construct( // + "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( // + "SELF" >> pure(OmpSelfModifier::Value::Self))) + TYPE_PARSER(construct( // "STEP" >> parenthesized(scalarIntExpr))) @@ -559,6 +573,9 @@ TYPE_PARSER(construct( "POINTER" >> pure(OmpVariableCategory::Value::Pointer) || "SCALAR" >> pure(OmpVariableCategory::Value::Scalar))) +TYPE_PARSER(construct( // + "OMPX_HOLD" >> pure(OmpxHoldModifier::Value::Ompx_Hold))) + // This could be auto-generated. TYPE_PARSER( sourced(construct(Parser{}))) @@ -611,10 +628,16 @@ TYPE_PARSER(sourced( construct(Parser{}))) TYPE_PARSER(sourced(construct( - sourced(construct(Parser{}) || + sourced(construct(Parser{}) || + construct(Parser{}) || + construct(Parser{}) || + construct(Parser{}) || + construct(Parser{}) || + construct(Parser{}) || construct(Parser{}) || construct(Parser{}) || - construct(Parser{}))))) + construct(Parser{}) || + construct(Parser{}))))) TYPE_PARSER( sourced(construct(Parser{}))) 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 bool Pre(T &) { return true; } template 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 T *GetConstructIf(parser::ExecutionPartConstruct &x) { if (auto *y{std::get_if(&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>; + auto &modifiers{std::get(map.t)}; + if (!modifiers) { + return; + } + + using MapTypeModifier = parser::OmpMapTypeModifier; + using MapType = parser::OmpMapType; + + for (auto &mod : *modifiers) { + if (std::holds_alternative(mod.u)) { + mod.u = MapTypeModifier(MapTypeModifier::Value::Always); + } else if (std::holds_alternative(mod.u)) { + mod.u = MapTypeModifier(MapTypeModifier::Value::Close); + } else if (std::holds_alternative(mod.u)) { + mod.u = MapTypeModifier(MapTypeModifier::Value::Present); + } else if (std::holds_alternative(mod.u)) { + mod.u = MapTypeModifier(MapTypeModifier::Value::Ompx_Hold); + } else if (std::holds_alternative(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 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() { return desc; } +template <> +const OmpModifierDescriptor &OmpGetDescriptor() { + static const OmpModifierDescriptor desc{ + /*name=*/"always-modifier", + /*props=*/ + { + {45, {OmpProperty::Unique}}, + }, + /*clauses=*/ + { + {45, {Clause::OMPC_map}}, + }, + }; + return desc; +} + template <> const OmpModifierDescriptor &OmpGetDescriptor() { static const OmpModifierDescriptor desc{ @@ -156,6 +172,22 @@ const OmpModifierDescriptor &OmpGetDescriptor() { return desc; } +template <> +const OmpModifierDescriptor &OmpGetDescriptor() { + static const OmpModifierDescriptor desc{ + /*name=*/"close-modifier", + /*props=*/ + { + {50, {OmpProperty::Unique}}, + }, + /*clauses=*/ + { + {50, {Clause::OMPC_map}}, + }, + }; + return desc; +} + template <> const OmpModifierDescriptor &OmpGetDescriptor() { static const OmpModifierDescriptor desc{ @@ -173,6 +205,23 @@ const OmpModifierDescriptor &OmpGetDescriptor() { return desc; } +template <> +const OmpModifierDescriptor &OmpGetDescriptor() { + 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() { static const OmpModifierDescriptor desc{ @@ -347,6 +396,7 @@ const OmpModifierDescriptor &OmpGetDescriptor() { /*props=*/ { {45, {OmpProperty::Ultimate}}, + {60, {OmpProperty::Unique}}, }, /*clauses=*/ { @@ -367,6 +417,7 @@ const OmpModifierDescriptor &OmpGetDescriptor() { /*clauses=*/ { {45, {Clause::OMPC_map}}, + {60, {}}, }, }; return desc; @@ -420,6 +471,22 @@ const OmpModifierDescriptor &OmpGetDescriptor() { return desc; } +template <> +const OmpModifierDescriptor &OmpGetDescriptor() { + static const OmpModifierDescriptor desc{ + /*name=*/"present-modifier", + /*props=*/ + { + {51, {OmpProperty::Unique}}, + }, + /*clauses=*/ + { + {51, {Clause::OMPC_map}}, + }, + }; + return desc; +} + template <> const OmpModifierDescriptor & OmpGetDescriptor() { @@ -456,6 +523,38 @@ const OmpModifierDescriptor &OmpGetDescriptor() { return desc; } +template <> +const OmpModifierDescriptor &OmpGetDescriptor() { + static const OmpModifierDescriptor desc{ + /*name=*/"ref-modifier", + /*props=*/ + { + {60, {OmpProperty::Unique}}, + }, + /*clauses=*/ + { + {60, {Clause::OMPC_map}}, + }, + }; + return desc; +} + +template <> +const OmpModifierDescriptor &OmpGetDescriptor() { + static const OmpModifierDescriptor desc{ + /*name=*/"self-modifier", + /*props=*/ + { + {60, {OmpProperty::Unique}}, + }, + /*clauses=*/ + { + {60, {Clause::OMPC_map}}, + }, + }; + return desc; +} + template <> const OmpModifierDescriptor & OmpGetDescriptor() { @@ -522,4 +621,20 @@ const OmpModifierDescriptor &OmpGetDescriptor() { }; return desc; } + +template <> +const OmpModifierDescriptor &OmpGetDescriptor() { + 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 { case parser::OmpMapType::Value::Delete: ompFlag = Symbol::Flag::OmpMapDelete; break; + default: + break; } } const auto &ompObjList{std::get(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 faff0d32746640c34988a65552e277198748fcf2 Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Mon, 21 Jul 2025 08:49:18 -0500 Subject: [PATCH 2/3] 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 bool Pre(T &) { return true; } template 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 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 64ec502991cddd823f7c1a1834255776d1cbab00 Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Mon, 21 Jul 2025 10:26:43 -0500 Subject: [PATCH 3/3] Add link to the description of ompx_hold --- flang/include/flang/Parser/parse-tree.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h index 92a449d2f9d49..0b3dec1010312 100644 --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -4079,7 +4079,8 @@ struct OmpVariableCategory { WRAPPER_CLASS_BOILERPLATE(OmpVariableCategory, Value); }; -// Extension +// Extension: +// https://openmp.llvm.org//openacc/OpenMPExtensions.html#ompx-hold // // ompx-hold-modifier -> // OMPX_HOLD // since 4.5