Skip to content

Commit 2914a48

Browse files
authored
[flang][OpenMP] Sema checks, lowering with new format of MAP modifiers (#149137)
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.
1 parent b692b23 commit 2914a48

File tree

19 files changed

+294
-128
lines changed

19 files changed

+294
-128
lines changed

flang/include/flang/Semantics/symbol.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -812,9 +812,8 @@ class Symbol {
812812
// OpenMP data-sharing attribute
813813
OmpShared, OmpPrivate, OmpLinear, OmpFirstPrivate, OmpLastPrivate,
814814
// OpenMP data-mapping attribute
815-
OmpMapTo, OmpMapFrom, OmpMapToFrom, OmpMapAlloc, OmpMapRelease,
816-
OmpMapDelete, OmpUseDevicePtr, OmpUseDeviceAddr, OmpIsDevicePtr,
817-
OmpHasDeviceAddr,
815+
OmpMapTo, OmpMapFrom, OmpMapToFrom, OmpMapStorage, OmpMapDelete,
816+
OmpUseDevicePtr, OmpUseDeviceAddr, OmpIsDevicePtr, OmpHasDeviceAddr,
818817
// OpenMP data-copying attribute
819818
OmpCopyIn, OmpCopyPrivate,
820819
// OpenMP miscellaneous flags

flang/lib/Lower/OpenMP/ClauseProcessor.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1315,7 +1315,8 @@ bool ClauseProcessor::processMap(
13151315
const parser::CharBlock &source) {
13161316
using Map = omp::clause::Map;
13171317
mlir::Location clauseLocation = converter.genLocation(source);
1318-
const auto &[mapType, typeMods, mappers, iterator, objects] = clause.t;
1318+
const auto &[mapType, typeMods, refMod, mappers, iterator, objects] =
1319+
clause.t;
13191320
llvm::omp::OpenMPOffloadMappingFlags mapTypeBits =
13201321
llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE;
13211322
std::string mapperIdName = "__implicit_mapper";
@@ -1342,16 +1343,13 @@ bool ClauseProcessor::processMap(
13421343
mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO |
13431344
llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
13441345
break;
1345-
case Map::MapType::Alloc:
1346-
case Map::MapType::Release:
1346+
case Map::MapType::Storage:
13471347
// alloc and release is the default map_type for the Target Data
13481348
// Ops, i.e. if no bits for map_type is supplied then alloc/release
1349-
// is implicitly assumed based on the target directive. Default
1350-
// value for Target Data and Enter Data is alloc and for Exit Data
1351-
// it is release.
1349+
// (aka storage in 6.0+) is implicitly assumed based on the target
1350+
// directive. Default value for Target Data and Enter Data is alloc
1351+
// and for Exit Data it is release.
13521352
break;
1353-
case Map::MapType::Delete:
1354-
mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_DELETE;
13551353
}
13561354

13571355
if (typeMods) {
@@ -1362,6 +1360,8 @@ bool ClauseProcessor::processMap(
13621360
mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
13631361
if (llvm::is_contained(*typeMods, Map::MapTypeModifier::Close))
13641362
mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_CLOSE;
1363+
if (llvm::is_contained(*typeMods, Map::MapTypeModifier::Delete))
1364+
mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_DELETE;
13651365
if (llvm::is_contained(*typeMods, Map::MapTypeModifier::OmpxHold))
13661366
mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
13671367
}

flang/lib/Lower/OpenMP/Clauses.cpp

Lines changed: 65 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1001,19 +1001,21 @@ Map make(const parser::OmpClause::Map &inp,
10011001
semantics::SemanticsContext &semaCtx) {
10021002
// inp.v -> parser::OmpMapClause
10031003
CLAUSET_ENUM_CONVERT( //
1004-
convert1, parser::OmpMapType::Value, Map::MapType,
1004+
convertMapType, parser::OmpMapType::Value, Map::MapType,
10051005
// clang-format off
1006-
MS(Alloc, Alloc)
1007-
MS(Delete, Delete)
1008-
MS(From, From)
1009-
MS(Release, Release)
1010-
MS(To, To)
1011-
MS(Tofrom, Tofrom)
1006+
MS(Alloc, Storage)
1007+
MS(Delete, Storage)
1008+
MS(Release, Storage)
1009+
MS(Storage, Storage)
1010+
MS(From, From)
1011+
MS(To, To)
1012+
MS(Tofrom, Tofrom)
10121013
// clang-format on
10131014
);
10141015

10151016
CLAUSET_ENUM_CONVERT( //
1016-
convert2, parser::OmpMapTypeModifier::Value, Map::MapTypeModifier,
1017+
convertMapTypeMod, parser::OmpMapTypeModifier::Value,
1018+
Map::MapTypeModifier,
10171019
// clang-format off
10181020
MS(Always, Always)
10191021
MS(Close, Close)
@@ -1022,43 +1024,76 @@ Map make(const parser::OmpClause::Map &inp,
10221024
// clang-format on
10231025
);
10241026

1027+
CLAUSET_ENUM_CONVERT( //
1028+
convertRefMod, parser::OmpRefModifier::Value, Map::RefModifier,
1029+
// clang-format off
1030+
MS(Ref_Ptee, RefPtee)
1031+
MS(Ref_Ptr, RefPtr)
1032+
MS(Ref_Ptr_Ptee, RefPtrPtee)
1033+
// clang-format on
1034+
);
1035+
1036+
// Treat always, close, present, self, delete modifiers as map-type-
1037+
// modifiers.
10251038
auto &mods = semantics::OmpGetModifiers(inp.v);
1026-
auto *t1 = semantics::OmpGetUniqueModifier<parser::OmpMapper>(mods);
1027-
auto *t2 = semantics::OmpGetUniqueModifier<parser::OmpIterator>(mods);
1028-
auto *t3 = semantics::OmpGetUniqueModifier<parser::OmpMapType>(mods);
1029-
auto &t4 = std::get<parser::OmpObjectList>(inp.v.t);
10301039

1031-
auto mappers = [&]() -> std::optional<List<Mapper>> {
1040+
auto *t1 = semantics::OmpGetUniqueModifier<parser::OmpMapType>(mods);
1041+
auto &t2 = std::get<parser::OmpObjectList>(inp.v.t);
1042+
1043+
auto type = [&]() -> std::optional<Map::MapType> {
10321044
if (t1)
1033-
return List<Mapper>{Mapper{makeObject(t1->v, semaCtx)}};
1045+
return convertMapType(t1->v);
10341046
return std::nullopt;
10351047
}();
10361048

1037-
auto iterator = [&]() -> std::optional<Iterator> {
1038-
if (t2)
1039-
return makeIterator(*t2, semaCtx);
1049+
llvm::DenseSet<Map::MapTypeModifier> modSet;
1050+
if (t1 && t1->v == parser::OmpMapType::Value::Delete)
1051+
modSet.insert(Map::MapTypeModifier::Delete);
1052+
1053+
for (auto *typeMod :
1054+
semantics::OmpGetRepeatableModifier<parser::OmpMapTypeModifier>(mods)) {
1055+
modSet.insert(convertMapTypeMod(typeMod->v));
1056+
}
1057+
if (semantics::OmpGetUniqueModifier<parser::OmpAlwaysModifier>(mods))
1058+
modSet.insert(Map::MapTypeModifier::Always);
1059+
if (semantics::OmpGetUniqueModifier<parser::OmpCloseModifier>(mods))
1060+
modSet.insert(Map::MapTypeModifier::Close);
1061+
if (semantics::OmpGetUniqueModifier<parser::OmpDeleteModifier>(mods))
1062+
modSet.insert(Map::MapTypeModifier::Delete);
1063+
if (semantics::OmpGetUniqueModifier<parser::OmpPresentModifier>(mods))
1064+
modSet.insert(Map::MapTypeModifier::Present);
1065+
if (semantics::OmpGetUniqueModifier<parser::OmpSelfModifier>(mods))
1066+
modSet.insert(Map::MapTypeModifier::Self);
1067+
if (semantics::OmpGetUniqueModifier<parser::OmpxHoldModifier>(mods))
1068+
modSet.insert(Map::MapTypeModifier::OmpxHold);
1069+
1070+
std::optional<Map::MapTypeModifiers> maybeTypeMods{};
1071+
if (!modSet.empty())
1072+
maybeTypeMods = Map::MapTypeModifiers(modSet.begin(), modSet.end());
1073+
1074+
auto refMod = [&]() -> std::optional<Map::RefModifier> {
1075+
if (auto *t = semantics::OmpGetUniqueModifier<parser::OmpRefModifier>(mods))
1076+
return convertRefMod(t->v);
10401077
return std::nullopt;
10411078
}();
10421079

1043-
auto type = [&]() -> std::optional<Map::MapType> {
1044-
if (t3)
1045-
return convert1(t3->v);
1080+
auto mappers = [&]() -> std::optional<List<Mapper>> {
1081+
if (auto *t = semantics::OmpGetUniqueModifier<parser::OmpMapper>(mods))
1082+
return List<Mapper>{Mapper{makeObject(t->v, semaCtx)}};
10461083
return std::nullopt;
10471084
}();
10481085

1049-
Map::MapTypeModifiers typeMods;
1050-
for (auto *typeMod :
1051-
semantics::OmpGetRepeatableModifier<parser::OmpMapTypeModifier>(mods)) {
1052-
typeMods.push_back(convert2(typeMod->v));
1053-
}
1054-
std::optional<Map::MapTypeModifiers> maybeTypeMods{};
1055-
if (!typeMods.empty())
1056-
maybeTypeMods = std::move(typeMods);
1086+
auto iterator = [&]() -> std::optional<Iterator> {
1087+
if (auto *t = semantics::OmpGetUniqueModifier<parser::OmpIterator>(mods))
1088+
return makeIterator(*t, semaCtx);
1089+
return std::nullopt;
1090+
}();
10571091

10581092
return Map{{/*MapType=*/std::move(type),
10591093
/*MapTypeModifiers=*/std::move(maybeTypeMods),
1060-
/*Mapper=*/std::move(mappers), /*Iterator=*/std::move(iterator),
1061-
/*LocatorList=*/makeObjects(t4, semaCtx)}};
1094+
/*RefModifier=*/std::move(refMod), /*Mapper=*/std::move(mappers),
1095+
/*Iterator=*/std::move(iterator),
1096+
/*LocatorList=*/makeObjects(t2, semaCtx)}};
10621097
}
10631098

10641099
Match make(const parser::OmpClause::Match &inp,

flang/lib/Semantics/canonicalize-omp.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ class CanonicalizationOfOmp {
2727
public:
2828
template <typename T> bool Pre(T &) { return true; }
2929
template <typename T> void Post(T &) {}
30-
CanonicalizationOfOmp(parser::Messages &messages) : messages_{messages} {}
30+
CanonicalizationOfOmp(SemanticsContext &context)
31+
: context_{context}, messages_{context.messages()} {}
3132

3233
void Post(parser::Block &block) {
3334
for (auto it{block.begin()}; it != block.end(); ++it) {
@@ -401,6 +402,11 @@ class CanonicalizationOfOmp {
401402
// if the specified OpenMP version is less than 6.0, rewrite the affected
402403
// modifiers back into the pre-6.0 forms.
403404
void CanonicalizeMapModifiers(parser::OmpMapClause &map) {
405+
unsigned version{context_.langOptions().OpenMPVersion};
406+
if (version >= 60) {
407+
return;
408+
}
409+
404410
// Omp{Always, Close, Present, xHold}Modifier -> OmpMapTypeModifier
405411
// OmpDeleteModifier -> OmpMapType
406412
using Modifier = parser::OmpMapClause::Modifier;
@@ -432,12 +438,13 @@ class CanonicalizationOfOmp {
432438
// same construct. This is for converting utility constructs to executable
433439
// constructs.
434440
std::map<parser::SpecificationPart *, parser::Block *> blockForSpec_;
441+
SemanticsContext &context_;
435442
parser::Messages &messages_;
436443
};
437444

438-
bool CanonicalizeOmp(parser::Messages &messages, parser::Program &program) {
439-
CanonicalizationOfOmp omp{messages};
445+
bool CanonicalizeOmp(SemanticsContext &context, parser::Program &program) {
446+
CanonicalizationOfOmp omp{context};
440447
Walk(program, omp);
441-
return !messages.AnyFatalError();
448+
return !context.messages().AnyFatalError();
442449
}
443450
} // namespace Fortran::semantics

flang/lib/Semantics/canonicalize-omp.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,12 @@
1111

1212
namespace Fortran::parser {
1313
struct Program;
14-
class Messages;
15-
} // namespace Fortran::parser
14+
}
1615

1716
namespace Fortran::semantics {
1817
class SemanticsContext;
1918

20-
bool CanonicalizeOmp(parser::Messages &messages, parser::Program &program);
19+
bool CanonicalizeOmp(SemanticsContext &context, parser::Program &program);
2120
} // namespace Fortran::semantics
2221

2322
#endif // FORTRAN_SEMANTICS_CANONICALIZE_OMP_H_

flang/lib/Semantics/check-omp-structure.cpp

Lines changed: 71 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737

3838
#include "llvm/ADT/ArrayRef.h"
3939
#include "llvm/ADT/STLExtras.h"
40+
#include "llvm/ADT/StringExtras.h"
4041
#include "llvm/ADT/StringRef.h"
4142
#include "llvm/Frontend/OpenMP/OMP.h"
4243

@@ -3398,23 +3399,22 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Detach &x) {
33983399
}
33993400
}
34003401

3401-
void OmpStructureChecker::CheckAllowedMapTypes(
3402-
const parser::OmpMapType::Value &type,
3403-
const std::list<parser::OmpMapType::Value> &allowedMapTypeList) {
3404-
if (!llvm::is_contained(allowedMapTypeList, type)) {
3405-
std::string commaSeparatedMapTypes;
3406-
llvm::interleave(
3407-
allowedMapTypeList.begin(), allowedMapTypeList.end(),
3408-
[&](const parser::OmpMapType::Value &mapType) {
3409-
commaSeparatedMapTypes.append(parser::ToUpperCaseLetters(
3410-
parser::OmpMapType::EnumToString(mapType)));
3411-
},
3412-
[&] { commaSeparatedMapTypes.append(", "); });
3413-
context_.Say(GetContext().clauseSource,
3414-
"Only the %s map types are permitted "
3415-
"for MAP clauses on the %s directive"_err_en_US,
3416-
commaSeparatedMapTypes, ContextDirectiveAsFortran());
3402+
void OmpStructureChecker::CheckAllowedMapTypes(parser::OmpMapType::Value type,
3403+
llvm::ArrayRef<parser::OmpMapType::Value> allowed) {
3404+
if (llvm::is_contained(allowed, type)) {
3405+
return;
34173406
}
3407+
3408+
llvm::SmallVector<std::string> names;
3409+
llvm::transform(
3410+
allowed, std::back_inserter(names), [](parser::OmpMapType::Value val) {
3411+
return parser::ToUpperCaseLetters(
3412+
parser::OmpMapType::EnumToString(val));
3413+
});
3414+
llvm::sort(names);
3415+
context_.Say(GetContext().clauseSource,
3416+
"Only the %s map types are permitted for MAP clauses on the %s directive"_err_en_US,
3417+
llvm::join(names, ", "), ContextDirectiveAsFortran());
34183418
}
34193419

34203420
void OmpStructureChecker::Enter(const parser::OmpClause::Map &x) {
@@ -3435,27 +3435,62 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Map &x) {
34353435
CheckIteratorModifier(*iter);
34363436
}
34373437
if (auto *type{OmpGetUniqueModifier<parser::OmpMapType>(modifiers)}) {
3438+
using Directive = llvm::omp::Directive;
34383439
using Value = parser::OmpMapType::Value;
3439-
switch (GetContext().directive) {
3440-
case llvm::omp::Directive::OMPD_target:
3441-
case llvm::omp::Directive::OMPD_target_teams:
3442-
case llvm::omp::Directive::OMPD_target_teams_distribute:
3443-
case llvm::omp::Directive::OMPD_target_teams_distribute_simd:
3444-
case llvm::omp::Directive::OMPD_target_teams_distribute_parallel_do:
3445-
case llvm::omp::Directive::OMPD_target_teams_distribute_parallel_do_simd:
3446-
case llvm::omp::Directive::OMPD_target_data:
3447-
CheckAllowedMapTypes(
3448-
type->v, {Value::To, Value::From, Value::Tofrom, Value::Alloc});
3449-
break;
3450-
case llvm::omp::Directive::OMPD_target_enter_data:
3451-
CheckAllowedMapTypes(type->v, {Value::To, Value::Alloc});
3452-
break;
3453-
case llvm::omp::Directive::OMPD_target_exit_data:
3454-
CheckAllowedMapTypes(
3455-
type->v, {Value::From, Value::Release, Value::Delete});
3456-
break;
3457-
default:
3458-
break;
3440+
3441+
static auto isValidForVersion{
3442+
[](parser::OmpMapType::Value t, unsigned version) {
3443+
switch (t) {
3444+
case parser::OmpMapType::Value::Alloc:
3445+
case parser::OmpMapType::Value::Delete:
3446+
case parser::OmpMapType::Value::Release:
3447+
return version < 60;
3448+
case parser::OmpMapType::Value::Storage:
3449+
return version >= 60;
3450+
default:
3451+
return true;
3452+
}
3453+
}};
3454+
3455+
llvm::SmallVector<parser::OmpMapType::Value> mapEnteringTypes{[&]() {
3456+
llvm::SmallVector<parser::OmpMapType::Value> result;
3457+
for (size_t i{0}; i != parser::OmpMapType::Value_enumSize; ++i) {
3458+
auto t{static_cast<parser::OmpMapType::Value>(i)};
3459+
if (isValidForVersion(t, version) && IsMapEnteringType(t)) {
3460+
result.push_back(t);
3461+
}
3462+
}
3463+
return result;
3464+
}()};
3465+
llvm::SmallVector<parser::OmpMapType::Value> mapExitingTypes{[&]() {
3466+
llvm::SmallVector<parser::OmpMapType::Value> result;
3467+
for (size_t i{0}; i != parser::OmpMapType::Value_enumSize; ++i) {
3468+
auto t{static_cast<parser::OmpMapType::Value>(i)};
3469+
if (isValidForVersion(t, version) && IsMapExitingType(t)) {
3470+
result.push_back(t);
3471+
}
3472+
}
3473+
return result;
3474+
}()};
3475+
3476+
llvm::omp::Directive dir{GetContext().directive};
3477+
llvm::ArrayRef<llvm::omp::Directive> leafs{
3478+
llvm::omp::getLeafConstructsOrSelf(dir)};
3479+
3480+
if (llvm::is_contained(leafs, Directive::OMPD_target) ||
3481+
llvm::is_contained(leafs, Directive::OMPD_target_data)) {
3482+
if (version >= 60) {
3483+
// Map types listed in the decay table. [6.0:276]
3484+
CheckAllowedMapTypes(
3485+
type->v, {Value::Storage, Value::From, Value::To, Value::Tofrom});
3486+
} else {
3487+
CheckAllowedMapTypes(
3488+
type->v, {Value::Alloc, Value::From, Value::To, Value::Tofrom});
3489+
}
3490+
} else if (llvm::is_contained(leafs, Directive::OMPD_target_enter_data)) {
3491+
CheckAllowedMapTypes(type->v, mapEnteringTypes);
3492+
} else if (llvm::is_contained(leafs, Directive::OMPD_target_exit_data)) {
3493+
CheckAllowedMapTypes(type->v, mapExitingTypes);
34593494
}
34603495
}
34613496

flang/lib/Semantics/check-omp-structure.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,8 +179,8 @@ class OmpStructureChecker
179179
void HasInvalidDistributeNesting(const parser::OpenMPLoopConstruct &x);
180180
void HasInvalidLoopBinding(const parser::OpenMPLoopConstruct &x);
181181
// specific clause related
182-
void CheckAllowedMapTypes(const parser::OmpMapType::Value &,
183-
const std::list<parser::OmpMapType::Value> &);
182+
void CheckAllowedMapTypes(
183+
parser::OmpMapType::Value, llvm::ArrayRef<parser::OmpMapType::Value>);
184184

185185
const std::list<parser::OmpTraitProperty> &GetTraitPropertyList(
186186
const parser::OmpTraitSelector &);

0 commit comments

Comments
 (0)