Skip to content

Commit 1c6ec29

Browse files
authored
[flang][OpenMP] Parsing support for iterator modifiers in FROM and TO (#114593)
Parse PRESENT modifier as well while we're at it (no MAPPER though). Add semantic checks for these clauses in the TARGET UPDATE construct, TODO messages in lowering.
1 parent 01463a2 commit 1c6ec29

22 files changed

+784
-42
lines changed

flang/include/flang/Evaluate/check-expression.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,10 @@ extern template std::optional<bool> IsContiguous(
115115
const CoarrayRef &, FoldingContext &);
116116
extern template std::optional<bool> IsContiguous(
117117
const Symbol &, FoldingContext &);
118+
static inline std::optional<bool> IsContiguous(
119+
const SymbolRef &s, FoldingContext &c) {
120+
return IsContiguous(s.get(), c);
121+
}
118122
template <typename A>
119123
bool IsSimplyContiguous(const A &x, FoldingContext &context) {
120124
return IsContiguous(x, context).value_or(false);

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,8 @@ class ParseTreeDumper {
525525
NODE(parser, OmpEndCriticalDirective)
526526
NODE(parser, OmpEndLoopDirective)
527527
NODE(parser, OmpEndSectionsDirective)
528+
NODE(parser, OmpFromClause)
529+
NODE_ENUM(OmpFromClause, Expectation)
528530
NODE(parser, OmpIfClause)
529531
NODE_ENUM(OmpIfClause, DirectiveNameModifier)
530532
NODE_ENUM(OmpLastprivateClause, LastprivateModifier)
@@ -582,6 +584,9 @@ class ParseTreeDumper {
582584
NODE(parser, OmpSectionBlocks)
583585
NODE(parser, OmpSectionsDirective)
584586
NODE(parser, OmpSimpleStandaloneDirective)
587+
NODE(parser, OmpToClause)
588+
// No NODE_ENUM for OmpToClause::Expectation, because it's an alias
589+
// for OmpFromClause::Expectation.
585590
NODE(parser, Only)
586591
NODE(parser, OpenACCAtomicConstruct)
587592
NODE(parser, OpenACCBlockConstruct)

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

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3582,6 +3582,26 @@ struct OmpDeviceTypeClause {
35823582
WRAPPER_CLASS_BOILERPLATE(OmpDeviceTypeClause, Type);
35833583
};
35843584

3585+
// Ref: [4.5:107-109], [5.0:176-180], [5.1:205-210], [5.2:167-168]
3586+
//
3587+
// from-clause ->
3588+
// FROM(locator-list) |
3589+
// FROM(mapper-modifier: locator-list) | // since 5.0
3590+
// FROM(motion-modifier[,] ...: locator-list) // since 5.1
3591+
// motion-modifier ->
3592+
// PRESENT | mapper-modifier | iterator-modifier
3593+
struct OmpFromClause {
3594+
ENUM_CLASS(Expectation, Present);
3595+
TUPLE_CLASS_BOILERPLATE(OmpFromClause);
3596+
3597+
// As in the case of MAP, modifiers are parsed as lists, even if they
3598+
// are unique. These restrictions will be checked in semantic checks.
3599+
std::tuple<std::optional<std::list<Expectation>>,
3600+
std::optional<std::list<OmpIteratorModifier>>, OmpObjectList,
3601+
bool> // were the modifiers comma-separated?
3602+
t;
3603+
};
3604+
35853605
// OMP 5.2 12.6.1 grainsize-clause -> grainsize ([prescriptiveness :] value)
35863606
struct OmpGrainsizeClause {
35873607
TUPLE_CLASS_BOILERPLATE(OmpGrainsizeClause);
@@ -3723,6 +3743,28 @@ struct OmpScheduleClause {
37233743
t;
37243744
};
37253745

3746+
// Ref: [4.5:107-109], [5.0:176-180], [5.1:205-210], [5.2:167-168]
3747+
//
3748+
// to-clause (in DECLARE TARGET) ->
3749+
// TO(extended-list) | // until 5.1
3750+
// to-clause (in TARGET UPDATE) ->
3751+
// TO(locator-list) |
3752+
// TO(mapper-modifier: locator-list) | // since 5.0
3753+
// TO(motion-modifier[,] ...: locator-list) // since 5.1
3754+
// motion-modifier ->
3755+
// PRESENT | mapper-modifier | iterator-modifier
3756+
struct OmpToClause {
3757+
using Expectation = OmpFromClause::Expectation;
3758+
TUPLE_CLASS_BOILERPLATE(OmpToClause);
3759+
3760+
// As in the case of MAP, modifiers are parsed as lists, even if they
3761+
// are unique. These restrictions will be checked in semantic checks.
3762+
std::tuple<std::optional<std::list<Expectation>>,
3763+
std::optional<std::list<OmpIteratorModifier>>, OmpObjectList,
3764+
bool> // were the modifiers comma-separated?
3765+
t;
3766+
};
3767+
37263768
// OMP 5.2 12.6.2 num_tasks-clause -> num_tasks ([prescriptiveness :] value)
37273769
struct OmpNumTasksClause {
37283770
TUPLE_CLASS_BOILERPLATE(OmpNumTasksClause);

flang/lib/Lower/OpenMP/ClauseProcessor.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1019,16 +1019,22 @@ bool ClauseProcessor::processMotionClauses(lower::StatementContext &stmtCtx,
10191019

10201020
auto callbackFn = [&](const auto &clause, const parser::CharBlock &source) {
10211021
mlir::Location clauseLocation = converter.genLocation(source);
1022-
1022+
const auto &[expectation, mapper, iterator, objects] = clause.t;
10231023
// TODO Support motion modifiers: present, mapper, iterator.
1024+
if (expectation) {
1025+
TODO(clauseLocation, "PRESENT modifier is not supported yet");
1026+
} else if (mapper) {
1027+
TODO(clauseLocation, "Mapper modifier is not supported yet");
1028+
} else if (iterator) {
1029+
TODO(clauseLocation, "Iterator modifier is not supported yet");
1030+
}
10241031
constexpr llvm::omp::OpenMPOffloadMappingFlags mapTypeBits =
10251032
std::is_same_v<llvm::remove_cvref_t<decltype(clause)>, omp::clause::To>
10261033
? llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO
10271034
: llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
10281035

1029-
processMapObjects(stmtCtx, clauseLocation, std::get<ObjectList>(clause.t),
1030-
mapTypeBits, parentMemberIndices, result.mapVars,
1031-
mapSymbols);
1036+
processMapObjects(stmtCtx, clauseLocation, objects, mapTypeBits,
1037+
parentMemberIndices, result.mapVars, mapSymbols);
10321038
};
10331039

10341040
bool clauseFound = findRepeatableClause<omp::clause::To>(callbackFn);

flang/lib/Lower/OpenMP/Clauses.cpp

Lines changed: 69 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -728,21 +728,51 @@ Firstprivate make(const parser::OmpClause::Firstprivate &inp,
728728

729729
From make(const parser::OmpClause::From &inp,
730730
semantics::SemanticsContext &semaCtx) {
731-
// inp.v -> parser::OmpObjectList
732-
return From{{/*Expectation=*/std::nullopt, /*Mapper=*/std::nullopt,
733-
/*Iterator=*/std::nullopt,
734-
/*LocatorList=*/makeObjects(inp.v, semaCtx)}};
731+
// inp.v -> parser::OmpFromClause
732+
using wrapped = parser::OmpFromClause;
733+
734+
CLAUSET_ENUM_CONVERT( //
735+
convert, parser::OmpFromClause::Expectation, From::Expectation,
736+
// clang-format off
737+
MS(Present, Present)
738+
// clang-format on
739+
);
740+
741+
auto &t0 = std::get<std::optional<std::list<wrapped::Expectation>>>(inp.v.t);
742+
auto &t1 =
743+
std::get<std::optional<std::list<parser::OmpIteratorModifier>>>(inp.v.t);
744+
auto &t2 = std::get<parser::OmpObjectList>(inp.v.t);
745+
746+
assert((!t0 || t0->size() == 1) && "Only one expectation modifier allowed");
747+
assert((!t1 || t1->size() == 1) && "Only one iterator modifier allowed");
748+
749+
auto expectation = [&]() -> std::optional<From::Expectation> {
750+
if (t0)
751+
return convert(t0->front());
752+
return std::nullopt;
753+
}();
754+
755+
auto iterator = [&]() -> std::optional<Iterator> {
756+
if (t1)
757+
return makeIterator(t1->front(), semaCtx);
758+
return std::nullopt;
759+
}();
760+
761+
return From{{/*Expectation=*/std::move(expectation), /*Mapper=*/std::nullopt,
762+
/*Iterator=*/std::move(iterator),
763+
/*LocatorList=*/makeObjects(t2, semaCtx)}};
735764
}
736765

737766
// Full: empty
738767

739768
Grainsize make(const parser::OmpClause::Grainsize &inp,
740-
semantics::SemanticsContext &semaCtx) {
769+
semantics::SemanticsContext &semaCtx) {
741770
// inp.v -> parser::OmpGrainsizeClause
742771
using wrapped = parser::OmpGrainsizeClause;
743772

744773
CLAUSET_ENUM_CONVERT( //
745-
convert, parser::OmpGrainsizeClause::Prescriptiveness, Grainsize::Prescriptiveness,
774+
convert, parser::OmpGrainsizeClause::Prescriptiveness,
775+
Grainsize::Prescriptiveness,
746776
// clang-format off
747777
MS(Strict, Strict)
748778
// clang-format on
@@ -1274,10 +1304,39 @@ ThreadLimit make(const parser::OmpClause::ThreadLimit &inp,
12741304

12751305
To make(const parser::OmpClause::To &inp,
12761306
semantics::SemanticsContext &semaCtx) {
1277-
// inp.v -> parser::OmpObjectList
1278-
return To{{/*Expectation=*/std::nullopt, /*Mapper=*/std::nullopt,
1279-
/*Iterator=*/std::nullopt,
1280-
/*LocatorList=*/makeObjects(inp.v, semaCtx)}};
1307+
// inp.v -> parser::OmpToClause
1308+
using wrapped = parser::OmpToClause;
1309+
1310+
CLAUSET_ENUM_CONVERT( //
1311+
convert, parser::OmpToClause::Expectation, To::Expectation,
1312+
// clang-format off
1313+
MS(Present, Present)
1314+
// clang-format on
1315+
);
1316+
1317+
auto &t0 = std::get<std::optional<std::list<wrapped::Expectation>>>(inp.v.t);
1318+
auto &t1 =
1319+
std::get<std::optional<std::list<parser::OmpIteratorModifier>>>(inp.v.t);
1320+
auto &t2 = std::get<parser::OmpObjectList>(inp.v.t);
1321+
1322+
assert((!t0 || t0->size() == 1) && "Only one expectation modifier allowed");
1323+
assert((!t1 || t1->size() == 1) && "Only one iterator modifier allowed");
1324+
1325+
auto expectation = [&]() -> std::optional<To::Expectation> {
1326+
if (t0)
1327+
return convert(t0->front());
1328+
return std::nullopt;
1329+
}();
1330+
1331+
auto iterator = [&]() -> std::optional<Iterator> {
1332+
if (t1)
1333+
return makeIterator(t1->front(), semaCtx);
1334+
return std::nullopt;
1335+
}();
1336+
1337+
return To{{/*Expectation=*/std::move(expectation), /*Mapper=*/std::nullopt,
1338+
/*Iterator=*/std::move(iterator),
1339+
/*LocatorList=*/makeObjects(t2, semaCtx)}};
12811340
}
12821341

12831342
// UnifiedAddress: empty

flang/lib/Parser/openmp-parsers.cpp

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,40 @@ template <typename Separator> struct MapModifiers {
122122
const Separator sep_;
123123
};
124124

125+
// This is almost exactly the same thing as MapModifiers. It has the same
126+
// issue (it expects modifiers in a specific order), and the fix for that
127+
// will change how modifiers are parsed. Instead of making this code more
128+
// generic, make it simple, and generalize after the fix is in place.
129+
template <typename Separator> struct MotionModifiers {
130+
constexpr MotionModifiers(Separator sep) : sep_(sep) {}
131+
constexpr MotionModifiers(const MotionModifiers &) = default;
132+
constexpr MotionModifiers(MotionModifiers &&) = default;
133+
134+
// Parsing of mappers if not implemented yet.
135+
using ExpParser = Parser<OmpFromClause::Expectation>;
136+
using IterParser = Parser<OmpIteratorModifier>;
137+
using ModParser = ConcatSeparated<Separator, ExpParser, IterParser>;
138+
139+
using resultType = typename ModParser::resultType;
140+
141+
std::optional<resultType> Parse(ParseState &state) const {
142+
auto mp{ModParser(sep_, ExpParser{}, IterParser{})};
143+
auto mods{mp.Parse(state)};
144+
// The ModParser always "succeeds", i.e. even if the input is junk, it
145+
// will return a tuple filled with nullopts. If any of the components
146+
// is not a nullopt, expect a ":".
147+
if (std::apply([](auto &&...opts) { return (... || !!opts); }, *mods)) {
148+
if (!attempt(":"_tok).Parse(state)) {
149+
return std::nullopt;
150+
}
151+
}
152+
return std::move(mods);
153+
}
154+
155+
private:
156+
const Separator sep_;
157+
};
158+
125159
// OpenMP Clauses
126160

127161
// [5.0] 2.1.6 iterator-specifier -> type-declaration-stmt = subscript-triple |
@@ -382,6 +416,31 @@ TYPE_CONTEXT_PARSER("Omp Depend clause"_en_US,
382416
maybe(Parser<OmpIteratorModifier>{} / ","_tok),
383417
Parser<OmpTaskDependenceType>{} / ":", Parser<OmpObjectList>{})))
384418

419+
TYPE_PARSER(construct<OmpFromClause::Expectation>(
420+
"PRESENT" >> pure(OmpFromClause::Expectation::Present)))
421+
422+
template <typename MotionClause, bool CommasEverywhere>
423+
static inline MotionClause makeMotionClause(
424+
std::tuple<std::optional<std::list<typename MotionClause::Expectation>>,
425+
std::optional<std::list<OmpIteratorModifier>>> &&mods,
426+
OmpObjectList &&objs) {
427+
auto &&[exp, iter] = std::move(mods);
428+
return MotionClause(
429+
std::move(exp), std::move(iter), std::move(objs), CommasEverywhere);
430+
}
431+
432+
TYPE_PARSER(construct<OmpFromClause>(
433+
applyFunction<OmpFromClause>(makeMotionClause<OmpFromClause, true>,
434+
MotionModifiers(","_tok), Parser<OmpObjectList>{}) ||
435+
applyFunction<OmpFromClause>(makeMotionClause<OmpFromClause, false>,
436+
MotionModifiers(maybe(","_tok)), Parser<OmpObjectList>{})))
437+
438+
TYPE_PARSER(construct<OmpToClause>(
439+
applyFunction<OmpToClause>(makeMotionClause<OmpToClause, true>,
440+
MotionModifiers(","_tok), Parser<OmpObjectList>{}) ||
441+
applyFunction<OmpToClause>(makeMotionClause<OmpToClause, false>,
442+
MotionModifiers(maybe(","_tok)), Parser<OmpObjectList>{})))
443+
385444
// 2.15.3.7 LINEAR (linear-list: linear-step)
386445
// linear-list -> list | modifier(list)
387446
// linear-modifier -> REF | VAL | UVAL
@@ -478,11 +537,11 @@ TYPE_PARSER(
478537
parenthesized(scalarIntExpr))) ||
479538
"FINAL" >> construct<OmpClause>(construct<OmpClause::Final>(
480539
parenthesized(scalarLogicalExpr))) ||
481-
"FULL" >> construct<OmpClause>(construct<OmpClause::Full>()) ||
482540
"FIRSTPRIVATE" >> construct<OmpClause>(construct<OmpClause::Firstprivate>(
483541
parenthesized(Parser<OmpObjectList>{}))) ||
484542
"FROM" >> construct<OmpClause>(construct<OmpClause::From>(
485-
parenthesized(Parser<OmpObjectList>{}))) ||
543+
parenthesized(Parser<OmpFromClause>{}))) ||
544+
"FULL" >> construct<OmpClause>(construct<OmpClause::Full>()) ||
486545
"GRAINSIZE" >> construct<OmpClause>(construct<OmpClause::Grainsize>(
487546
parenthesized(Parser<OmpGrainsizeClause>{}))) ||
488547
"HAS_DEVICE_ADDR" >>
@@ -559,7 +618,7 @@ TYPE_PARSER(
559618
"THREAD_LIMIT" >> construct<OmpClause>(construct<OmpClause::ThreadLimit>(
560619
parenthesized(scalarIntExpr))) ||
561620
"TO" >> construct<OmpClause>(construct<OmpClause::To>(
562-
parenthesized(Parser<OmpObjectList>{}))) ||
621+
parenthesized(Parser<OmpToClause>{}))) ||
563622
"USE_DEVICE_PTR" >> construct<OmpClause>(construct<OmpClause::UseDevicePtr>(
564623
parenthesized(Parser<OmpObjectList>{}))) ||
565624
"USE_DEVICE_ADDR" >>

flang/lib/Parser/unparse.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2138,6 +2138,27 @@ class UnparseVisitor {
21382138
Put(",");
21392139
Walk(std::get<std::optional<ScalarIntConstantExpr>>(x.t));
21402140
}
2141+
void Unparse(const OmpFromClause &x) {
2142+
auto &expect{
2143+
std::get<std::optional<std::list<OmpFromClause::Expectation>>>(x.t)};
2144+
auto &iter{std::get<std::optional<std::list<OmpIteratorModifier>>>(x.t)};
2145+
bool needComma{false};
2146+
if (expect) {
2147+
Walk(*expect);
2148+
needComma = true;
2149+
}
2150+
if (iter) {
2151+
if (needComma) {
2152+
Put(", ");
2153+
}
2154+
Walk(*iter);
2155+
needComma = true;
2156+
}
2157+
if (needComma) {
2158+
Put(": ");
2159+
}
2160+
Walk(std::get<OmpObjectList>(x.t));
2161+
}
21412162
void Unparse(const OmpIfClause &x) {
21422163
Walk(std::get<std::optional<OmpIfClause::DirectiveNameModifier>>(x.t), ":");
21432164
Walk(std::get<ScalarLogicalExpr>(x.t));
@@ -2242,6 +2263,27 @@ class UnparseVisitor {
22422263
Walk(":",
22432264
std::get<std::optional<OmpDefaultmapClause::VariableCategory>>(x.t));
22442265
}
2266+
void Unparse(const OmpToClause &x) {
2267+
auto &expect{
2268+
std::get<std::optional<std::list<OmpToClause::Expectation>>>(x.t)};
2269+
auto &iter{std::get<std::optional<std::list<OmpIteratorModifier>>>(x.t)};
2270+
bool needComma{false};
2271+
if (expect) {
2272+
Walk(*expect);
2273+
needComma = true;
2274+
}
2275+
if (iter) {
2276+
if (needComma) {
2277+
Put(", ");
2278+
}
2279+
Walk(*iter);
2280+
needComma = true;
2281+
}
2282+
if (needComma) {
2283+
Put(": ");
2284+
}
2285+
Walk(std::get<OmpObjectList>(x.t));
2286+
}
22452287
#define GEN_FLANG_CLAUSE_UNPARSE
22462288
#include "llvm/Frontend/OpenMP/OMP.inc"
22472289
void Unparse(const OmpLoopDirective &x) {
@@ -2859,6 +2901,7 @@ class UnparseVisitor {
28592901
WALK_NESTED_ENUM(OmpDeviceTypeClause, Type) // OMP DEVICE_TYPE
28602902
WALK_NESTED_ENUM(
28612903
OmpReductionClause, ReductionModifier) // OMP reduction-modifier
2904+
WALK_NESTED_ENUM(OmpFromClause, Expectation) // OMP motion-expectation
28622905
WALK_NESTED_ENUM(OmpIfClause, DirectiveNameModifier) // OMP directive-modifier
28632906
WALK_NESTED_ENUM(OmpCancelType, Type) // OMP cancel-type
28642907
WALK_NESTED_ENUM(OmpOrderClause, Type) // OMP order-type

0 commit comments

Comments
 (0)