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/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..686fba0154f44 100644 --- a/flang/lib/Lower/OpenMP/Clauses.cpp +++ b/flang/lib/Lower/OpenMP/Clauses.cpp @@ -1001,19 +1001,21 @@ 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, Alloc) - MS(Delete, Delete) - MS(From, From) - MS(Release, Release) - MS(To, To) - MS(Tofrom, Tofrom) + 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, + convertMapTypeMod, parser::OmpMapTypeModifier::Value, + Map::MapTypeModifier, // clang-format off MS(Always, Always) MS(Close, Close) @@ -1022,43 +1024,76 @@ Map make(const parser::OmpClause::Map &inp, // clang-format on ); + CLAUSET_ENUM_CONVERT( // + convertRefMod, parser::OmpRefModifier::Value, Map::RefModifier, + // clang-format off + 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(mods); - auto *t2 = semantics::OmpGetUniqueModifier(mods); - auto *t3 = semantics::OmpGetUniqueModifier(mods); - auto &t4 = std::get(inp.v.t); - auto mappers = [&]() -> std::optional> { + auto *t1 = semantics::OmpGetUniqueModifier(mods); + auto &t2 = std::get(inp.v.t); + + auto type = [&]() -> std::optional { if (t1) - return List{Mapper{makeObject(t1->v, semaCtx)}}; + return convertMapType(t1->v); return std::nullopt; }(); - auto iterator = [&]() -> std::optional { - if (t2) - return makeIterator(*t2, semaCtx); + llvm::DenseSet modSet; + if (t1 && t1->v == parser::OmpMapType::Value::Delete) + modSet.insert(Map::MapTypeModifier::Delete); + + for (auto *typeMod : + semantics::OmpGetRepeatableModifier(mods)) { + modSet.insert(convertMapTypeMod(typeMod->v)); + } + if (semantics::OmpGetUniqueModifier(mods)) + modSet.insert(Map::MapTypeModifier::Always); + if (semantics::OmpGetUniqueModifier(mods)) + modSet.insert(Map::MapTypeModifier::Close); + if (semantics::OmpGetUniqueModifier(mods)) + modSet.insert(Map::MapTypeModifier::Delete); + if (semantics::OmpGetUniqueModifier(mods)) + modSet.insert(Map::MapTypeModifier::Present); + if (semantics::OmpGetUniqueModifier(mods)) + modSet.insert(Map::MapTypeModifier::Self); + if (semantics::OmpGetUniqueModifier(mods)) + modSet.insert(Map::MapTypeModifier::OmpxHold); + + std::optional maybeTypeMods{}; + if (!modSet.empty()) + maybeTypeMods = Map::MapTypeModifiers(modSet.begin(), modSet.end()); + + auto refMod = [&]() -> std::optional { + if (auto *t = semantics::OmpGetUniqueModifier(mods)) + return convertRefMod(t->v); return std::nullopt; }(); - auto type = [&]() -> std::optional { - if (t3) - return convert1(t3->v); + auto mappers = [&]() -> std::optional> { + if (auto *t = semantics::OmpGetUniqueModifier(mods)) + return List{Mapper{makeObject(t->v, semaCtx)}}; return std::nullopt; }(); - Map::MapTypeModifiers typeMods; - for (auto *typeMod : - semantics::OmpGetRepeatableModifier(mods)) { - typeMods.push_back(convert2(typeMod->v)); - } - std::optional maybeTypeMods{}; - if (!typeMods.empty()) - maybeTypeMods = std::move(typeMods); + auto iterator = [&]() -> std::optional { + if (auto *t = semantics::OmpGetUniqueModifier(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 bba4d72a702e9..77e2fd6ca5097 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) { @@ -401,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; @@ -432,12 +438,13 @@ class CanonicalizationOfOmp { // 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 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/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index e4a94efcc6b55..8264e1d5e8fd9 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" @@ -3398,23 +3399,22 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Detach &x) { } } -void OmpStructureChecker::CheckAllowedMapTypes( - const parser::OmpMapType::Value &type, - const std::list &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 allowed) { + if (llvm::is_contained(allowed, type)) { + return; } + + llvm::SmallVector 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) { @@ -3435,27 +3435,62 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Map &x) { CheckIteratorModifier(*iter); } if (auto *type{OmpGetUniqueModifier(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 mapEnteringTypes{[&]() { + llvm::SmallVector result; + for (size_t i{0}; i != parser::OmpMapType::Value_enumSize; ++i) { + auto t{static_cast(i)}; + if (isValidForVersion(t, version) && IsMapEnteringType(t)) { + result.push_back(t); + } + } + return result; + }()}; + llvm::SmallVector mapExitingTypes{[&]() { + llvm::SmallVector result; + for (size_t i{0}; i != parser::OmpMapType::Value_enumSize; ++i) { + auto t{static_cast(i)}; + if (isValidForVersion(t, version) && IsMapExitingType(t)) { + result.push_back(t); + } + } + return result; + }()}; + + llvm::omp::Directive dir{GetContext().directive}; + llvm::ArrayRef 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 &); + void CheckAllowedMapTypes( + parser::OmpMapType::Value, llvm::ArrayRef); const std::list &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 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 GetEvaluateExpr(const parser::Expr &parserExpr); std::optional GetDynamicType( const parser::Expr &parserExpr); diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp index 332291a2aefe8..addd7d322a4fd 100644 --- a/flang/lib/Semantics/resolve-directives.cpp +++ b/flang/lib/Semantics/resolve-directives.cpp @@ -727,7 +727,9 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor { 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}; + std::optional ompFlag; + auto &mods{OmpGetModifiers(x)}; if (auto *mapType{OmpGetUniqueModifier(mods)}) { switch (mapType->v) { @@ -741,10 +743,9 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor { 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; @@ -753,6 +754,24 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor { 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(mods)) { + ompFlag = Symbol::Flag::OmpMapStorage; + } + // 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(x.t)}; for (const auto &ompObj : ompObjList.v) { common::visit( @@ -761,15 +780,15 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor { 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(Symbol::Flag::OmpMapStorage)); + 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"); + } } } }, @@ -777,7 +796,7 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor { }, ompObj.u); - ResolveOmpObject(ompObj, ompFlag); + ResolveOmpObject(ompObj, ompFlag.value_or(Symbol::Flag::OmpMapStorage)); } } @@ -2776,9 +2795,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/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_} 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; diff --git a/flang/test/Lower/OpenMP/map-modifiers.f90 b/flang/test/Lower/OpenMP/map-modifiers.f90 index 64d7869cbb836..be93c14627f9a 100644 --- a/flang/test/Lower/OpenMP/map-modifiers.f90 +++ b/flang/test/Lower/OpenMP/map-modifiers.f90 @@ -1,4 +1,6 @@ ! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=51 %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=60 %s -o - | FileCheck %s subroutine map_present_target_data integer :: x @@ -15,6 +17,14 @@ subroutine map_present_update !$omp target update to(present: x) end subroutine +subroutine map_always + integer :: x +!CHECK: %[[MAP:.*]] = omp.map.info {{.*}} map_clauses(always, tofrom) {{.*}} {name = "x"} +!CHECK: omp.target_data map_entries(%[[MAP]] : {{.*}}) { +!$omp target data map(always, tofrom: x) +!$omp end target data +end subroutine + subroutine map_close integer :: x !CHECK: %[[MAP:.*]] = omp.map.info {{.*}} map_clauses(close, tofrom) {{.*}} {name = "x"} 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/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 + + 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 // struct MapT { using LocatorList = ObjectListT; - 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>; // Not a spec name using Iterator = type::IteratorT; using MapTypeModifiers = ListT; // Not a spec name using TupleTrait = std::true_type; - std::tuple + std::tuple 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::applyClause( tomp::clause::MapT{ {/*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::applyClause( llvm::omp::Clause::OMPC_map, tomp::clause::MapT{ {/*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/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