Skip to content

Commit 01e0445

Browse files
kparzyszGroverkss
authored andcommitted
[flang][OpenMP] Parse DOACROSS clause (llvm#115396)
Extract the SINK/SOURCE parse tree elements into a separate class `OmpDoacross`, share them between DEPEND and DOACROSS clauses. Most of the changes in Semantics are to accommodate the new contents of OmpDependClause, and a mere introduction of OmpDoacrossClause. There are no semantic checks specifically for DOACROSS.
1 parent 7801a96 commit 01e0445

24 files changed

+525
-259
lines changed

flang/examples/FeatureList/FeatureList.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -470,13 +470,17 @@ struct NodeVisitor {
470470
READ_FEATURE(OmpDefaultmapClause::ImplicitBehavior)
471471
READ_FEATURE(OmpDefaultmapClause::VariableCategory)
472472
READ_FEATURE(OmpDependClause)
473-
READ_FEATURE(OmpDependClause::InOut)
474-
READ_FEATURE(OmpDependClause::Sink)
475-
READ_FEATURE(OmpDependClause::Source)
473+
READ_FEATURE(OmpDependClause::TaskDep)
474+
READ_FEATURE(OmpDoacross::Sink)
475+
READ_FEATURE(OmpDoacross::Source)
476+
READ_FEATURE(OmpDoacrossClause)
477+
READ_FEATURE(OmpDependenceType)
478+
READ_FEATURE(OmpDependenceType::Type)
476479
READ_FEATURE(OmpTaskDependenceType)
477480
READ_FEATURE(OmpTaskDependenceType::Type)
478-
READ_FEATURE(OmpDependSinkVec)
479-
READ_FEATURE(OmpDependSinkVecLength)
481+
READ_FEATURE(OmpIteration)
482+
READ_FEATURE(OmpIterationOffset)
483+
READ_FEATURE(OmpIterationVector)
480484
READ_FEATURE(OmpEndAllocators)
481485
READ_FEATURE(OmpEndAtomic)
482486
READ_FEATURE(OmpEndBlockDirective)

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

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -510,15 +510,20 @@ class ParseTreeDumper {
510510
NODE(parser, OmpDefaultmapClause)
511511
NODE_ENUM(OmpDefaultmapClause, ImplicitBehavior)
512512
NODE_ENUM(OmpDefaultmapClause, VariableCategory)
513-
NODE(parser, OmpDependClause)
514-
NODE(parser, OmpDetachClause)
515-
NODE(OmpDependClause, InOut)
516-
NODE(OmpDependClause, Sink)
517-
NODE(OmpDependClause, Source)
513+
NODE(parser, OmpDependenceType)
514+
NODE_ENUM(OmpDependenceType, Type)
518515
NODE(parser, OmpTaskDependenceType)
519516
NODE_ENUM(OmpTaskDependenceType, Type)
520-
NODE(parser, OmpDependSinkVec)
521-
NODE(parser, OmpDependSinkVecLength)
517+
NODE(parser, OmpIterationOffset)
518+
NODE(parser, OmpIteration)
519+
NODE(parser, OmpIterationVector)
520+
NODE(parser, OmpDoacross)
521+
NODE(OmpDoacross, Sink)
522+
NODE(OmpDoacross, Source)
523+
NODE(parser, OmpDependClause)
524+
NODE(OmpDependClause, TaskDep)
525+
NODE(parser, OmpDetachClause)
526+
NODE(parser, OmpDoacrossClause)
522527
NODE(parser, OmpDestroyClause)
523528
NODE(parser, OmpEndAllocators)
524529
NODE(parser, OmpEndAtomic)

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

Lines changed: 58 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3440,16 +3440,35 @@ struct OmpObject {
34403440

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

3443+
// Ref: [4.5:169-170], [5.0:255-256], [5.1:288-289]
3444+
//
3445+
// 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
3450+
//
3451+
// All of these, except SINK and SOURCE became task-dependence-type in 5.2.
3452+
//
3453+
// Keeping these two as separate types, since having them all together
3454+
// creates conflicts when parsing the DEPEND clause. For DEPEND(SINK: ...),
3455+
// the SINK may be parsed as 'task-dependence-type', and the list after
3456+
// the ':' would then be parsed as OmpObjectList (instead of the iteration
3457+
// vector). This would accept the vector "i, j, k" (although interpreted
3458+
// incorrectly), while flagging a syntax error for "i+1, j, k".
3459+
struct OmpDependenceType {
3460+
ENUM_CLASS(Type, Sink, Source);
3461+
WRAPPER_CLASS_BOILERPLATE(OmpDependenceType, Type);
3462+
};
3463+
34433464
// Ref: [4.5:169-170], [5.0:254-256], [5.1:287-289], [5.2:321]
34443465
//
34453466
// task-dependence-type -> // "dependence-type" in 5.1 and before
34463467
// IN | OUT | INOUT | // since 4.5
3447-
// SOURCE | SINK | // since 4.5, until 5.1
34483468
// MUTEXINOUTSET | DEPOBJ | // since 5.0
34493469
// INOUTSET // since 5.2
34503470
struct OmpTaskDependenceType {
3451-
ENUM_CLASS(
3452-
Type, In, Out, Inout, Inoutset, Mutexinoutset, Source, Sink, Depobj)
3471+
ENUM_CLASS(Type, In, Out, Inout, Inoutset, Mutexinoutset, Depobj)
34533472
WRAPPER_CLASS_BOILERPLATE(OmpTaskDependenceType, Type);
34543473
};
34553474

@@ -3529,41 +3548,55 @@ struct OmpDefaultmapClause {
35293548
std::tuple<ImplicitBehavior, std::optional<VariableCategory>> t;
35303549
};
35313550

3532-
// 2.13.9 depend-vec-length -> +/- non-negative-constant
3533-
struct OmpDependSinkVecLength {
3534-
TUPLE_CLASS_BOILERPLATE(OmpDependSinkVecLength);
3551+
// 2.13.9 iteration-offset -> +/- non-negative-constant
3552+
struct OmpIterationOffset {
3553+
TUPLE_CLASS_BOILERPLATE(OmpIterationOffset);
35353554
std::tuple<DefinedOperator, ScalarIntConstantExpr> t;
35363555
};
35373556

3538-
// 2.13.9 depend-vec -> induction-variable [depend-vec-length], ...
3539-
struct OmpDependSinkVec {
3540-
TUPLE_CLASS_BOILERPLATE(OmpDependSinkVec);
3541-
std::tuple<Name, std::optional<OmpDependSinkVecLength>> t;
3557+
// 2.13.9 iteration -> induction-variable [iteration-offset]
3558+
struct OmpIteration {
3559+
TUPLE_CLASS_BOILERPLATE(OmpIteration);
3560+
std::tuple<Name, std::optional<OmpIterationOffset>> t;
3561+
};
3562+
3563+
WRAPPER_CLASS(OmpIterationVector, std::list<OmpIteration>);
3564+
3565+
// Extract this into a separate structure (instead of having it directly in
3566+
// OmpDoacrossClause), so that the context in TYPE_CONTEXT_PARSER can be set
3567+
// separately for OmpDependClause and OmpDoacrossClause.
3568+
struct OmpDoacross {
3569+
OmpDependenceType::Type GetDepType() const;
3570+
3571+
WRAPPER_CLASS(Sink, OmpIterationVector);
3572+
EMPTY_CLASS(Source);
3573+
UNION_CLASS_BOILERPLATE(OmpDoacross);
3574+
std::variant<Sink, Source> u;
35423575
};
35433576

35443577
// Ref: [4.5:169-170], [5.0:255-256], [5.1:288-289], [5.2:323-324]
35453578
//
35463579
// depend-clause ->
35473580
// DEPEND(SOURCE) | // since 4.5, until 5.1
3548-
// DEPEND(SINK: depend-vec) | // since 4.5, until 5.1
3549-
// DEPEND([depend-modifier,]dependence-type: locator-list) // since 4.5
3581+
// DEPEND(SINK: iteration-vector) | // since 4.5, until 5.1
3582+
// DEPEND([depend-modifier,]
3583+
// task-dependence-type: locator-list) // since 4.5
35503584
//
35513585
// depend-modifier -> iterator-modifier // since 5.0
35523586
struct OmpDependClause {
3553-
OmpTaskDependenceType::Type GetDepType() const;
3554-
35553587
UNION_CLASS_BOILERPLATE(OmpDependClause);
3556-
EMPTY_CLASS(Source);
3557-
WRAPPER_CLASS(Sink, std::list<OmpDependSinkVec>);
3558-
struct InOut {
3559-
TUPLE_CLASS_BOILERPLATE(InOut);
3588+
struct TaskDep {
3589+
OmpTaskDependenceType::Type GetTaskDepType() const;
3590+
TUPLE_CLASS_BOILERPLATE(TaskDep);
35603591
std::tuple<std::optional<OmpIteratorModifier>, OmpTaskDependenceType,
35613592
OmpObjectList>
35623593
t;
35633594
};
3564-
std::variant<Source, Sink, InOut> u;
3595+
std::variant<TaskDep, OmpDoacross> u;
35653596
};
35663597

3598+
WRAPPER_CLASS(OmpDoacrossClause, OmpDoacross);
3599+
35673600
// Ref: [5.0:254-255], [5.1:287-288], [5.2:73]
35683601
//
35693602
// destroy-clause ->
@@ -3775,8 +3808,12 @@ struct OmpNumTasksClause {
37753808

37763809
// Ref: [5.0:254-255], [5.1:287-288], [5.2:321-322]
37773810
//
3778-
// update-clause -> UPDATE(task-dependence-type) // since 5.0
3779-
WRAPPER_CLASS(OmpUpdateClause, OmpTaskDependenceType);
3811+
// update-clause -> UPDATE(dependence-type) // since 5.0, until 5.1
3812+
// update-clause -> UPDATE(task-dependence-type) // since 5.2
3813+
struct OmpUpdateClause {
3814+
UNION_CLASS_BOILERPLATE(OmpUpdateClause);
3815+
std::variant<OmpDependenceType, OmpTaskDependenceType> u;
3816+
};
37803817

37813818
// OMP 5.2 11.7.1 bind-clause ->
37823819
// BIND( PARALLEL | TEAMS | THREAD )

flang/lib/Lower/OpenMP/ClauseProcessor.cpp

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -122,28 +122,28 @@ genProcBindKindAttr(fir::FirOpBuilder &firOpBuilder,
122122

123123
static mlir::omp::ClauseTaskDependAttr
124124
genDependKindAttr(lower::AbstractConverter &converter,
125-
const omp::clause::Depend::TaskDependenceType kind) {
125+
const omp::clause::DependenceType kind) {
126126
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
127127
mlir::Location currentLocation = converter.getCurrentLocation();
128128

129129
mlir::omp::ClauseTaskDepend pbKind;
130130
switch (kind) {
131-
case omp::clause::Depend::TaskDependenceType::In:
131+
case omp::clause::DependenceType::In:
132132
pbKind = mlir::omp::ClauseTaskDepend::taskdependin;
133133
break;
134-
case omp::clause::Depend::TaskDependenceType::Out:
134+
case omp::clause::DependenceType::Out:
135135
pbKind = mlir::omp::ClauseTaskDepend::taskdependout;
136136
break;
137-
case omp::clause::Depend::TaskDependenceType::Inout:
137+
case omp::clause::DependenceType::Inout:
138138
pbKind = mlir::omp::ClauseTaskDepend::taskdependinout;
139139
break;
140-
case omp::clause::Depend::TaskDependenceType::Mutexinoutset:
141-
case omp::clause::Depend::TaskDependenceType::Inoutset:
140+
case omp::clause::DependenceType::Mutexinoutset:
141+
case omp::clause::DependenceType::Inoutset:
142142
TODO(currentLocation, "INOUTSET and MUTEXINOUTSET are not supported yet");
143143
break;
144-
case omp::clause::Depend::TaskDependenceType::Depobj:
145-
case omp::clause::Depend::TaskDependenceType::Sink:
146-
case omp::clause::Depend::TaskDependenceType::Source:
144+
case omp::clause::DependenceType::Depobj:
145+
case omp::clause::DependenceType::Sink:
146+
case omp::clause::DependenceType::Source:
147147
llvm_unreachable("unhandled parser task dependence type");
148148
break;
149149
}
@@ -803,20 +803,20 @@ bool ClauseProcessor::processDepend(mlir::omp::DependClauseOps &result) const {
803803
auto process = [&](const omp::clause::Depend &clause,
804804
const parser::CharBlock &) {
805805
using Depend = omp::clause::Depend;
806-
if (!std::holds_alternative<Depend::DepType>(clause.u)) {
806+
if (!std::holds_alternative<Depend::TaskDep>(clause.u)) {
807807
TODO(converter.getCurrentLocation(),
808808
"DEPEND clause with SINK or SOURCE is not supported yet");
809809
}
810-
auto &depType = std::get<Depend::DepType>(clause.u);
811-
auto kind = std::get<Depend::TaskDependenceType>(depType.t);
812-
auto &objects = std::get<omp::ObjectList>(depType.t);
810+
auto &taskDep = std::get<Depend::TaskDep>(clause.u);
811+
auto depType = std::get<clause::DependenceType>(taskDep.t);
812+
auto &objects = std::get<omp::ObjectList>(taskDep.t);
813813

814-
if (std::get<std::optional<omp::clause::Iterator>>(depType.t)) {
814+
if (std::get<std::optional<omp::clause::Iterator>>(taskDep.t)) {
815815
TODO(converter.getCurrentLocation(),
816816
"Support for iterator modifiers is not implemented yet");
817817
}
818818
mlir::omp::ClauseTaskDependAttr dependTypeOperand =
819-
genDependKindAttr(converter, kind);
819+
genDependKindAttr(converter, depType);
820820
result.dependKinds.append(objects.size(), dependTypeOperand);
821821

822822
for (const omp::Object &object : objects) {

flang/lib/Lower/OpenMP/Clauses.cpp

Lines changed: 61 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -338,27 +338,32 @@ ReductionOperator makeReductionOperator(const parser::OmpReductionOperator &inp,
338338
inp.u);
339339
}
340340

341-
clause::TaskDependenceType
342-
makeDepType(const parser::OmpTaskDependenceType &inp) {
341+
clause::DependenceType makeDepType(const parser::OmpDependenceType &inp) {
342+
switch (inp.v) {
343+
case parser::OmpDependenceType::Type::Sink:
344+
return clause::DependenceType::Sink;
345+
case parser::OmpDependenceType::Type::Source:
346+
return clause::DependenceType::Source;
347+
}
348+
llvm_unreachable("Unexpected dependence type");
349+
}
350+
351+
clause::DependenceType makeDepType(const parser::OmpTaskDependenceType &inp) {
343352
switch (inp.v) {
344353
case parser::OmpTaskDependenceType::Type::Depobj:
345-
return clause::TaskDependenceType::Depobj;
354+
return clause::DependenceType::Depobj;
346355
case parser::OmpTaskDependenceType::Type::In:
347-
return clause::TaskDependenceType::In;
356+
return clause::DependenceType::In;
348357
case parser::OmpTaskDependenceType::Type::Inout:
349-
return clause::TaskDependenceType::Inout;
358+
return clause::DependenceType::Inout;
350359
case parser::OmpTaskDependenceType::Type::Inoutset:
351-
return clause::TaskDependenceType::Inoutset;
360+
return clause::DependenceType::Inoutset;
352361
case parser::OmpTaskDependenceType::Type::Mutexinoutset:
353-
return clause::TaskDependenceType::Mutexinoutset;
362+
return clause::DependenceType::Mutexinoutset;
354363
case parser::OmpTaskDependenceType::Type::Out:
355-
return clause::TaskDependenceType::Out;
356-
case parser::OmpTaskDependenceType::Type::Sink:
357-
return clause::TaskDependenceType::Sink;
358-
case parser::OmpTaskDependenceType::Type::Source:
359-
return clause::TaskDependenceType::Source;
364+
return clause::DependenceType::Out;
360365
}
361-
llvm_unreachable("Unexpected dependence type");
366+
llvm_unreachable("Unexpected task dependence type");
362367
}
363368

364369
// --------------------------------------------------------------------
@@ -574,49 +579,52 @@ Depend make(const parser::OmpClause::Depend &inp,
574579
// inp.v -> parser::OmpDependClause
575580
using wrapped = parser::OmpDependClause;
576581
using Variant = decltype(Depend::u);
577-
// Iteration is the equivalent of parser::OmpDependSinkVec
582+
// Iteration is the equivalent of parser::OmpIteration
578583
using Iteration = Doacross::Vector::value_type; // LoopIterationT
579584

585+
auto visitSource = [&](const parser::OmpDoacross::Source &) -> Variant {
586+
return Doacross{{/*DependenceType=*/Doacross::DependenceType::Source,
587+
/*Vector=*/{}}};
588+
};
589+
590+
auto visitSink = [&](const parser::OmpDoacross::Sink &s) -> Variant {
591+
using IterOffset = parser::OmpIterationOffset;
592+
auto convert2 = [&](const parser::OmpIteration &v) {
593+
auto &t0 = std::get<parser::Name>(v.t);
594+
auto &t1 = std::get<std::optional<IterOffset>>(v.t);
595+
596+
auto convert3 = [&](const IterOffset &u) {
597+
auto &s0 = std::get<parser::DefinedOperator>(u.t);
598+
auto &s1 = std::get<parser::ScalarIntConstantExpr>(u.t);
599+
return Iteration::Distance{
600+
{makeDefinedOperator(s0, semaCtx), makeExpr(s1, semaCtx)}};
601+
};
602+
return Iteration{{makeObject(t0, semaCtx), maybeApply(convert3, t1)}};
603+
};
604+
return Doacross{{/*DependenceType=*/Doacross::DependenceType::Sink,
605+
/*Vector=*/makeList(s.v.v, convert2)}};
606+
};
607+
608+
auto visitTaskDep = [&](const wrapped::TaskDep &s) -> Variant {
609+
auto &t0 = std::get<std::optional<parser::OmpIteratorModifier>>(s.t);
610+
auto &t1 = std::get<parser::OmpTaskDependenceType>(s.t);
611+
auto &t2 = std::get<parser::OmpObjectList>(s.t);
612+
613+
auto &&maybeIter =
614+
maybeApply([&](auto &&s) { return makeIterator(s, semaCtx); }, t0);
615+
return Depend::TaskDep{{/*DependenceType=*/makeDepType(t1),
616+
/*Iterator=*/std::move(maybeIter),
617+
/*LocatorList=*/makeObjects(t2, semaCtx)}};
618+
};
619+
580620
return Depend{Fortran::common::visit( //
581621
common::visitors{
582622
// Doacross
583-
[&](const wrapped::Source &s) -> Variant {
584-
return Doacross{
585-
{/*DependenceType=*/Doacross::DependenceType::Source,
586-
/*Vector=*/{}}};
587-
},
588-
// Doacross
589-
[&](const wrapped::Sink &s) -> Variant {
590-
using DependLength = parser::OmpDependSinkVecLength;
591-
auto convert2 = [&](const parser::OmpDependSinkVec &v) {
592-
auto &t0 = std::get<parser::Name>(v.t);
593-
auto &t1 = std::get<std::optional<DependLength>>(v.t);
594-
595-
auto convert3 = [&](const DependLength &u) {
596-
auto &s0 = std::get<parser::DefinedOperator>(u.t);
597-
auto &s1 = std::get<parser::ScalarIntConstantExpr>(u.t);
598-
return Iteration::Distance{
599-
{makeDefinedOperator(s0, semaCtx), makeExpr(s1, semaCtx)}};
600-
};
601-
return Iteration{
602-
{makeObject(t0, semaCtx), maybeApply(convert3, t1)}};
603-
};
604-
return Doacross{{/*DependenceType=*/Doacross::DependenceType::Sink,
605-
/*Vector=*/makeList(s.v, convert2)}};
606-
},
607-
// Depend::DepType
608-
[&](const wrapped::InOut &s) -> Variant {
609-
auto &t0 =
610-
std::get<std::optional<parser::OmpIteratorModifier>>(s.t);
611-
auto &t1 = std::get<parser::OmpTaskDependenceType>(s.t);
612-
auto &t2 = std::get<parser::OmpObjectList>(s.t);
613-
614-
auto &&maybeIter = maybeApply(
615-
[&](auto &&s) { return makeIterator(s, semaCtx); }, t0);
616-
return Depend::DepType{{/*TaskDependenceType=*/makeDepType(t1),
617-
/*Iterator=*/std::move(maybeIter),
618-
/*LocatorList=*/makeObjects(t2, semaCtx)}};
623+
[&](const parser::OmpDoacross &s) -> Variant {
624+
return common::visit(common::visitors{visitSink, visitSource}, s.u);
619625
},
626+
// Depend::TaskDep
627+
visitTaskDep,
620628
},
621629
inp.v.u)};
622630
}
@@ -1355,7 +1363,9 @@ Uniform make(const parser::OmpClause::Uniform &inp,
13551363
Update make(const parser::OmpClause::Update &inp,
13561364
semantics::SemanticsContext &semaCtx) {
13571365
// inp.v -> parser::OmpUpdateClause
1358-
return Update{/*TaskDependenceType=*/makeDepType(inp.v.v)};
1366+
auto depType =
1367+
common::visit([](auto &&s) { return makeDepType(s); }, inp.v.u);
1368+
return Update{/*DependenceType=*/depType};
13591369
}
13601370

13611371
Use make(const parser::OmpClause::Use &inp,

flang/lib/Lower/OpenMP/Clauses.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ using IteratorSpecifier = tomp::type::IteratorSpecifierT<TypeTy, IdTy, ExprTy>;
152152
using DefinedOperator = tomp::type::DefinedOperatorT<IdTy, ExprTy>;
153153
using ProcedureDesignator = tomp::type::ProcedureDesignatorT<IdTy, ExprTy>;
154154
using ReductionOperator = tomp::type::ReductionIdentifierT<IdTy, ExprTy>;
155-
using TaskDependenceType = tomp::type::TaskDependenceType;
155+
using DependenceType = tomp::type::DependenceType;
156156

157157
// "Requires" clauses are handled early on, and the aggregated information
158158
// is stored in the Symbol details of modules, programs, and subprograms.

0 commit comments

Comments
 (0)