Skip to content

Commit 919a6d7

Browse files
committed
[flang][OpenMP] Rework LINEAR clause
The OmpLinearClause class was a variant of two classes, one for when the linear modifier was present, and one for when it was absent. These two classes did not follow the conventions for parse tree nodes, (i.e. tuple/wrapper/union formats), which necessitated specialization of the parse tree visitor. The new form of OmpLinearClause is the standard tuple with a list of modifiers and an object list. The specialization of parse tree visitor for it has been removed. Parsing and unparsing of the new form bears additional complexity due to syntactical differences between OpenMP 5.2 and prior versions: in OpenMP 5.2 the argument list is post-modified, while in the prior versions, the step modifier was a post-modifier while the linear modifier had an unusual syntax of `modifier(list)`. With this change the LINEAR clause is no different from any other clauses in terms of its structure and use of modifiers. Modifier validation and all other checks work the same as with other clauses.
1 parent 7d89ebf commit 919a6d7

File tree

18 files changed

+449
-233
lines changed

18 files changed

+449
-233
lines changed

flang/examples/FeatureList/FeatureList.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -495,8 +495,7 @@ struct NodeVisitor {
495495
READ_FEATURE(OmpIfClause::Modifier)
496496
READ_FEATURE(OmpDirectiveNameModifier)
497497
READ_FEATURE(OmpLinearClause)
498-
READ_FEATURE(OmpLinearClause::WithModifier)
499-
READ_FEATURE(OmpLinearClause::WithoutModifier)
498+
READ_FEATURE(OmpLinearClause::Modifier)
500499
READ_FEATURE(OmpLinearModifier)
501500
READ_FEATURE(OmpLinearModifier::Value)
502501
READ_FEATURE(OmpLoopDirective)

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -558,10 +558,11 @@ class ParseTreeDumper {
558558
NODE(parser, OmpLastprivateModifier)
559559
NODE_ENUM(OmpLastprivateModifier, Value)
560560
NODE(parser, OmpLinearClause)
561-
NODE(OmpLinearClause, WithModifier)
562-
NODE(OmpLinearClause, WithoutModifier)
561+
NODE(OmpLinearClause, Modifier)
563562
NODE(parser, OmpLinearModifier)
564563
NODE_ENUM(OmpLinearModifier, Value)
564+
NODE(parser, OmpStepComplexModifier)
565+
NODE(parser, OmpStepSimpleModifier)
565566
NODE(parser, OmpLoopDirective)
566567
NODE(parser, OmpMapClause)
567568
NODE(OmpMapClause, Modifier)

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

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -897,40 +897,6 @@ struct ParseTreeVisitorLookupScope {
897897
mutator.Post(x);
898898
}
899899
}
900-
template <typename V>
901-
static void Walk(const OmpLinearClause::WithModifier &x, V &visitor) {
902-
if (visitor.Pre(x)) {
903-
Walk(x.modifier, visitor);
904-
Walk(x.names, visitor);
905-
Walk(x.step, visitor);
906-
visitor.Post(x);
907-
}
908-
}
909-
template <typename M>
910-
static void Walk(OmpLinearClause::WithModifier &x, M &mutator) {
911-
if (mutator.Pre(x)) {
912-
Walk(x.modifier, mutator);
913-
Walk(x.names, mutator);
914-
Walk(x.step, mutator);
915-
mutator.Post(x);
916-
}
917-
}
918-
template <typename V>
919-
static void Walk(const OmpLinearClause::WithoutModifier &x, V &visitor) {
920-
if (visitor.Pre(x)) {
921-
Walk(x.names, visitor);
922-
Walk(x.step, visitor);
923-
visitor.Post(x);
924-
}
925-
}
926-
template <typename M>
927-
static void Walk(OmpLinearClause::WithoutModifier &x, M &mutator) {
928-
if (mutator.Pre(x)) {
929-
Walk(x.names, mutator);
930-
Walk(x.step, mutator);
931-
mutator.Post(x);
932-
}
933-
}
934900
};
935901
} // namespace detail
936902

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

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3698,6 +3698,22 @@ struct OmpReductionModifier {
36983698
WRAPPER_CLASS_BOILERPLATE(OmpReductionModifier, Value);
36993699
};
37003700

3701+
// Ref: [5.2:117-120]
3702+
//
3703+
// step-complex-modifier ->
3704+
// STEP(integer-expression) // since 5.2
3705+
struct OmpStepComplexModifier {
3706+
WRAPPER_CLASS_BOILERPLATE(OmpStepComplexModifier, ScalarIntExpr);
3707+
};
3708+
3709+
// Ref: [4.5:207-210], [5.0:290-293], [5.1:323-325], [5.2:117-120]
3710+
//
3711+
// step-simple-modifier ->
3712+
// integer-expresion // since 4.5
3713+
struct OmpStepSimpleModifier {
3714+
WRAPPER_CLASS_BOILERPLATE(OmpStepSimpleModifier, ScalarIntExpr);
3715+
};
3716+
37013717
// Ref: [4.5:169-170], [5.0:254-256], [5.1:287-289], [5.2:321]
37023718
//
37033719
// task-dependence-type -> // "dependence-type" in 5.1 and before
@@ -3925,7 +3941,7 @@ struct OmpDeviceTypeClause {
39253941
struct OmpFromClause {
39263942
TUPLE_CLASS_BOILERPLATE(OmpFromClause);
39273943
MODIFIER_BOILERPLATE(OmpExpectation, OmpIterator, OmpMapper);
3928-
std::tuple<MODIFIERS(), OmpObjectList, bool> t;
3944+
std::tuple<MODIFIERS(), OmpObjectList, /*CommaSeparated=*/bool> t;
39293945
};
39303946

39313947
// Ref: [4.5:87-91], [5.0:140-146], [5.1:166-171], [5.2:269]
@@ -3969,28 +3985,20 @@ struct OmpLastprivateClause {
39693985
std::tuple<MODIFIERS(), OmpObjectList> t;
39703986
};
39713987

3972-
// 2.15.3.7 linear-clause -> LINEAR (linear-list[ : linear-step])
3973-
// linear-list -> list | linear-modifier(list)
3988+
// Ref: [4.5:207-210], [5.0:290-293], [5.1:323-325], [5.2:117-120]
3989+
//
3990+
// linear-clause ->
3991+
// LINEAR(list [: step-simple-modifier]) | // since 4.5
3992+
// LINEAR(linear-modifier(list)
3993+
// [: step-simple-modifier]) | // since 4.5, until 5.2[*]
3994+
// LINEAR(list [: linear-modifier,
3995+
// step-complex-modifier]) // since 5.2
3996+
// [*] Still allowed in 5.2 when on DECLARE SIMD, but deprecated.
39743997
struct OmpLinearClause {
3975-
UNION_CLASS_BOILERPLATE(OmpLinearClause);
3976-
struct WithModifier {
3977-
BOILERPLATE(WithModifier);
3978-
WithModifier(OmpLinearModifier &&m, std::list<Name> &&n,
3979-
std::optional<ScalarIntConstantExpr> &&s)
3980-
: modifier(std::move(m)), names(std::move(n)), step(std::move(s)) {}
3981-
OmpLinearModifier modifier;
3982-
std::list<Name> names;
3983-
std::optional<ScalarIntConstantExpr> step;
3984-
};
3985-
struct WithoutModifier {
3986-
BOILERPLATE(WithoutModifier);
3987-
WithoutModifier(
3988-
std::list<Name> &&n, std::optional<ScalarIntConstantExpr> &&s)
3989-
: names(std::move(n)), step(std::move(s)) {}
3990-
std::list<Name> names;
3991-
std::optional<ScalarIntConstantExpr> step;
3992-
};
3993-
std::variant<WithModifier, WithoutModifier> u;
3998+
TUPLE_CLASS_BOILERPLATE(OmpLinearClause);
3999+
MODIFIER_BOILERPLATE(
4000+
OmpLinearModifier, OmpStepSimpleModifier, OmpStepComplexModifier);
4001+
std::tuple<OmpObjectList, MODIFIERS(), /*PostModified=*/bool> t;
39944002
};
39954003

39964004
// Ref: [4.5:216-219], [5.0:315-324], [5.1:347-355], [5.2:150-158]
@@ -4005,7 +4013,7 @@ struct OmpLinearClause {
40054013
struct OmpMapClause {
40064014
TUPLE_CLASS_BOILERPLATE(OmpMapClause);
40074015
MODIFIER_BOILERPLATE(OmpMapTypeModifier, OmpMapper, OmpIterator, OmpMapType);
4008-
std::tuple<MODIFIERS(), OmpObjectList, bool> t;
4016+
std::tuple<MODIFIERS(), OmpObjectList, /*CommaSeparated=*/bool> t;
40094017
};
40104018

40114019
// Ref: [4.5:87-91], [5.0:140-146], [5.1:166-171], [5.2:270]
@@ -4083,7 +4091,7 @@ struct OmpScheduleClause {
40834091
struct OmpToClause {
40844092
TUPLE_CLASS_BOILERPLATE(OmpToClause);
40854093
MODIFIER_BOILERPLATE(OmpExpectation, OmpIterator, OmpMapper);
4086-
std::tuple<MODIFIERS(), OmpObjectList, bool> t;
4094+
std::tuple<MODIFIERS(), OmpObjectList, /*CommaSeparated=*/bool> t;
40874095
};
40884096

40894097
// Ref: [5.0:254-255], [5.1:287-288], [5.2:321-322]

flang/include/flang/Semantics/openmp-modifiers.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ DECLARE_DESCRIPTOR(parser::OmpOrderingModifier);
8787
DECLARE_DESCRIPTOR(parser::OmpPrescriptiveness);
8888
DECLARE_DESCRIPTOR(parser::OmpReductionIdentifier);
8989
DECLARE_DESCRIPTOR(parser::OmpReductionModifier);
90+
DECLARE_DESCRIPTOR(parser::OmpStepComplexModifier);
91+
DECLARE_DESCRIPTOR(parser::OmpStepSimpleModifier);
9092
DECLARE_DESCRIPTOR(parser::OmpTaskDependenceType);
9193
DECLARE_DESCRIPTOR(parser::OmpVariableCategory);
9294

flang/lib/Lower/OpenMP/Clauses.cpp

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -895,8 +895,6 @@ Lastprivate make(const parser::OmpClause::Lastprivate &inp,
895895
Linear make(const parser::OmpClause::Linear &inp,
896896
semantics::SemanticsContext &semaCtx) {
897897
// inp.v -> parser::OmpLinearClause
898-
using wrapped = parser::OmpLinearClause;
899-
900898
CLAUSET_ENUM_CONVERT( //
901899
convert, parser::OmpLinearModifier::Value, Linear::LinearModifier,
902900
// clang-format off
@@ -906,26 +904,23 @@ Linear make(const parser::OmpClause::Linear &inp,
906904
// clang-format on
907905
);
908906

909-
using Tuple = decltype(Linear::t);
907+
auto &mods = semantics::OmpGetModifiers(inp.v);
908+
auto *m0 =
909+
semantics::OmpGetUniqueModifier<parser::OmpStepComplexModifier>(mods);
910+
auto *m1 =
911+
semantics::OmpGetUniqueModifier<parser::OmpStepSimpleModifier>(mods);
912+
assert((!m0 || !m1) && "Simple and complex modifiers both present");
910913

911-
return Linear{Fortran::common::visit(
912-
common::visitors{
913-
[&](const wrapped::WithModifier &s) -> Tuple {
914-
return {
915-
/*StepSimpleModifier=*/std::nullopt,
916-
/*StepComplexModifier=*/maybeApply(makeExprFn(semaCtx), s.step),
917-
/*LinearModifier=*/convert(s.modifier.v),
918-
/*List=*/makeList(s.names, makeObjectFn(semaCtx))};
919-
},
920-
[&](const wrapped::WithoutModifier &s) -> Tuple {
921-
return {
922-
/*StepSimpleModifier=*/maybeApply(makeExprFn(semaCtx), s.step),
923-
/*StepComplexModifier=*/std::nullopt,
924-
/*LinearModifier=*/std::nullopt,
925-
/*List=*/makeList(s.names, makeObjectFn(semaCtx))};
926-
},
927-
},
928-
inp.v.u)};
914+
auto *m2 = semantics::OmpGetUniqueModifier<parser::OmpLinearModifier>(mods);
915+
auto &t1 = std::get<parser::OmpObjectList>(inp.v.t);
916+
917+
auto &&maybeStep = m0 ? maybeApplyToV(makeExprFn(semaCtx), m0)
918+
: m1 ? maybeApplyToV(makeExprFn(semaCtx), m1)
919+
: std::optional<Linear::StepComplexModifier>{};
920+
921+
return Linear{{/*StepComplexModifier=*/std::move(maybeStep),
922+
/*LinearModifier=*/maybeApplyToV(convert, m2),
923+
/*List=*/makeObjects(t1, semaCtx)}};
929924
}
930925

931926
Link make(const parser::OmpClause::Link &inp,

flang/lib/Parser/openmp-parsers.cpp

Lines changed: 57 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,26 @@ constexpr ModifierList<Clause, Separator> modifierList(Separator sep) {
9999
return ModifierList<Clause, Separator>(sep);
100100
}
101101

102+
// Parse the input as any modifier from ClauseTy, but only succeed if
103+
// the result was the SpecificTy. It requires that SpecificTy is one
104+
// of the alternatives in ClauseTy::Modifier.
105+
// The reason to have this is that ClauseTy::Modifier has "source",
106+
// while specific modifiers don't. This class allows to parse a specific
107+
// modifier together with obtaining its location.
108+
template <typename SpecificTy, typename ClauseTy>
109+
struct SpecificModifierParser {
110+
using resultType = typename ClauseTy::Modifier;
111+
std::optional<resultType> Parse(ParseState &state) const {
112+
Parser<resultType> p;
113+
if (auto result{attempt(Parser<resultType>{}).Parse(state)}) {
114+
if (std::holds_alternative<SpecificTy>(result->u)) {
115+
return result;
116+
}
117+
}
118+
return std::nullopt;
119+
}
120+
};
121+
102122
// OpenMP Clauses
103123

104124
// [5.0] 2.1.6 iterator-specifier -> type-declaration-stmt = subscript-triple |
@@ -232,6 +252,11 @@ TYPE_PARSER(construct<OmpReductionModifier>(
232252
"TASK" >> pure(OmpReductionModifier::Value::Task) ||
233253
"DEFAULT" >> pure(OmpReductionModifier::Value::Default)))
234254

255+
TYPE_PARSER(construct<OmpStepComplexModifier>( //
256+
"STEP" >> parenthesized(scalarIntExpr)))
257+
258+
TYPE_PARSER(construct<OmpStepSimpleModifier>(scalarIntExpr))
259+
235260
TYPE_PARSER(construct<OmpTaskDependenceType>(
236261
"DEPOBJ" >> pure(OmpTaskDependenceType::Value::Depobj) ||
237262
"IN"_id >> pure(OmpTaskDependenceType::Value::In) ||
@@ -285,6 +310,11 @@ TYPE_PARSER(sourced(construct<OmpIfClause::Modifier>(OmpDirectiveNameParser{})))
285310
TYPE_PARSER(sourced(construct<OmpLastprivateClause::Modifier>(
286311
Parser<OmpLastprivateModifier>{})))
287312

313+
TYPE_PARSER(sourced(
314+
construct<OmpLinearClause::Modifier>(Parser<OmpLinearModifier>{}) ||
315+
construct<OmpLinearClause::Modifier>(Parser<OmpStepComplexModifier>{}) ||
316+
construct<OmpLinearClause::Modifier>(Parser<OmpStepSimpleModifier>{})))
317+
288318
TYPE_PARSER(sourced(construct<OmpMapClause::Modifier>(
289319
sourced(construct<OmpMapClause::Modifier>(Parser<OmpMapTypeModifier>{}) ||
290320
construct<OmpMapClause::Modifier>(Parser<OmpMapper>{}) ||
@@ -460,13 +490,33 @@ TYPE_PARSER(construct<OmpToClause>(
460490
applyFunction<OmpToClause>(makeMobClause<false>,
461491
modifierList<OmpToClause>(maybe(","_tok)), Parser<OmpObjectList>{})))
462492

463-
TYPE_CONTEXT_PARSER("Omp LINEAR clause"_en_US,
464-
construct<OmpLinearClause>(
465-
construct<OmpLinearClause>(construct<OmpLinearClause::WithModifier>(
466-
Parser<OmpLinearModifier>{}, parenthesized(nonemptyList(name)),
467-
maybe(":" >> scalarIntConstantExpr))) ||
468-
construct<OmpLinearClause>(construct<OmpLinearClause::WithoutModifier>(
469-
nonemptyList(name), maybe(":" >> scalarIntConstantExpr)))))
493+
OmpLinearClause makeLinearFromOldSyntax(OmpLinearClause::Modifier &&lm,
494+
OmpObjectList &&objs, std::optional<OmpLinearClause::Modifier> &&ssm) {
495+
std::list<OmpLinearClause::Modifier> mods;
496+
mods.emplace_back(std::move(lm));
497+
if (ssm) {
498+
mods.emplace_back(std::move(*ssm));
499+
}
500+
return OmpLinearClause{std::move(objs),
501+
mods.empty() ? decltype(mods){} : std::move(mods),
502+
/*PostModified=*/false};
503+
}
504+
505+
TYPE_PARSER(
506+
// Parse the "modifier(x)" first, because syntacticaly it will match
507+
// an array element (i.e. a list item).
508+
// LINEAR(linear-modifier(list) [: step-simple-modifier])
509+
construct<OmpLinearClause>( //
510+
applyFunction(makeLinearFromOldSyntax,
511+
SpecificModifierParser<OmpLinearModifier, OmpLinearClause>{},
512+
parenthesized(Parser<OmpObjectList>{}),
513+
maybe(":"_tok >> SpecificModifierParser<OmpStepSimpleModifier,
514+
OmpLinearClause>{}))) ||
515+
// LINEAR(list [: modifiers])
516+
construct<OmpLinearClause>( //
517+
Parser<OmpObjectList>{},
518+
maybe(":"_tok >> nonemptyList(Parser<OmpLinearClause::Modifier>{})),
519+
/*PostModified=*/pure(true)))
470520

471521
// OpenMPv5.2 12.5.2 detach-clause -> DETACH (event-handle)
472522
TYPE_PARSER(construct<OmpDetachClause>(Parser<OmpObject>{}))

flang/lib/Parser/unparse.cpp

Lines changed: 56 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2133,13 +2133,63 @@ class UnparseVisitor {
21332133
Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ": ");
21342134
Walk(std::get<ScalarLogicalExpr>(x.t));
21352135
}
2136-
void Unparse(const OmpLinearClause::WithoutModifier &x) {
2137-
Walk(x.names, ", ");
2138-
Walk(":", x.step);
2136+
void Unparse(const OmpStepSimpleModifier &x) { Walk(x.v); }
2137+
void Unparse(const OmpStepComplexModifier &x) {
2138+
Word("STEP(");
2139+
Walk(x.v);
2140+
Put(")");
21392141
}
2140-
void Unparse(const OmpLinearClause::WithModifier &x) {
2141-
Walk(x.modifier), Put("("), Walk(x.names, ","), Put(")");
2142-
Walk(":", x.step);
2142+
void Unparse(const OmpLinearClause &x) {
2143+
using Modifier = OmpLinearClause::Modifier;
2144+
auto &modifiers{std::get<std::optional<std::list<Modifier>>>(x.t)};
2145+
if (std::get<bool>(x.t)) { // PostModified
2146+
Walk(std::get<OmpObjectList>(x.t));
2147+
Walk(": ", modifiers);
2148+
} else {
2149+
// Unparse using pre-5.2 syntax.
2150+
bool HasStepModifier{false}, HasLinearModifier{false};
2151+
2152+
if (modifiers) {
2153+
bool NeedComma{false};
2154+
for (const Modifier &m : *modifiers) {
2155+
// Print all linear modifiers in case we need to unparse an
2156+
// incorrect tree.
2157+
if (auto *lmod{std::get_if<parser::OmpLinearModifier>(&m.u)}) {
2158+
if (NeedComma) {
2159+
Put(",");
2160+
}
2161+
Walk(*lmod);
2162+
HasLinearModifier = true;
2163+
NeedComma = true;
2164+
} else {
2165+
// If not linear-modifier, then it has to be step modifier.
2166+
HasStepModifier = true;
2167+
}
2168+
}
2169+
}
2170+
2171+
if (HasLinearModifier) {
2172+
Put("(");
2173+
}
2174+
Walk(std::get<OmpObjectList>(x.t));
2175+
if (HasLinearModifier) {
2176+
Put(")");
2177+
}
2178+
2179+
if (HasStepModifier) {
2180+
Put(": ");
2181+
bool NeedComma{false};
2182+
for (const Modifier &m : *modifiers) {
2183+
if (!std::holds_alternative<parser::OmpLinearModifier>(m.u)) {
2184+
if (NeedComma) {
2185+
Put(",");
2186+
}
2187+
common::visit([&](auto &&s) { Walk(s); }, m.u);
2188+
NeedComma = true;
2189+
}
2190+
}
2191+
}
2192+
}
21432193
}
21442194
void Unparse(const OmpReductionClause &x) {
21452195
using Modifier = OmpReductionClause::Modifier;

0 commit comments

Comments
 (0)