Skip to content

Commit 2ab3e29

Browse files
committed
[flang][OpenMP] Normalize clause modifiers that exist on their own
This is the first part of the effort to make parsing of clause modifiers more uniform and robust. Currently, when multiple modifiers are allowed, the parser will expect them to appear in a hard-coded order. Additionally, modifier properties (such as "ultimate") are checked separately for each case. The overall plan is 1. Extract all modifiers into their own top-level classes, and then equip them with sets of common properties that will allow performing the property checks generically, without refering to the specific kind of the modifier. 2. Define a parser (as a separate class) for each modifier. 3. For each clause define a union (std::variant) of all allowable modifiers, and parse the modifiers as a list of these unions. The intent is also to isolate parts of the code that could eventually be auto-generated. OpenMP modifier overhaul: #1/3
1 parent a52cb0a commit 2ab3e29

16 files changed

+188
-159
lines changed

flang/include/flang/Parser/dump-parse-tree.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,7 @@ class ParseTreeDumper {
477477
NODE(parser, ObjectDecl)
478478
NODE(parser, OldParameterStmt)
479479
NODE(parser, OmpIteratorSpecifier)
480-
NODE(parser, OmpIteratorModifier)
480+
NODE(parser, OmpIterator)
481481
NODE(parser, OmpAffinityClause)
482482
NODE(parser, OmpAlignedClause)
483483
NODE(parser, OmpAtomic)
@@ -513,9 +513,9 @@ class ParseTreeDumper {
513513
NODE_ENUM(OmpDefaultmapClause, ImplicitBehavior)
514514
NODE_ENUM(OmpDefaultmapClause, VariableCategory)
515515
NODE(parser, OmpDependenceType)
516-
NODE_ENUM(OmpDependenceType, Type)
516+
NODE_ENUM(OmpDependenceType, Value)
517517
NODE(parser, OmpTaskDependenceType)
518-
NODE_ENUM(OmpTaskDependenceType, Type)
518+
NODE_ENUM(OmpTaskDependenceType, Value)
519519
NODE(parser, OmpIterationOffset)
520520
NODE(parser, OmpIteration)
521521
NODE(parser, OmpIterationVector)
@@ -543,7 +543,7 @@ class ParseTreeDumper {
543543
NODE(OmpLinearClause, WithModifier)
544544
NODE(OmpLinearClause, WithoutModifier)
545545
NODE(parser, OmpLinearModifier)
546-
NODE_ENUM(OmpLinearModifier, Type)
546+
NODE_ENUM(OmpLinearModifier, Value)
547547
NODE(parser, OmpLoopDirective)
548548
NODE(parser, OmpMapClause)
549549
NODE_ENUM(OmpMapClause, TypeModifier)
@@ -573,7 +573,7 @@ class ParseTreeDumper {
573573
NODE(parser, OmpReductionCombiner)
574574
NODE(OmpReductionCombiner, FunctionCombiner)
575575
NODE(parser, OmpReductionInitializerClause)
576-
NODE(parser, OmpReductionOperator)
576+
NODE(parser, OmpReductionIdentifier)
577577
NODE(parser, OmpAllocateClause)
578578
NODE(OmpAllocateClause, AllocateModifier)
579579
NODE(OmpAllocateClause::AllocateModifier, Allocator)

flang/include/flang/Parser/parse-tree.h

Lines changed: 70 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -3440,13 +3440,33 @@ struct OmpObject {
34403440

34413441
WRAPPER_CLASS(OmpObjectList, std::list<OmpObject>);
34423442

3443+
inline namespace modifier {
3444+
// For uniformity, in all keyword modifiers the name of the type defined
3445+
// by ENUM_CLASS is "Value", e.g.
3446+
// struct Foo {
3447+
// ENUM_CLASS(Value, Keyword1, Keyword2);
3448+
// };
3449+
3450+
// Ref: [5.0:47-49], [5.1:49-51], [5.2:67-69]
3451+
//
3452+
// iterator-specifier ->
3453+
// [iterator-type] iterator-identifier
3454+
// = range-specification | // since 5.0
3455+
// [iterator-type ::] iterator-identifier
3456+
// = range-specification // since 5.2
3457+
struct OmpIteratorSpecifier {
3458+
TUPLE_CLASS_BOILERPLATE(OmpIteratorSpecifier);
3459+
CharBlock source;
3460+
std::tuple<TypeDeclarationStmt, SubscriptTriplet> t;
3461+
};
3462+
34433463
// Ref: [4.5:169-170], [5.0:255-256], [5.1:288-289]
34443464
//
34453465
// dependence-type ->
3446-
// SINK | SOURCE | // since 4.5
3447-
// IN | OUT | INOUT | // since 4.5, until 5.1
3448-
// MUTEXINOUTSET | DEPOBJ | // since 5.0, until 5.1
3449-
// INOUTSET // since 5.1, until 5.1
3466+
// SINK | SOURCE | // since 4.5
3467+
// IN | OUT | INOUT | // since 4.5, until 5.1
3468+
// MUTEXINOUTSET | DEPOBJ | // since 5.0, until 5.1
3469+
// INOUTSET // since 5.1, until 5.1
34503470
//
34513471
// All of these, except SINK and SOURCE became task-dependence-type in 5.2.
34523472
//
@@ -3457,45 +3477,59 @@ WRAPPER_CLASS(OmpObjectList, std::list<OmpObject>);
34573477
// vector). This would accept the vector "i, j, k" (although interpreted
34583478
// incorrectly), while flagging a syntax error for "i+1, j, k".
34593479
struct OmpDependenceType {
3460-
ENUM_CLASS(Type, Sink, Source);
3461-
WRAPPER_CLASS_BOILERPLATE(OmpDependenceType, Type);
3480+
ENUM_CLASS(Value, Sink, Source);
3481+
WRAPPER_CLASS_BOILERPLATE(OmpDependenceType, Value);
34623482
};
34633483

3464-
// Ref: [4.5:169-170], [5.0:254-256], [5.1:287-289], [5.2:321]
3484+
// Ref: [5.0:47-49], [5.1:49-51], [5.2:67-69]
34653485
//
3466-
// task-dependence-type -> // "dependence-type" in 5.1 and before
3467-
// IN | OUT | INOUT | // since 4.5
3468-
// MUTEXINOUTSET | DEPOBJ | // since 5.0
3469-
// INOUTSET // since 5.2
3470-
struct OmpTaskDependenceType {
3471-
ENUM_CLASS(Type, In, Out, Inout, Inoutset, Mutexinoutset, Depobj)
3472-
WRAPPER_CLASS_BOILERPLATE(OmpTaskDependenceType, Type);
3486+
// iterator-modifier ->
3487+
// ITERATOR(iterator-specifier [, ...]) // since 5.0
3488+
struct OmpIterator {
3489+
WRAPPER_CLASS_BOILERPLATE(OmpIterator, std::list<OmpIteratorSpecifier>);
34733490
};
34743491

3475-
// [5.0] 2.1.6 iterator-specifier -> type-declaration-stmt = subscript-triple
3476-
// iterator-modifier -> iterator-specifier-list
3477-
struct OmpIteratorSpecifier {
3478-
TUPLE_CLASS_BOILERPLATE(OmpIteratorSpecifier);
3479-
CharBlock source;
3480-
std::tuple<TypeDeclarationStmt, SubscriptTriplet> t;
3492+
// Ref: [4.5:207-210], [5.0:290-293], [5.1:323-325], [5.2:117-120]
3493+
//
3494+
// linear-modifier ->
3495+
// REF | UVAL | VAL // since 4.5
3496+
struct OmpLinearModifier {
3497+
ENUM_CLASS(Value, Ref, Uval, Val);
3498+
WRAPPER_CLASS_BOILERPLATE(OmpLinearModifier, Value);
34813499
};
34823500

3483-
WRAPPER_CLASS(OmpIteratorModifier, std::list<OmpIteratorSpecifier>);
3484-
3485-
// 2.15.3.6 reduction-identifier -> + | - | * | .AND. | .OR. | .EQV. | .NEQV. |
3486-
// MAX | MIN | IAND | IOR | IEOR
3487-
struct OmpReductionOperator {
3488-
UNION_CLASS_BOILERPLATE(OmpReductionOperator);
3501+
// Ref: [4.5:201-207], [5.0:293-299], [5.1:325-331], [5.2:124]
3502+
//
3503+
// reduction-identifier ->
3504+
// base-language-identifier | // since 4.5
3505+
// - | // since 4.5, until 5.2
3506+
// + | * | .AND. | .OR. | .EQV. | .NEQV. | // since 4.5
3507+
// MIN | MAX | IAND | IOR | IEOR // since 4.5
3508+
//
3509+
struct OmpReductionIdentifier {
3510+
UNION_CLASS_BOILERPLATE(OmpReductionIdentifier);
34893511
std::variant<DefinedOperator, ProcedureDesignator> u;
34903512
};
34913513

3514+
// Ref: [4.5:169-170], [5.0:254-256], [5.1:287-289], [5.2:321]
3515+
//
3516+
// task-dependence-type -> // "dependence-type" in 5.1 and before
3517+
// IN | OUT | INOUT | // since 4.5
3518+
// MUTEXINOUTSET | DEPOBJ | // since 5.0
3519+
// INOUTSET // since 5.2
3520+
struct OmpTaskDependenceType {
3521+
ENUM_CLASS(Value, In, Out, Inout, Inoutset, Mutexinoutset, Depobj)
3522+
WRAPPER_CLASS_BOILERPLATE(OmpTaskDependenceType, Value);
3523+
};
3524+
} // namespace modifier
3525+
34923526
// --- Clauses
34933527

34943528
// OMP 5.0 2.10.1 affinity([aff-modifier:] locator-list)
34953529
// aff-modifier: interator-modifier
34963530
struct OmpAffinityClause {
34973531
TUPLE_CLASS_BOILERPLATE(OmpAffinityClause);
3498-
std::tuple<std::optional<OmpIteratorModifier>, OmpObjectList> t;
3532+
std::tuple<std::optional<OmpIterator>, OmpObjectList> t;
34993533
};
35003534

35013535
// 2.8.1 aligned-clause -> ALIGNED (variable-name-list[ : scalar-constant])
@@ -3566,7 +3600,7 @@ WRAPPER_CLASS(OmpIterationVector, std::list<OmpIteration>);
35663600
// OmpDoacrossClause), so that the context in TYPE_CONTEXT_PARSER can be set
35673601
// separately for OmpDependClause and OmpDoacrossClause.
35683602
struct OmpDoacross {
3569-
OmpDependenceType::Type GetDepType() const;
3603+
OmpDependenceType::Value GetDepType() const;
35703604

35713605
WRAPPER_CLASS(Sink, OmpIterationVector);
35723606
EMPTY_CLASS(Source);
@@ -3586,10 +3620,9 @@ struct OmpDoacross {
35863620
struct OmpDependClause {
35873621
UNION_CLASS_BOILERPLATE(OmpDependClause);
35883622
struct TaskDep {
3589-
OmpTaskDependenceType::Type GetTaskDepType() const;
3623+
OmpTaskDependenceType::Value GetTaskDepType() const;
35903624
TUPLE_CLASS_BOILERPLATE(TaskDep);
3591-
std::tuple<std::optional<OmpIteratorModifier>, OmpTaskDependenceType,
3592-
OmpObjectList>
3625+
std::tuple<std::optional<OmpIterator>, OmpTaskDependenceType, OmpObjectList>
35933626
t;
35943627
};
35953628
std::variant<TaskDep, OmpDoacross> u;
@@ -3632,7 +3665,7 @@ struct OmpFromClause {
36323665
// As in the case of MAP, modifiers are parsed as lists, even if they
36333666
// are unique. These restrictions will be checked in semantic checks.
36343667
std::tuple<std::optional<std::list<Expectation>>,
3635-
std::optional<std::list<OmpIteratorModifier>>, OmpObjectList,
3668+
std::optional<std::list<OmpIterator>>, OmpObjectList,
36363669
bool> // were the modifiers comma-separated?
36373670
t;
36383671
};
@@ -3661,7 +3694,7 @@ struct OmpDetachClause {
36613694
// variable-name-list)
36623695
struct OmpInReductionClause {
36633696
TUPLE_CLASS_BOILERPLATE(OmpInReductionClause);
3664-
std::tuple<OmpReductionOperator, OmpObjectList> t;
3697+
std::tuple<OmpReductionIdentifier, OmpObjectList> t;
36653698
};
36663699

36673700
// OMP 5.0 2.19.4.5 lastprivate-clause ->
@@ -3673,12 +3706,6 @@ struct OmpLastprivateClause {
36733706
std::tuple<std::optional<LastprivateModifier>, OmpObjectList> t;
36743707
};
36753708

3676-
// 2.15.3.7 linear-modifier -> REF | VAL | UVAL
3677-
struct OmpLinearModifier {
3678-
ENUM_CLASS(Type, Ref, Val, Uval)
3679-
WRAPPER_CLASS_BOILERPLATE(OmpLinearModifier, Type);
3680-
};
3681-
36823709
// 2.15.3.7 linear-clause -> LINEAR (linear-list[ : linear-step])
36833710
// linear-list -> list | linear-modifier(list)
36843711
struct OmpLinearClause {
@@ -3719,7 +3746,7 @@ struct OmpMapClause {
37193746
// In OpenMP 5.2 the non-comma syntax has been deprecated: keep the
37203747
// information about separator presence to emit a diagnostic if needed.
37213748
std::tuple<std::optional<std::list<TypeModifier>>,
3722-
std::optional<std::list<OmpIteratorModifier>>, // unique
3749+
std::optional<std::list<OmpIterator>>, // unique
37233750
std::optional<std::list<Type>>, // unique
37243751
OmpObjectList,
37253752
bool> // were the modifiers comma-separated?
@@ -3749,7 +3776,7 @@ struct OmpProcBindClause {
37493776
struct OmpReductionClause {
37503777
TUPLE_CLASS_BOILERPLATE(OmpReductionClause);
37513778
ENUM_CLASS(ReductionModifier, Inscan, Task, Default)
3752-
std::tuple<std::optional<ReductionModifier>, OmpReductionOperator,
3779+
std::tuple<std::optional<ReductionModifier>, OmpReductionIdentifier,
37533780
OmpObjectList>
37543781
t;
37553782
};
@@ -3794,7 +3821,7 @@ struct OmpToClause {
37943821
// As in the case of MAP, modifiers are parsed as lists, even if they
37953822
// are unique. These restrictions will be checked in semantic checks.
37963823
std::tuple<std::optional<std::list<Expectation>>,
3797-
std::optional<std::list<OmpIteratorModifier>>, OmpObjectList,
3824+
std::optional<std::list<OmpIterator>>, OmpObjectList,
37983825
bool> // were the modifiers comma-separated?
37993826
t;
38003827
};
@@ -3942,7 +3969,7 @@ WRAPPER_CLASS(OmpReductionInitializerClause, Expr);
39423969
struct OpenMPDeclareReductionConstruct {
39433970
TUPLE_CLASS_BOILERPLATE(OpenMPDeclareReductionConstruct);
39443971
CharBlock source;
3945-
std::tuple<Verbatim, OmpReductionOperator, std::list<DeclarationTypeSpec>,
3972+
std::tuple<Verbatim, OmpReductionIdentifier, std::list<DeclarationTypeSpec>,
39463973
OmpReductionCombiner, std::optional<OmpReductionInitializerClause>>
39473974
t;
39483975
};

flang/lib/Lower/OpenMP/Clauses.cpp

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ makeIteratorSpecifiers(const parser::OmpIteratorSpecifier &inp,
264264
return specifiers;
265265
}
266266

267-
Iterator makeIterator(const parser::OmpIteratorModifier &inp,
267+
Iterator makeIterator(const parser::OmpIterator &inp,
268268
semantics::SemanticsContext &semaCtx) {
269269
Iterator iterator;
270270
for (auto &&spec : inp.v)
@@ -324,8 +324,9 @@ makeProcedureDesignator(const parser::ProcedureDesignator &inp,
324324
inp.u)};
325325
}
326326

327-
ReductionOperator makeReductionOperator(const parser::OmpReductionOperator &inp,
328-
semantics::SemanticsContext &semaCtx) {
327+
ReductionOperator
328+
makeReductionOperator(const parser::OmpReductionIdentifier &inp,
329+
semantics::SemanticsContext &semaCtx) {
329330
return Fortran::common::visit(
330331
common::visitors{
331332
[&](const parser::DefinedOperator &s) {
@@ -340,27 +341,27 @@ ReductionOperator makeReductionOperator(const parser::OmpReductionOperator &inp,
340341

341342
clause::DependenceType makeDepType(const parser::OmpDependenceType &inp) {
342343
switch (inp.v) {
343-
case parser::OmpDependenceType::Type::Sink:
344+
case parser::OmpDependenceType::Value::Sink:
344345
return clause::DependenceType::Sink;
345-
case parser::OmpDependenceType::Type::Source:
346+
case parser::OmpDependenceType::Value::Source:
346347
return clause::DependenceType::Source;
347348
}
348349
llvm_unreachable("Unexpected dependence type");
349350
}
350351

351352
clause::DependenceType makeDepType(const parser::OmpTaskDependenceType &inp) {
352353
switch (inp.v) {
353-
case parser::OmpTaskDependenceType::Type::Depobj:
354+
case parser::OmpTaskDependenceType::Value::Depobj:
354355
return clause::DependenceType::Depobj;
355-
case parser::OmpTaskDependenceType::Type::In:
356+
case parser::OmpTaskDependenceType::Value::In:
356357
return clause::DependenceType::In;
357-
case parser::OmpTaskDependenceType::Type::Inout:
358+
case parser::OmpTaskDependenceType::Value::Inout:
358359
return clause::DependenceType::Inout;
359-
case parser::OmpTaskDependenceType::Type::Inoutset:
360+
case parser::OmpTaskDependenceType::Value::Inoutset:
360361
return clause::DependenceType::Inoutset;
361-
case parser::OmpTaskDependenceType::Type::Mutexinoutset:
362+
case parser::OmpTaskDependenceType::Value::Mutexinoutset:
362363
return clause::DependenceType::Mutexinoutset;
363-
case parser::OmpTaskDependenceType::Type::Out:
364+
case parser::OmpTaskDependenceType::Value::Out:
364365
return clause::DependenceType::Out;
365366
}
366367
llvm_unreachable("Unexpected task dependence type");
@@ -381,7 +382,7 @@ Absent make(const parser::OmpClause::Absent &inp,
381382
Affinity make(const parser::OmpClause::Affinity &inp,
382383
semantics::SemanticsContext &semaCtx) {
383384
// inp.v -> parser::OmpAffinityClause
384-
auto &t0 = std::get<std::optional<parser::OmpIteratorModifier>>(inp.v.t);
385+
auto &t0 = std::get<std::optional<parser::OmpIterator>>(inp.v.t);
385386
auto &t1 = std::get<parser::OmpObjectList>(inp.v.t);
386387

387388
auto &&maybeIter =
@@ -626,7 +627,7 @@ Depend make(const parser::OmpClause::Depend &inp,
626627
using Variant = decltype(Depend::u);
627628

628629
auto visitTaskDep = [&](const wrapped::TaskDep &s) -> Variant {
629-
auto &t0 = std::get<std::optional<parser::OmpIteratorModifier>>(s.t);
630+
auto &t0 = std::get<std::optional<parser::OmpIterator>>(s.t);
630631
auto &t1 = std::get<parser::OmpTaskDependenceType>(s.t);
631632
auto &t2 = std::get<parser::OmpObjectList>(s.t);
632633

@@ -769,8 +770,7 @@ From make(const parser::OmpClause::From &inp,
769770
);
770771

771772
auto &t0 = std::get<std::optional<std::list<wrapped::Expectation>>>(inp.v.t);
772-
auto &t1 =
773-
std::get<std::optional<std::list<parser::OmpIteratorModifier>>>(inp.v.t);
773+
auto &t1 = std::get<std::optional<std::list<parser::OmpIterator>>>(inp.v.t);
774774
auto &t2 = std::get<parser::OmpObjectList>(inp.v.t);
775775

776776
assert((!t0 || t0->size() == 1) && "Only one expectation modifier allowed");
@@ -881,7 +881,7 @@ Init make(const parser::OmpClause::Init &inp,
881881
InReduction make(const parser::OmpClause::InReduction &inp,
882882
semantics::SemanticsContext &semaCtx) {
883883
// inp.v -> parser::OmpInReductionClause
884-
auto &t0 = std::get<parser::OmpReductionOperator>(inp.v.t);
884+
auto &t0 = std::get<parser::OmpReductionIdentifier>(inp.v.t);
885885
auto &t1 = std::get<parser::OmpObjectList>(inp.v.t);
886886
return InReduction{
887887
{/*ReductionIdentifiers=*/{makeReductionOperator(t0, semaCtx)},
@@ -920,7 +920,7 @@ Linear make(const parser::OmpClause::Linear &inp,
920920
using wrapped = parser::OmpLinearClause;
921921

922922
CLAUSET_ENUM_CONVERT( //
923-
convert, parser::OmpLinearModifier::Type, Linear::LinearModifier,
923+
convert, parser::OmpLinearModifier::Value, Linear::LinearModifier,
924924
// clang-format off
925925
MS(Ref, Ref)
926926
MS(Val, Val)
@@ -984,8 +984,7 @@ Map make(const parser::OmpClause::Map &inp,
984984
);
985985

986986
auto &t0 = std::get<std::optional<std::list<wrapped::TypeModifier>>>(inp.v.t);
987-
auto &t1 =
988-
std::get<std::optional<std::list<parser::OmpIteratorModifier>>>(inp.v.t);
987+
auto &t1 = std::get<std::optional<std::list<parser::OmpIterator>>>(inp.v.t);
989988
auto &t2 = std::get<std::optional<std::list<wrapped::Type>>>(inp.v.t);
990989
auto &t3 = std::get<parser::OmpObjectList>(inp.v.t);
991990

@@ -1188,7 +1187,7 @@ Reduction make(const parser::OmpClause::Reduction &inp,
11881187
auto &t0 =
11891188
std::get<std::optional<parser::OmpReductionClause::ReductionModifier>>(
11901189
inp.v.t);
1191-
auto &t1 = std::get<parser::OmpReductionOperator>(inp.v.t);
1190+
auto &t1 = std::get<parser::OmpReductionIdentifier>(inp.v.t);
11921191
auto &t2 = std::get<parser::OmpObjectList>(inp.v.t);
11931192
return Reduction{
11941193
{/*ReductionModifier=*/t0
@@ -1315,7 +1314,7 @@ Permutation make(const parser::OmpClause::Permutation &inp,
13151314
TaskReduction make(const parser::OmpClause::TaskReduction &inp,
13161315
semantics::SemanticsContext &semaCtx) {
13171316
// inp.v -> parser::OmpReductionClause
1318-
auto &t0 = std::get<parser::OmpReductionOperator>(inp.v.t);
1317+
auto &t0 = std::get<parser::OmpReductionIdentifier>(inp.v.t);
13191318
auto &t1 = std::get<parser::OmpObjectList>(inp.v.t);
13201319
return TaskReduction{
13211320
{/*ReductionIdentifiers=*/{makeReductionOperator(t0, semaCtx)},
@@ -1344,8 +1343,7 @@ To make(const parser::OmpClause::To &inp,
13441343
);
13451344

13461345
auto &t0 = std::get<std::optional<std::list<wrapped::Expectation>>>(inp.v.t);
1347-
auto &t1 =
1348-
std::get<std::optional<std::list<parser::OmpIteratorModifier>>>(inp.v.t);
1346+
auto &t1 = std::get<std::optional<std::list<parser::OmpIterator>>>(inp.v.t);
13491347
auto &t2 = std::get<parser::OmpObjectList>(inp.v.t);
13501348

13511349
assert((!t0 || t0->size() == 1) && "Only one expectation modifier allowed");

0 commit comments

Comments
 (0)