Skip to content

Commit c5f29cd

Browse files
committed
[flang][OpenMP] Parse DOACROSS clause
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 faefedf commit c5f29cd

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
@@ -509,15 +509,20 @@ class ParseTreeDumper {
509509
NODE(parser, OmpDefaultmapClause)
510510
NODE_ENUM(OmpDefaultmapClause, ImplicitBehavior)
511511
NODE_ENUM(OmpDefaultmapClause, VariableCategory)
512-
NODE(parser, OmpDependClause)
513-
NODE(parser, OmpDetachClause)
514-
NODE(OmpDependClause, InOut)
515-
NODE(OmpDependClause, Sink)
516-
NODE(OmpDependClause, Source)
512+
NODE(parser, OmpDependenceType)
513+
NODE_ENUM(OmpDependenceType, Type)
517514
NODE(parser, OmpTaskDependenceType)
518515
NODE_ENUM(OmpTaskDependenceType, Type)
519-
NODE(parser, OmpDependSinkVec)
520-
NODE(parser, OmpDependSinkVecLength)
516+
NODE(parser, OmpIterationOffset)
517+
NODE(parser, OmpIteration)
518+
NODE(parser, OmpIterationVector)
519+
NODE(parser, OmpDoacross)
520+
NODE(OmpDoacross, Sink)
521+
NODE(OmpDoacross, Source)
522+
NODE(parser, OmpDependClause)
523+
NODE(OmpDependClause, TaskDep)
524+
NODE(parser, OmpDetachClause)
525+
NODE(parser, OmpDoacrossClause)
521526
NODE(parser, OmpDestroyClause)
522527
NODE(parser, OmpEndAllocators)
523528
NODE(parser, OmpEndAtomic)

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

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

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

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

@@ -3528,41 +3547,55 @@ struct OmpDefaultmapClause {
35283547
std::tuple<ImplicitBehavior, std::optional<VariableCategory>> t;
35293548
};
35303549

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

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

35433576
// Ref: [4.5:169-170], [5.0:255-256], [5.1:288-289], [5.2:323-324]
35443577
//
35453578
// depend-clause ->
35463579
// DEPEND(SOURCE) | // since 4.5, until 5.1
3547-
// DEPEND(SINK: depend-vec) | // since 4.5, until 5.1
3548-
// DEPEND([depend-modifier,]dependence-type: locator-list) // since 4.5
3580+
// DEPEND(SINK: iteration-vector) | // since 4.5, until 5.1
3581+
// DEPEND([depend-modifier,]
3582+
// task-dependence-type: locator-list) // since 4.5
35493583
//
35503584
// depend-modifier -> iterator-modifier // since 5.0
35513585
struct OmpDependClause {
3552-
OmpTaskDependenceType::Type GetDepType() const;
3553-
35543586
UNION_CLASS_BOILERPLATE(OmpDependClause);
3555-
EMPTY_CLASS(Source);
3556-
WRAPPER_CLASS(Sink, std::list<OmpDependSinkVec>);
3557-
struct InOut {
3558-
TUPLE_CLASS_BOILERPLATE(InOut);
3587+
struct TaskDep {
3588+
OmpTaskDependenceType::Type GetTaskDepType() const;
3589+
TUPLE_CLASS_BOILERPLATE(TaskDep);
35593590
std::tuple<std::optional<OmpIteratorModifier>, OmpTaskDependenceType,
35603591
OmpObjectList>
35613592
t;
35623593
};
3563-
std::variant<Source, Sink, InOut> u;
3594+
std::variant<TaskDep, OmpDoacross> u;
35643595
};
35653596

3597+
WRAPPER_CLASS(OmpDoacrossClause, OmpDoacross);
3598+
35663599
// Ref: [5.0:254-255], [5.1:287-288], [5.2:73]
35673600
//
35683601
// 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
// OpenMP Clauses
37823819
struct OmpClause {

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
}
@@ -1356,7 +1364,9 @@ Uniform make(const parser::OmpClause::Uniform &inp,
13561364
Update make(const parser::OmpClause::Update &inp,
13571365
semantics::SemanticsContext &semaCtx) {
13581366
// inp.v -> parser::OmpUpdateClause
1359-
return Update{/*TaskDependenceType=*/makeDepType(inp.v.v)};
1367+
auto depType =
1368+
common::visit([](auto &&s) { return makeDepType(s); }, inp.v.u);
1369+
return Update{/*DependenceType=*/depType};
13601370
}
13611371

13621372
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)