Skip to content

Commit 148a557

Browse files
authored
[flang][OpenMP] Make OpenMP clause representation language-agnostic (#86289)
The clause templates defined in ClauseT.h were originally based on flang's parse tree nodes. Since those representations are going to be reused for clang (together with the clause splitting code), it makes sense to separate them from flang, and instead have them based on the actual OpenMP spec (v5.2). The member names in the templates follow the naming presented in the spec, and the representation (e.g. members) is derived from the clause definitions as described in the spec. Since the representations of some clauses has changed (while preserving the information), the current code using the clauses (especially the code converting parser::OmpClause to omp::Clause) needs to be adjusted. This patch does not make any functional changes.
1 parent 2fbc40d commit 148a557

File tree

9 files changed

+2011
-1082
lines changed

9 files changed

+2011
-1082
lines changed

flang/lib/Lower/OpenMP/ClauseProcessor.cpp

Lines changed: 81 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -31,57 +31,33 @@ static void checkMapType(mlir::Location location, mlir::Type type) {
3131
}
3232

3333
static mlir::omp::ScheduleModifier
34-
translateScheduleModifier(const omp::clause::Schedule::ModType &m) {
34+
translateScheduleModifier(const omp::clause::Schedule::OrderingModifier &m) {
3535
switch (m) {
36-
case omp::clause::Schedule::ModType::Monotonic:
36+
case omp::clause::Schedule::OrderingModifier::Monotonic:
3737
return mlir::omp::ScheduleModifier::monotonic;
38-
case omp::clause::Schedule::ModType::Nonmonotonic:
38+
case omp::clause::Schedule::OrderingModifier::Nonmonotonic:
3939
return mlir::omp::ScheduleModifier::nonmonotonic;
40-
case omp::clause::Schedule::ModType::Simd:
41-
return mlir::omp::ScheduleModifier::simd;
4240
}
4341
return mlir::omp::ScheduleModifier::none;
4442
}
4543

4644
static mlir::omp::ScheduleModifier
4745
getScheduleModifier(const omp::clause::Schedule &clause) {
48-
using ScheduleModifier = omp::clause::Schedule::ScheduleModifier;
49-
const auto &modifier = std::get<std::optional<ScheduleModifier>>(clause.t);
50-
// The input may have the modifier any order, so we look for one that isn't
51-
// SIMD. If modifier is not set at all, fall down to the bottom and return
52-
// "none".
53-
if (modifier) {
54-
using ModType = omp::clause::Schedule::ModType;
55-
const auto &modType1 = std::get<ModType>(modifier->t);
56-
if (modType1 == ModType::Simd) {
57-
const auto &modType2 = std::get<std::optional<ModType>>(modifier->t);
58-
if (modType2 && *modType2 != ModType::Simd)
59-
return translateScheduleModifier(*modType2);
60-
return mlir::omp::ScheduleModifier::none;
61-
}
62-
63-
return translateScheduleModifier(modType1);
64-
}
46+
using Schedule = omp::clause::Schedule;
47+
const auto &modifier =
48+
std::get<std::optional<Schedule::OrderingModifier>>(clause.t);
49+
if (modifier)
50+
return translateScheduleModifier(*modifier);
6551
return mlir::omp::ScheduleModifier::none;
6652
}
6753

6854
static mlir::omp::ScheduleModifier
6955
getSimdModifier(const omp::clause::Schedule &clause) {
70-
using ScheduleModifier = omp::clause::Schedule::ScheduleModifier;
71-
const auto &modifier = std::get<std::optional<ScheduleModifier>>(clause.t);
72-
// Either of the two possible modifiers in the input can be the SIMD modifier,
73-
// so look in either one, and return simd if we find one. Not found = return
74-
// "none".
75-
if (modifier) {
76-
using ModType = omp::clause::Schedule::ModType;
77-
const auto &modType1 = std::get<ModType>(modifier->t);
78-
if (modType1 == ModType::Simd)
79-
return mlir::omp::ScheduleModifier::simd;
80-
81-
const auto &modType2 = std::get<std::optional<ModType>>(modifier->t);
82-
if (modType2 && *modType2 == ModType::Simd)
83-
return mlir::omp::ScheduleModifier::simd;
84-
}
56+
using Schedule = omp::clause::Schedule;
57+
const auto &modifier =
58+
std::get<std::optional<Schedule::ChunkModifier>>(clause.t);
59+
if (modifier && *modifier == Schedule::ChunkModifier::Simd)
60+
return mlir::omp::ScheduleModifier::simd;
8561
return mlir::omp::ScheduleModifier::none;
8662
}
8763

@@ -94,53 +70,48 @@ genAllocateClause(Fortran::lower::AbstractConverter &converter,
9470
mlir::Location currentLocation = converter.getCurrentLocation();
9571
Fortran::lower::StatementContext stmtCtx;
9672

97-
const omp::ObjectList &objectList = std::get<omp::ObjectList>(clause.t);
98-
const auto &modifier =
99-
std::get<std::optional<omp::clause::Allocate::Modifier>>(clause.t);
100-
101-
// If the allocate modifier is present, check if we only use the allocator
102-
// submodifier. ALIGN in this context is unimplemented
103-
const bool onlyAllocator =
104-
modifier &&
105-
std::holds_alternative<omp::clause::Allocate::Modifier::Allocator>(
106-
modifier->u);
73+
auto &objects = std::get<omp::ObjectList>(clause.t);
10774

108-
if (modifier && !onlyAllocator) {
75+
using Allocate = omp::clause::Allocate;
76+
// ALIGN in this context is unimplemented
77+
if (std::get<std::optional<Allocate::AlignModifier>>(clause.t))
10978
TODO(currentLocation, "OmpAllocateClause ALIGN modifier");
110-
}
11179

11280
// Check if allocate clause has allocator specified. If so, add it
11381
// to list of allocators, otherwise, add default allocator to
11482
// list of allocators.
115-
if (onlyAllocator) {
116-
const auto &value =
117-
std::get<omp::clause::Allocate::Modifier::Allocator>(modifier->u);
118-
mlir::Value operand =
119-
fir::getBase(converter.genExprValue(value.v, stmtCtx));
120-
allocatorOperands.append(objectList.size(), operand);
83+
using SimpleModifier = Allocate::AllocatorSimpleModifier;
84+
using ComplexModifier = Allocate::AllocatorComplexModifier;
85+
if (auto &mod = std::get<std::optional<SimpleModifier>>(clause.t)) {
86+
mlir::Value operand = fir::getBase(converter.genExprValue(*mod, stmtCtx));
87+
allocatorOperands.append(objects.size(), operand);
88+
} else if (auto &mod = std::get<std::optional<ComplexModifier>>(clause.t)) {
89+
mlir::Value operand = fir::getBase(converter.genExprValue(mod->v, stmtCtx));
90+
allocatorOperands.append(objects.size(), operand);
12191
} else {
12292
mlir::Value operand = firOpBuilder.createIntegerConstant(
12393
currentLocation, firOpBuilder.getI32Type(), 1);
124-
allocatorOperands.append(objectList.size(), operand);
94+
allocatorOperands.append(objects.size(), operand);
12595
}
126-
genObjectList(objectList, converter, allocateOperands);
96+
97+
genObjectList(objects, converter, allocateOperands);
12798
}
12899

129100
static mlir::omp::ClauseProcBindKindAttr
130101
genProcBindKindAttr(fir::FirOpBuilder &firOpBuilder,
131102
const omp::clause::ProcBind &clause) {
132103
mlir::omp::ClauseProcBindKind procBindKind;
133104
switch (clause.v) {
134-
case omp::clause::ProcBind::Type::Master:
105+
case omp::clause::ProcBind::AffinityPolicy::Master:
135106
procBindKind = mlir::omp::ClauseProcBindKind::Master;
136107
break;
137-
case omp::clause::ProcBind::Type::Close:
108+
case omp::clause::ProcBind::AffinityPolicy::Close:
138109
procBindKind = mlir::omp::ClauseProcBindKind::Close;
139110
break;
140-
case omp::clause::ProcBind::Type::Spread:
111+
case omp::clause::ProcBind::AffinityPolicy::Spread:
141112
procBindKind = mlir::omp::ClauseProcBindKind::Spread;
142113
break;
143-
case omp::clause::ProcBind::Type::Primary:
114+
case omp::clause::ProcBind::AffinityPolicy::Primary:
144115
procBindKind = mlir::omp::ClauseProcBindKind::Primary;
145116
break;
146117
}
@@ -150,21 +121,22 @@ genProcBindKindAttr(fir::FirOpBuilder &firOpBuilder,
150121

151122
static mlir::omp::ClauseTaskDependAttr
152123
genDependKindAttr(fir::FirOpBuilder &firOpBuilder,
153-
const omp::clause::Depend &clause) {
124+
const omp::clause::Depend::TaskDependenceType kind) {
154125
mlir::omp::ClauseTaskDepend pbKind;
155-
const auto &inOut = std::get<omp::clause::Depend::InOut>(clause.u);
156-
switch (std::get<omp::clause::Depend::Type>(inOut.t)) {
157-
case omp::clause::Depend::Type::In:
126+
switch (kind) {
127+
case omp::clause::Depend::TaskDependenceType::In:
158128
pbKind = mlir::omp::ClauseTaskDepend::taskdependin;
159129
break;
160-
case omp::clause::Depend::Type::Out:
130+
case omp::clause::Depend::TaskDependenceType::Out:
161131
pbKind = mlir::omp::ClauseTaskDepend::taskdependout;
162132
break;
163-
case omp::clause::Depend::Type::Inout:
133+
case omp::clause::Depend::TaskDependenceType::Inout:
164134
pbKind = mlir::omp::ClauseTaskDepend::taskdependinout;
165135
break;
166-
default:
167-
llvm_unreachable("unknown parser task dependence type");
136+
case omp::clause::Depend::TaskDependenceType::Mutexinoutset:
137+
case omp::clause::Depend::TaskDependenceType::Inoutset:
138+
case omp::clause::Depend::TaskDependenceType::Depobj:
139+
llvm_unreachable("unhandled parser task dependence type");
168140
break;
169141
}
170142
return mlir::omp::ClauseTaskDependAttr::get(firOpBuilder.getContext(),
@@ -295,16 +267,16 @@ bool ClauseProcessor::processDefault() const {
295267
if (auto *clause = findUniqueClause<omp::clause::Default>()) {
296268
// Private, Firstprivate, Shared, None
297269
switch (clause->v) {
298-
case omp::clause::Default::Type::Shared:
299-
case omp::clause::Default::Type::None:
270+
case omp::clause::Default::DataSharingAttribute::Shared:
271+
case omp::clause::Default::DataSharingAttribute::None:
300272
// Default clause with shared or none do not require any handling since
301273
// Shared is the default behavior in the IR and None is only required
302274
// for semantic checks.
303275
break;
304-
case omp::clause::Default::Type::Private:
276+
case omp::clause::Default::DataSharingAttribute::Private:
305277
// TODO Support default(private)
306278
break;
307-
case omp::clause::Default::Type::Firstprivate:
279+
case omp::clause::Default::DataSharingAttribute::Firstprivate:
308280
// TODO Support default(firstprivate)
309281
break;
310282
}
@@ -337,13 +309,13 @@ bool ClauseProcessor::processDeviceType(
337309
if (auto *clause = findUniqueClause<omp::clause::DeviceType>()) {
338310
// Case: declare target ... device_type(any | host | nohost)
339311
switch (clause->v) {
340-
case omp::clause::DeviceType::Type::Nohost:
312+
case omp::clause::DeviceType::DeviceTypeDescription::Nohost:
341313
result = mlir::omp::DeclareTargetDeviceType::nohost;
342314
break;
343-
case omp::clause::DeviceType::Type::Host:
315+
case omp::clause::DeviceType::DeviceTypeDescription::Host:
344316
result = mlir::omp::DeclareTargetDeviceType::host;
345317
break;
346-
case omp::clause::DeviceType::Type::Any:
318+
case omp::clause::DeviceType::DeviceTypeDescription::Any:
347319
result = mlir::omp::DeclareTargetDeviceType::any;
348320
break;
349321
}
@@ -391,7 +363,9 @@ bool ClauseProcessor::processNumTeams(Fortran::lower::StatementContext &stmtCtx,
391363
// TODO Get lower and upper bounds for num_teams when parser is updated to
392364
// accept both.
393365
if (auto *clause = findUniqueClause<omp::clause::NumTeams>()) {
394-
result = fir::getBase(converter.genExprValue(clause->v, stmtCtx));
366+
// auto lowerBound = std::get<std::optional<ExprTy>>(clause->t);
367+
auto &upperBound = std::get<ExprTy>(clause->t);
368+
result = fir::getBase(converter.genExprValue(upperBound, stmtCtx));
395369
return true;
396370
}
397371
return false;
@@ -456,24 +430,23 @@ bool ClauseProcessor::processSchedule(
456430
if (auto *clause = findUniqueClause<omp::clause::Schedule>()) {
457431
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
458432
mlir::MLIRContext *context = firOpBuilder.getContext();
459-
const auto &scheduleType =
460-
std::get<omp::clause::Schedule::ScheduleType>(clause->t);
433+
const auto &scheduleType = std::get<omp::clause::Schedule::Kind>(clause->t);
461434

462435
mlir::omp::ClauseScheduleKind scheduleKind;
463436
switch (scheduleType) {
464-
case omp::clause::Schedule::ScheduleType::Static:
437+
case omp::clause::Schedule::Kind::Static:
465438
scheduleKind = mlir::omp::ClauseScheduleKind::Static;
466439
break;
467-
case omp::clause::Schedule::ScheduleType::Dynamic:
440+
case omp::clause::Schedule::Kind::Dynamic:
468441
scheduleKind = mlir::omp::ClauseScheduleKind::Dynamic;
469442
break;
470-
case omp::clause::Schedule::ScheduleType::Guided:
443+
case omp::clause::Schedule::Kind::Guided:
471444
scheduleKind = mlir::omp::ClauseScheduleKind::Guided;
472445
break;
473-
case omp::clause::Schedule::ScheduleType::Auto:
446+
case omp::clause::Schedule::Kind::Auto:
474447
scheduleKind = mlir::omp::ClauseScheduleKind::Auto;
475448
break;
476-
case omp::clause::Schedule::ScheduleType::Runtime:
449+
case omp::clause::Schedule::Kind::Runtime:
477450
scheduleKind = mlir::omp::ClauseScheduleKind::Runtime;
478451
break;
479452
}
@@ -749,13 +722,15 @@ bool ClauseProcessor::processDepend(
749722
return findRepeatableClause<omp::clause::Depend>(
750723
[&](const omp::clause::Depend &clause,
751724
const Fortran::parser::CharBlock &) {
752-
assert(std::holds_alternative<omp::clause::Depend::InOut>(clause.u) &&
753-
"Only InOut is handled at the moment");
754-
const auto &inOut = std::get<omp::clause::Depend::InOut>(clause.u);
755-
const auto &objects = std::get<omp::ObjectList>(inOut.t);
725+
using Depend = omp::clause::Depend;
726+
assert(std::holds_alternative<Depend::WithLocators>(clause.u) &&
727+
"Only the modern form is handled at the moment");
728+
auto &modern = std::get<Depend::WithLocators>(clause.u);
729+
auto kind = std::get<Depend::TaskDependenceType>(modern.t);
730+
auto &objects = std::get<omp::ObjectList>(modern.t);
756731

757732
mlir::omp::ClauseTaskDependAttr dependTypeOperand =
758-
genDependKindAttr(firOpBuilder, clause);
733+
genDependKindAttr(firOpBuilder, kind);
759734
dependTypeOperands.append(objects.size(), dependTypeOperand);
760735

761736
for (const omp::Object &object : objects) {
@@ -844,39 +819,42 @@ bool ClauseProcessor::processMap(
844819
const Fortran::parser::CharBlock &source) {
845820
using Map = omp::clause::Map;
846821
mlir::Location clauseLocation = converter.genLocation(source);
847-
const auto &oMapType = std::get<std::optional<Map::MapType>>(clause.t);
822+
const auto &mapType = std::get<std::optional<Map::MapType>>(clause.t);
848823
llvm::omp::OpenMPOffloadMappingFlags mapTypeBits =
849824
llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE;
850825
// If the map type is specified, then process it else Tofrom is the
851826
// default.
852-
if (oMapType) {
853-
const Map::MapType::Type &mapType =
854-
std::get<Map::MapType::Type>(oMapType->t);
855-
switch (mapType) {
856-
case Map::MapType::Type::To:
827+
if (mapType) {
828+
switch (*mapType) {
829+
case Map::MapType::To:
857830
mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO;
858831
break;
859-
case Map::MapType::Type::From:
832+
case Map::MapType::From:
860833
mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
861834
break;
862-
case Map::MapType::Type::Tofrom:
835+
case Map::MapType::Tofrom:
863836
mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO |
864837
llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
865838
break;
866-
case Map::MapType::Type::Alloc:
867-
case Map::MapType::Type::Release:
839+
case Map::MapType::Alloc:
840+
case Map::MapType::Release:
868841
// alloc and release is the default map_type for the Target Data
869842
// Ops, i.e. if no bits for map_type is supplied then alloc/release
870843
// is implicitly assumed based on the target directive. Default
871844
// value for Target Data and Enter Data is alloc and for Exit Data
872845
// it is release.
873846
break;
874-
case Map::MapType::Type::Delete:
847+
case Map::MapType::Delete:
875848
mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_DELETE;
876849
}
877850

878-
if (std::get<std::optional<Map::MapType::Always>>(oMapType->t))
879-
mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS;
851+
auto &modTypeMods =
852+
std::get<std::optional<Map::MapTypeModifiers>>(clause.t);
853+
if (modTypeMods) {
854+
if (llvm::is_contained(*modTypeMods, Map::MapTypeModifier::Always))
855+
mapTypeBits |=
856+
llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS;
857+
}
880858
} else {
881859
mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO |
882860
llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
@@ -972,7 +950,7 @@ bool ClauseProcessor::processTo(
972950
return findRepeatableClause<omp::clause::To>(
973951
[&](const omp::clause::To &clause, const Fortran::parser::CharBlock &) {
974952
// Case: declare target to(func, var1, var2)...
975-
gatherFuncAndVarSyms(clause.v,
953+
gatherFuncAndVarSyms(std::get<ObjectList>(clause.t),
976954
mlir::omp::DeclareTargetCaptureClause::to, result);
977955
});
978956
}

flang/lib/Lower/OpenMP/ClauseProcessor.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,8 @@ bool ClauseProcessor::processMotionClauses(
200200
? llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO
201201
: llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
202202

203-
for (const omp::Object &object : clause.v) {
203+
auto &objects = std::get<ObjectList>(clause.t);
204+
for (const omp::Object &object : objects) {
204205
llvm::SmallVector<mlir::Value> bounds;
205206
std::stringstream asFortran;
206207
Fortran::lower::AddrAndBoundsInfo info =

0 commit comments

Comments
 (0)