Skip to content

[flang][OpenMP] Rework LINEAR clause #119278

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Dec 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions flang/examples/FeatureList/FeatureList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -495,8 +495,7 @@ struct NodeVisitor {
READ_FEATURE(OmpIfClause::Modifier)
READ_FEATURE(OmpDirectiveNameModifier)
READ_FEATURE(OmpLinearClause)
READ_FEATURE(OmpLinearClause::WithModifier)
READ_FEATURE(OmpLinearClause::WithoutModifier)
READ_FEATURE(OmpLinearClause::Modifier)
READ_FEATURE(OmpLinearModifier)
READ_FEATURE(OmpLinearModifier::Value)
READ_FEATURE(OmpLoopDirective)
Expand Down
5 changes: 3 additions & 2 deletions flang/include/flang/Parser/dump-parse-tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -558,10 +558,11 @@ class ParseTreeDumper {
NODE(parser, OmpLastprivateModifier)
NODE_ENUM(OmpLastprivateModifier, Value)
NODE(parser, OmpLinearClause)
NODE(OmpLinearClause, WithModifier)
NODE(OmpLinearClause, WithoutModifier)
NODE(OmpLinearClause, Modifier)
NODE(parser, OmpLinearModifier)
NODE_ENUM(OmpLinearModifier, Value)
NODE(parser, OmpStepComplexModifier)
NODE(parser, OmpStepSimpleModifier)
NODE(parser, OmpLoopDirective)
NODE(parser, OmpMapClause)
NODE(OmpMapClause, Modifier)
Expand Down
34 changes: 0 additions & 34 deletions flang/include/flang/Parser/parse-tree-visitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -897,40 +897,6 @@ struct ParseTreeVisitorLookupScope {
mutator.Post(x);
}
}
template <typename V>
static void Walk(const OmpLinearClause::WithModifier &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.modifier, visitor);
Walk(x.names, visitor);
Walk(x.step, visitor);
visitor.Post(x);
}
}
template <typename M>
static void Walk(OmpLinearClause::WithModifier &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.modifier, mutator);
Walk(x.names, mutator);
Walk(x.step, mutator);
mutator.Post(x);
}
}
template <typename V>
static void Walk(const OmpLinearClause::WithoutModifier &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.names, visitor);
Walk(x.step, visitor);
visitor.Post(x);
}
}
template <typename M>
static void Walk(OmpLinearClause::WithoutModifier &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.names, mutator);
Walk(x.step, mutator);
mutator.Post(x);
}
}
};
} // namespace detail

Expand Down
56 changes: 32 additions & 24 deletions flang/include/flang/Parser/parse-tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -3698,6 +3698,22 @@ struct OmpReductionModifier {
WRAPPER_CLASS_BOILERPLATE(OmpReductionModifier, Value);
};

// Ref: [5.2:117-120]
//
// step-complex-modifier ->
// STEP(integer-expression) // since 5.2
struct OmpStepComplexModifier {
WRAPPER_CLASS_BOILERPLATE(OmpStepComplexModifier, ScalarIntExpr);
};

// Ref: [4.5:207-210], [5.0:290-293], [5.1:323-325], [5.2:117-120]
//
// step-simple-modifier ->
// integer-expresion // since 4.5
struct OmpStepSimpleModifier {
WRAPPER_CLASS_BOILERPLATE(OmpStepSimpleModifier, ScalarIntExpr);
};

// Ref: [4.5:169-170], [5.0:254-256], [5.1:287-289], [5.2:321]
//
// task-dependence-type -> // "dependence-type" in 5.1 and before
Expand Down Expand Up @@ -3925,7 +3941,7 @@ struct OmpDeviceTypeClause {
struct OmpFromClause {
TUPLE_CLASS_BOILERPLATE(OmpFromClause);
MODIFIER_BOILERPLATE(OmpExpectation, OmpIterator, OmpMapper);
std::tuple<MODIFIERS(), OmpObjectList, bool> t;
std::tuple<MODIFIERS(), OmpObjectList, /*CommaSeparated=*/bool> t;
};

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

// 2.15.3.7 linear-clause -> LINEAR (linear-list[ : linear-step])
// linear-list -> list | linear-modifier(list)
// Ref: [4.5:207-210], [5.0:290-293], [5.1:323-325], [5.2:117-120]
//
// linear-clause ->
// LINEAR(list [: step-simple-modifier]) | // since 4.5
// LINEAR(linear-modifier(list)
// [: step-simple-modifier]) | // since 4.5, until 5.2[*]
// LINEAR(list [: linear-modifier,
// step-complex-modifier]) // since 5.2
// [*] Still allowed in 5.2 when on DECLARE SIMD, but deprecated.
struct OmpLinearClause {
UNION_CLASS_BOILERPLATE(OmpLinearClause);
struct WithModifier {
BOILERPLATE(WithModifier);
WithModifier(OmpLinearModifier &&m, std::list<Name> &&n,
std::optional<ScalarIntConstantExpr> &&s)
: modifier(std::move(m)), names(std::move(n)), step(std::move(s)) {}
OmpLinearModifier modifier;
std::list<Name> names;
std::optional<ScalarIntConstantExpr> step;
};
struct WithoutModifier {
BOILERPLATE(WithoutModifier);
WithoutModifier(
std::list<Name> &&n, std::optional<ScalarIntConstantExpr> &&s)
: names(std::move(n)), step(std::move(s)) {}
std::list<Name> names;
std::optional<ScalarIntConstantExpr> step;
};
std::variant<WithModifier, WithoutModifier> u;
TUPLE_CLASS_BOILERPLATE(OmpLinearClause);
MODIFIER_BOILERPLATE(
OmpLinearModifier, OmpStepSimpleModifier, OmpStepComplexModifier);
std::tuple<OmpObjectList, MODIFIERS(), /*PostModified=*/bool> t;
};

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

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

// Ref: [5.0:254-255], [5.1:287-288], [5.2:321-322]
Expand Down
2 changes: 2 additions & 0 deletions flang/include/flang/Semantics/openmp-modifiers.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ DECLARE_DESCRIPTOR(parser::OmpOrderingModifier);
DECLARE_DESCRIPTOR(parser::OmpPrescriptiveness);
DECLARE_DESCRIPTOR(parser::OmpReductionIdentifier);
DECLARE_DESCRIPTOR(parser::OmpReductionModifier);
DECLARE_DESCRIPTOR(parser::OmpStepComplexModifier);
DECLARE_DESCRIPTOR(parser::OmpStepSimpleModifier);
DECLARE_DESCRIPTOR(parser::OmpTaskDependenceType);
DECLARE_DESCRIPTOR(parser::OmpVariableCategory);

Expand Down
37 changes: 16 additions & 21 deletions flang/lib/Lower/OpenMP/Clauses.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -895,8 +895,6 @@ Lastprivate make(const parser::OmpClause::Lastprivate &inp,
Linear make(const parser::OmpClause::Linear &inp,
semantics::SemanticsContext &semaCtx) {
// inp.v -> parser::OmpLinearClause
using wrapped = parser::OmpLinearClause;

CLAUSET_ENUM_CONVERT( //
convert, parser::OmpLinearModifier::Value, Linear::LinearModifier,
// clang-format off
Expand All @@ -906,26 +904,23 @@ Linear make(const parser::OmpClause::Linear &inp,
// clang-format on
);

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

return Linear{Fortran::common::visit(
common::visitors{
[&](const wrapped::WithModifier &s) -> Tuple {
return {
/*StepSimpleModifier=*/std::nullopt,
/*StepComplexModifier=*/maybeApply(makeExprFn(semaCtx), s.step),
/*LinearModifier=*/convert(s.modifier.v),
/*List=*/makeList(s.names, makeObjectFn(semaCtx))};
},
[&](const wrapped::WithoutModifier &s) -> Tuple {
return {
/*StepSimpleModifier=*/maybeApply(makeExprFn(semaCtx), s.step),
/*StepComplexModifier=*/std::nullopt,
/*LinearModifier=*/std::nullopt,
/*List=*/makeList(s.names, makeObjectFn(semaCtx))};
},
},
inp.v.u)};
auto *m2 = semantics::OmpGetUniqueModifier<parser::OmpLinearModifier>(mods);
auto &t1 = std::get<parser::OmpObjectList>(inp.v.t);

auto &&maybeStep = m0 ? maybeApplyToV(makeExprFn(semaCtx), m0)
: m1 ? maybeApplyToV(makeExprFn(semaCtx), m1)
: std::optional<Linear::StepComplexModifier>{};

return Linear{{/*StepComplexModifier=*/std::move(maybeStep),
/*LinearModifier=*/maybeApplyToV(convert, m2),
/*List=*/makeObjects(t1, semaCtx)}};
}

Link make(const parser::OmpClause::Link &inp,
Expand Down
63 changes: 56 additions & 7 deletions flang/lib/Parser/openmp-parsers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,25 @@ constexpr ModifierList<Clause, Separator> modifierList(Separator sep) {
return ModifierList<Clause, Separator>(sep);
}

// Parse the input as any modifier from ClauseTy, but only succeed if
// the result was the SpecificTy. It requires that SpecificTy is one
// of the alternatives in ClauseTy::Modifier.
// The reason to have this is that ClauseTy::Modifier has "source",
// while specific modifiers don't. This class allows to parse a specific
// modifier together with obtaining its location.
template <typename SpecificTy, typename ClauseTy>
struct SpecificModifierParser {
using resultType = typename ClauseTy::Modifier;
std::optional<resultType> Parse(ParseState &state) const {
if (auto result{attempt(Parser<resultType>{}).Parse(state)}) {
if (std::holds_alternative<SpecificTy>(result->u)) {
return result;
}
}
return std::nullopt;
}
};

// OpenMP Clauses

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

TYPE_PARSER(construct<OmpStepComplexModifier>( //
"STEP" >> parenthesized(scalarIntExpr)))

TYPE_PARSER(construct<OmpStepSimpleModifier>(scalarIntExpr))

TYPE_PARSER(construct<OmpTaskDependenceType>(
"DEPOBJ" >> pure(OmpTaskDependenceType::Value::Depobj) ||
"IN"_id >> pure(OmpTaskDependenceType::Value::In) ||
Expand Down Expand Up @@ -285,6 +309,11 @@ TYPE_PARSER(sourced(construct<OmpIfClause::Modifier>(OmpDirectiveNameParser{})))
TYPE_PARSER(sourced(construct<OmpLastprivateClause::Modifier>(
Parser<OmpLastprivateModifier>{})))

TYPE_PARSER(sourced(
construct<OmpLinearClause::Modifier>(Parser<OmpLinearModifier>{}) ||
construct<OmpLinearClause::Modifier>(Parser<OmpStepComplexModifier>{}) ||
construct<OmpLinearClause::Modifier>(Parser<OmpStepSimpleModifier>{})))

TYPE_PARSER(sourced(construct<OmpMapClause::Modifier>(
sourced(construct<OmpMapClause::Modifier>(Parser<OmpMapTypeModifier>{}) ||
construct<OmpMapClause::Modifier>(Parser<OmpMapper>{}) ||
Expand Down Expand Up @@ -460,13 +489,33 @@ TYPE_PARSER(construct<OmpToClause>(
applyFunction<OmpToClause>(makeMobClause<false>,
modifierList<OmpToClause>(maybe(","_tok)), Parser<OmpObjectList>{})))

TYPE_CONTEXT_PARSER("Omp LINEAR clause"_en_US,
construct<OmpLinearClause>(
construct<OmpLinearClause>(construct<OmpLinearClause::WithModifier>(
Parser<OmpLinearModifier>{}, parenthesized(nonemptyList(name)),
maybe(":" >> scalarIntConstantExpr))) ||
construct<OmpLinearClause>(construct<OmpLinearClause::WithoutModifier>(
nonemptyList(name), maybe(":" >> scalarIntConstantExpr)))))
OmpLinearClause makeLinearFromOldSyntax(OmpLinearClause::Modifier &&lm,
OmpObjectList &&objs, std::optional<OmpLinearClause::Modifier> &&ssm) {
std::list<OmpLinearClause::Modifier> mods;
mods.emplace_back(std::move(lm));
if (ssm) {
mods.emplace_back(std::move(*ssm));
}
return OmpLinearClause{std::move(objs),
mods.empty() ? decltype(mods){} : std::move(mods),
/*PostModified=*/false};
}

TYPE_PARSER(
// Parse the "modifier(x)" first, because syntacticaly it will match
// an array element (i.e. a list item).
// LINEAR(linear-modifier(list) [: step-simple-modifier])
construct<OmpLinearClause>( //
applyFunction<OmpLinearClause>(makeLinearFromOldSyntax,
SpecificModifierParser<OmpLinearModifier, OmpLinearClause>{},
parenthesized(Parser<OmpObjectList>{}),
maybe(":"_tok >> SpecificModifierParser<OmpStepSimpleModifier,
OmpLinearClause>{}))) ||
// LINEAR(list [: modifiers])
construct<OmpLinearClause>( //
Parser<OmpObjectList>{},
maybe(":"_tok >> nonemptyList(Parser<OmpLinearClause::Modifier>{})),
/*PostModified=*/pure(true)))

// OpenMPv5.2 12.5.2 detach-clause -> DETACH (event-handle)
TYPE_PARSER(construct<OmpDetachClause>(Parser<OmpObject>{}))
Expand Down
62 changes: 56 additions & 6 deletions flang/lib/Parser/unparse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2133,13 +2133,63 @@ class UnparseVisitor {
Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ": ");
Walk(std::get<ScalarLogicalExpr>(x.t));
}
void Unparse(const OmpLinearClause::WithoutModifier &x) {
Walk(x.names, ", ");
Walk(":", x.step);
void Unparse(const OmpStepSimpleModifier &x) { Walk(x.v); }
void Unparse(const OmpStepComplexModifier &x) {
Word("STEP(");
Walk(x.v);
Put(")");
}
void Unparse(const OmpLinearClause::WithModifier &x) {
Walk(x.modifier), Put("("), Walk(x.names, ","), Put(")");
Walk(":", x.step);
void Unparse(const OmpLinearClause &x) {
using Modifier = OmpLinearClause::Modifier;
auto &modifiers{std::get<std::optional<std::list<Modifier>>>(x.t)};
if (std::get<bool>(x.t)) { // PostModified
Walk(std::get<OmpObjectList>(x.t));
Walk(": ", modifiers);
} else {
// Unparse using pre-5.2 syntax.
bool HasStepModifier{false}, HasLinearModifier{false};

if (modifiers) {
bool NeedComma{false};
for (const Modifier &m : *modifiers) {
// Print all linear modifiers in case we need to unparse an
// incorrect tree.
if (auto *lmod{std::get_if<parser::OmpLinearModifier>(&m.u)}) {
if (NeedComma) {
Put(",");
}
Walk(*lmod);
HasLinearModifier = true;
NeedComma = true;
} else {
// If not linear-modifier, then it has to be step modifier.
HasStepModifier = true;
}
}
}

if (HasLinearModifier) {
Put("(");
}
Walk(std::get<OmpObjectList>(x.t));
if (HasLinearModifier) {
Put(")");
}

if (HasStepModifier) {
Put(": ");
bool NeedComma{false};
for (const Modifier &m : *modifiers) {
if (!std::holds_alternative<parser::OmpLinearModifier>(m.u)) {
if (NeedComma) {
Put(",");
}
common::visit([&](auto &&s) { Walk(s); }, m.u);
NeedComma = true;
}
}
}
}
}
void Unparse(const OmpReductionClause &x) {
using Modifier = OmpReductionClause::Modifier;
Expand Down
Loading
Loading