[flang] [llvm] [flang][OpenMP] Parser support for DEPOBJ plus DEPEND, DESTROY, UPDATE (PR #114074)
Krzysztof Parzyszek via llvm-commits
llvm-commits at lists.llvm.org
Tue Oct 29 08:43:15 PDT 2024
https://github.com/kparzysz created https://github.com/llvm/llvm-project/pull/114074
Parse the DEPOBJ construct and the associated clauses, perform basic semantic checks.
>From 24e8174c47379351577cfd7b7772fee267681bf8 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Fri, 25 Oct 2024 12:01:29 -0500
Subject: [PATCH] [flang][OpenMP] Parser support for DEPOBJ plus DEPEND,
DESTROY, UPDATE
Parse the DEPOBJ construct and the associated clauses, perform basic
semantic checks.
---
flang/include/flang/Parser/dump-parse-tree.h | 3 +
flang/include/flang/Parser/parse-tree.h | 57 +++++--
flang/include/flang/Semantics/symbol.h | 2 +-
flang/lib/Lower/OpenMP/ClauseProcessor.cpp | 2 +
flang/lib/Lower/OpenMP/Clauses.cpp | 49 ++++--
flang/lib/Lower/OpenMP/Clauses.h | 1 +
flang/lib/Lower/OpenMP/OpenMP.cpp | 15 ++
flang/lib/Parser/openmp-parsers.cpp | 18 ++-
flang/lib/Parser/parse-tree.cpp | 17 ++
flang/lib/Parser/unparse.cpp | 12 +-
flang/lib/Semantics/check-omp-structure.cpp | 152 ++++++++++++++++--
flang/lib/Semantics/check-omp-structure.h | 2 +
flang/lib/Semantics/resolve-directives.cpp | 8 +
flang/lib/Semantics/resolve-names.cpp | 7 +
.../Lower/OpenMP/Todo/depobj-construct.f90 | 9 ++
flang/test/Parser/OpenMP/depobj-construct.f90 | 64 ++++++++
.../Semantics/OpenMP/depobj-construct-v50.f90 | 28 ++++
.../Semantics/OpenMP/depobj-construct-v51.f90 | 13 ++
.../Semantics/OpenMP/depobj-construct-v52.f90 | 15 ++
llvm/include/llvm/Frontend/OpenMP/ClauseT.h | 3 +-
llvm/include/llvm/Frontend/OpenMP/OMP.td | 3 +
21 files changed, 429 insertions(+), 51 deletions(-)
create mode 100644 flang/test/Lower/OpenMP/Todo/depobj-construct.f90
create mode 100644 flang/test/Parser/OpenMP/depobj-construct.f90
create mode 100644 flang/test/Semantics/OpenMP/depobj-construct-v50.f90
create mode 100644 flang/test/Semantics/OpenMP/depobj-construct-v51.f90
create mode 100644 flang/test/Semantics/OpenMP/depobj-construct-v52.f90
diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h
index 31ad1b7c6ce5b5..67f7e1aac40edb 100644
--- a/flang/include/flang/Parser/dump-parse-tree.h
+++ b/flang/include/flang/Parser/dump-parse-tree.h
@@ -517,6 +517,7 @@ class ParseTreeDumper {
NODE_ENUM(OmpTaskDependenceType, Type)
NODE(parser, OmpDependSinkVec)
NODE(parser, OmpDependSinkVecLength)
+ NODE(parser, OmpDestroyClause)
NODE(parser, OmpEndAllocators)
NODE(parser, OmpEndAtomic)
NODE(parser, OmpEndBlockDirective)
@@ -571,6 +572,7 @@ class ParseTreeDumper {
NODE_ENUM(OmpDeviceClause, DeviceModifier)
NODE(parser, OmpDeviceTypeClause)
NODE_ENUM(OmpDeviceTypeClause, Type)
+ NODE(parser, OmpUpdateClause)
NODE(parser, OmpScheduleModifier)
NODE(OmpScheduleModifier, Modifier1)
NODE(OmpScheduleModifier, Modifier2)
@@ -609,6 +611,7 @@ class ParseTreeDumper {
NODE(parser, OmpAtomicClauseList)
NODE(parser, OmpAtomicDefaultMemOrderClause)
NODE_ENUM(common, OmpAtomicDefaultMemOrderType)
+ NODE(parser, OpenMPDepobjConstruct)
NODE(parser, OpenMPFlushConstruct)
NODE(parser, OpenMPLoopConstruct)
NODE(parser, OpenMPExecutableAllocate)
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index 174f4c631e9d4c..13c3353512208b 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -3447,7 +3447,7 @@ WRAPPER_CLASS(OmpObjectList, std::list<OmpObject>);
// MUTEXINOUTSET | DEPOBJ | // since 5.0
// INOUTSET // since 5.2
struct OmpTaskDependenceType {
- ENUM_CLASS(Type, In, Out, Inout, Source, Sink)
+ ENUM_CLASS(Type, In, Out, Inout, Source, Sink, Depobj)
WRAPPER_CLASS_BOILERPLATE(OmpTaskDependenceType, Type);
};
@@ -3527,19 +3527,6 @@ struct OmpDefaultmapClause {
std::tuple<ImplicitBehavior, std::optional<VariableCategory>> t;
};
-// device([ device-modifier :] scalar-integer-expression)
-struct OmpDeviceClause {
- TUPLE_CLASS_BOILERPLATE(OmpDeviceClause);
- ENUM_CLASS(DeviceModifier, Ancestor, Device_Num)
- std::tuple<std::optional<DeviceModifier>, ScalarIntExpr> t;
-};
-
-// device_type(any | host | nohost)
-struct OmpDeviceTypeClause {
- ENUM_CLASS(Type, Any, Host, Nohost)
- WRAPPER_CLASS_BOILERPLATE(OmpDeviceTypeClause, Type);
-};
-
// 2.13.9 depend-vec-length -> +/- non-negative-constant
struct OmpDependSinkVecLength {
TUPLE_CLASS_BOILERPLATE(OmpDependSinkVecLength);
@@ -3561,6 +3548,8 @@ struct OmpDependSinkVec {
//
// depend-modifier -> iterator-modifier // since 5.0
struct OmpDependClause {
+ OmpTaskDependenceType::Type GetDepType() const;
+
UNION_CLASS_BOILERPLATE(OmpDependClause);
EMPTY_CLASS(Source);
WRAPPER_CLASS(Sink, std::list<OmpDependSinkVec>);
@@ -3573,6 +3562,26 @@ struct OmpDependClause {
std::variant<Source, Sink, InOut> u;
};
+// Ref: [5.0:254-255], [5.1:287-288], [5.2:73]
+//
+// destroy-clause ->
+// DESTROY | // since 5.0, until 5.2
+// DESTROY(variable) // since 5.2
+WRAPPER_CLASS(OmpDestroyClause, OmpObject);
+
+// device([ device-modifier :] scalar-integer-expression)
+struct OmpDeviceClause {
+ TUPLE_CLASS_BOILERPLATE(OmpDeviceClause);
+ ENUM_CLASS(DeviceModifier, Ancestor, Device_Num)
+ std::tuple<std::optional<DeviceModifier>, ScalarIntExpr> t;
+};
+
+// device_type(any | host | nohost)
+struct OmpDeviceTypeClause {
+ ENUM_CLASS(Type, Any, Host, Nohost)
+ WRAPPER_CLASS_BOILERPLATE(OmpDeviceTypeClause, Type);
+};
+
// OMP 5.2 12.6.1 grainsize-clause -> grainsize ([prescriptiveness :] value)
struct OmpGrainsizeClause {
TUPLE_CLASS_BOILERPLATE(OmpGrainsizeClause);
@@ -3716,6 +3725,11 @@ struct OmpNumTasksClause {
std::tuple<std::optional<Prescriptiveness>, ScalarIntExpr> t;
};
+// Ref: [5.0:254-255], [5.1:287-288], [5.2:321-322]
+//
+// update-clause -> UPDATE(task-dependence-type) // since 5.0
+WRAPPER_CLASS(OmpUpdateClause, OmpTaskDependenceType);
+
// OpenMP Clauses
struct OmpClause {
UNION_CLASS_BOILERPLATE(OmpClause);
@@ -4023,6 +4037,18 @@ struct OpenMPCancelConstruct {
std::tuple<Verbatim, OmpCancelType, std::optional<If>> t;
};
+// Ref: [5.0:254-255], [5.1:287-288], [5.2:322-323]
+//
+// depobj-construct -> DEPOBJ(depend-object) depobj-clause // since 5.0
+// depobj-clause -> depend-clause | // until 5.2
+// destroy-clause |
+// update-clause
+struct OpenMPDepobjConstruct {
+ TUPLE_CLASS_BOILERPLATE(OpenMPDepobjConstruct);
+ CharBlock source;
+ std::tuple<Verbatim, OmpObject, OmpClause> t;
+};
+
// 2.17.8 flush -> FLUSH [memory-order-clause] [(variable-name-list)]
struct OpenMPFlushConstruct {
TUPLE_CLASS_BOILERPLATE(OpenMPFlushConstruct);
@@ -4047,7 +4073,8 @@ struct OpenMPStandaloneConstruct {
UNION_CLASS_BOILERPLATE(OpenMPStandaloneConstruct);
CharBlock source;
std::variant<OpenMPSimpleStandaloneConstruct, OpenMPFlushConstruct,
- OpenMPCancelConstruct, OpenMPCancellationPointConstruct>
+ OpenMPCancelConstruct, OpenMPCancellationPointConstruct,
+ OpenMPDepobjConstruct>
u;
};
diff --git a/flang/include/flang/Semantics/symbol.h b/flang/include/flang/Semantics/symbol.h
index 0767d8ea84bc6b..b9512f33eaacd5 100644
--- a/flang/include/flang/Semantics/symbol.h
+++ b/flang/include/flang/Semantics/symbol.h
@@ -755,7 +755,7 @@ class Symbol {
OmpDeclarativeAllocateDirective, OmpExecutableAllocateDirective,
OmpDeclareSimd, OmpDeclareTarget, OmpThreadprivate, OmpDeclareReduction,
OmpFlushed, OmpCriticalLock, OmpIfSpecified, OmpNone, OmpPreDetermined,
- OmpImplicit);
+ OmpImplicit, OmpDependObject);
using Flags = common::EnumSet<Flag, Flag_enumSize>;
const Scope &owner() const { return *owner_; }
diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
index 7c254ce673855a..8eb1fdb4709178 100644
--- a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
+++ b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
@@ -137,6 +137,8 @@ genDependKindAttr(fir::FirOpBuilder &firOpBuilder,
case omp::clause::Depend::TaskDependenceType::Mutexinoutset:
case omp::clause::Depend::TaskDependenceType::Inoutset:
case omp::clause::Depend::TaskDependenceType::Depobj:
+ case omp::clause::Depend::TaskDependenceType::Sink:
+ case omp::clause::Depend::TaskDependenceType::Source:
llvm_unreachable("unhandled parser task dependence type");
break;
}
diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp
index 9483f643acd55a..4fc910ce4c1e78 100644
--- a/flang/lib/Lower/OpenMP/Clauses.cpp
+++ b/flang/lib/Lower/OpenMP/Clauses.cpp
@@ -338,6 +338,27 @@ ReductionOperator makeReductionOperator(const parser::OmpReductionOperator &inp,
inp.u);
}
+clause::TaskDependenceType
+makeDepType(const parser::OmpTaskDependenceType &inp) {
+ switch (inp.v) {
+ case parser::OmpTaskDependenceType::Type::Depobj:
+ return clause::TaskDependenceType::Depobj;
+ case parser::OmpTaskDependenceType::Type::In:
+ return clause::TaskDependenceType::In;
+ case parser::OmpTaskDependenceType::Type::Inout:
+ return clause::TaskDependenceType::Inout;
+ // Inoutset // missing-in-parser
+ // Mutexinoutset // missing-in-parser
+ case parser::OmpTaskDependenceType::Type::Out:
+ return clause::TaskDependenceType::Out;
+ case parser::OmpTaskDependenceType::Type::Sink:
+ return clause::TaskDependenceType::Sink;
+ case parser::OmpTaskDependenceType::Type::Source:
+ return clause::TaskDependenceType::Source;
+ }
+ llvm_unreachable("Unexpected dependence type");
+}
+
// --------------------------------------------------------------------
// Actual clauses. Each T (where tomp::T exists in ClauseT) has its "make".
@@ -554,18 +575,6 @@ Depend make(const parser::OmpClause::Depend &inp,
// Iteration is the equivalent of parser::OmpDependSinkVec
using Iteration = Doacross::Vector::value_type; // LoopIterationT
- CLAUSET_ENUM_CONVERT( //
- convert1, parser::OmpTaskDependenceType::Type, Depend::TaskDependenceType,
- // clang-format off
- MS(In, In)
- MS(Out, Out)
- MS(Inout, Inout)
- // MS(, Mutexinoutset) // missing-in-parser
- // MS(, Inputset) // missing-in-parser
- // MS(, Depobj) // missing-in-parser
- // clang-format on
- );
-
return Depend{Fortran::common::visit( //
common::visitors{
// Doacross
@@ -602,7 +611,7 @@ Depend make(const parser::OmpClause::Depend &inp,
auto &&maybeIter = maybeApply(
[&](auto &&s) { return makeIterator(s, semaCtx); }, t0);
- return Depend::DepType{{/*TaskDependenceType=*/convert1(t1.v),
+ return Depend::DepType{{/*TaskDependenceType=*/makeDepType(t1),
/*Iterator=*/std::move(maybeIter),
/*LocatorList=*/makeObjects(t2, semaCtx)}};
},
@@ -614,8 +623,14 @@ Depend make(const parser::OmpClause::Depend &inp,
Destroy make(const parser::OmpClause::Destroy &inp,
semantics::SemanticsContext &semaCtx) {
- // inp -> empty
- llvm_unreachable("Empty: destroy");
+ // inp.v -> std::optional<OmpDestroyClause>
+ auto &&maybeObject = maybeApply(
+ [&](const parser::OmpDestroyClause &c) {
+ return makeObject(c.v, semaCtx);
+ },
+ inp.v);
+
+ return Destroy{/*DestroyVar=*/std::move(maybeObject)};
}
Detach make(const parser::OmpClause::Detach &inp,
@@ -1279,8 +1294,8 @@ Uniform make(const parser::OmpClause::Uniform &inp,
Update make(const parser::OmpClause::Update &inp,
semantics::SemanticsContext &semaCtx) {
- // inp -> empty
- return Update{/*TaskDependenceType=*/std::nullopt};
+ // inp.v -> parser::OmpUpdateClause
+ return Update{/*TaskDependenceType=*/makeDepType(inp.v.v)};
}
Use make(const parser::OmpClause::Use &inp,
diff --git a/flang/lib/Lower/OpenMP/Clauses.h b/flang/lib/Lower/OpenMP/Clauses.h
index 1e911a20468575..51180ebfe5745e 100644
--- a/flang/lib/Lower/OpenMP/Clauses.h
+++ b/flang/lib/Lower/OpenMP/Clauses.h
@@ -152,6 +152,7 @@ using IteratorSpecifier = tomp::type::IteratorSpecifierT<TypeTy, IdTy, ExprTy>;
using DefinedOperator = tomp::type::DefinedOperatorT<IdTy, ExprTy>;
using ProcedureDesignator = tomp::type::ProcedureDesignatorT<IdTy, ExprTy>;
using ReductionOperator = tomp::type::ReductionIdentifierT<IdTy, ExprTy>;
+using TaskDependenceType = tomp::type::TaskDependenceType;
// "Requires" clauses are handled early on, and the aggregated information
// is stored in the Symbol details of modules, programs, and subprograms.
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index 01a40d6e2204ef..954d6b8d122f46 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -2699,6 +2699,21 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
TODO(converter.getCurrentLocation(), "OpenMPCancelConstruct");
}
+static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
+ semantics::SemanticsContext &semaCtx,
+ lower::pft::Evaluation &eval,
+ const parser::OpenMPDepobjConstruct &construct) {
+ // These values will be ignored until the construct itself is implemented,
+ // but run them anyway for the sake of testing (via a Todo test).
+ auto &ompObj = std::get<parser::OmpObject>(construct.t);
+ const Object &depObj = makeObject(ompObj, semaCtx);
+ Clause clause = makeClause(std::get<parser::OmpClause>(construct.t), semaCtx);
+ (void)depObj;
+ (void)clause;
+
+ TODO(converter.getCurrentLocation(), "OpenMPDepobjConstruct");
+}
+
static void
genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval,
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index 598439cbee87e6..852898c6623dc6 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -366,9 +366,12 @@ TYPE_PARSER(
construct<OmpDependSinkVec>(name, maybe(Parser<OmpDependSinkVecLength>{})))
TYPE_PARSER(construct<OmpTaskDependenceType>(
+ "DEPOBJ" >> pure(OmpTaskDependenceType::Type::Depobj) ||
"IN"_id >> pure(OmpTaskDependenceType::Type::In) ||
"INOUT" >> pure(OmpTaskDependenceType::Type::Inout) ||
- "OUT" >> pure(OmpTaskDependenceType::Type::Out)))
+ "OUT" >> pure(OmpTaskDependenceType::Type::Out) ||
+ "SINK" >> pure(OmpTaskDependenceType::Type::Sink) ||
+ "SOURCE" >> pure(OmpTaskDependenceType::Type::Source)))
TYPE_CONTEXT_PARSER("Omp Depend clause"_en_US,
construct<OmpDependClause>(construct<OmpDependClause::Sink>(
@@ -454,6 +457,9 @@ TYPE_PARSER(
parenthesized(Parser<OmpDefaultmapClause>{}))) ||
"DEPEND" >> construct<OmpClause>(construct<OmpClause::Depend>(
parenthesized(Parser<OmpDependClause>{}))) ||
+ "DESTROY" >> construct<OmpClause>(construct<OmpClause::Destroy>(
+ maybe(parenthesized(construct<OmpDestroyClause>(
+ Parser<OmpObject>{}))))) ||
"DEVICE" >> construct<OmpClause>(construct<OmpClause::Device>(
parenthesized(Parser<OmpDeviceClause>{}))) ||
"DEVICE_TYPE" >> construct<OmpClause>(construct<OmpClause::DeviceType>(
@@ -560,7 +566,9 @@ TYPE_PARSER(
construct<OmpClause>(construct<OmpClause::UnifiedSharedMemory>()) ||
"UNIFORM" >> construct<OmpClause>(construct<OmpClause::Uniform>(
parenthesized(nonemptyList(name)))) ||
- "UNTIED" >> construct<OmpClause>(construct<OmpClause::Untied>()))
+ "UNTIED" >> construct<OmpClause>(construct<OmpClause::Untied>()) ||
+ "UPDATE" >> construct<OmpClause>(construct<OmpClause::Update>(
+ parenthesized(Parser<OmpTaskDependenceType>{}))))
// [Clause, [Clause], ...]
TYPE_PARSER(sourced(construct<OmpClauseList>(
@@ -673,6 +681,9 @@ TYPE_PARSER(sourced(construct<OmpAtomicClause>(
TYPE_PARSER(sourced(construct<OmpAtomicClauseList>(
many(maybe(","_tok) >> sourced(Parser<OmpAtomicClause>{})))))
+TYPE_PARSER(sourced(construct<OpenMPDepobjConstruct>(verbatim("DEPOBJ"_tok),
+ parenthesized(Parser<OmpObject>{}), sourced(Parser<OmpClause>{}))))
+
TYPE_PARSER(sourced(construct<OpenMPFlushConstruct>(verbatim("FLUSH"_tok),
many(maybe(","_tok) >> sourced(Parser<OmpMemoryOrderClause>{})),
maybe(parenthesized(Parser<OmpObjectList>{})))))
@@ -697,7 +708,8 @@ TYPE_PARSER(
construct<OpenMPStandaloneConstruct>(Parser<OpenMPFlushConstruct>{}) ||
construct<OpenMPStandaloneConstruct>(Parser<OpenMPCancelConstruct>{}) ||
construct<OpenMPStandaloneConstruct>(
- Parser<OpenMPCancellationPointConstruct>{})) /
+ Parser<OpenMPCancellationPointConstruct>{}) ||
+ construct<OpenMPStandaloneConstruct>(Parser<OpenMPDepobjConstruct>{})) /
endOfLine)
// Directives enclosing structured-block
diff --git a/flang/lib/Parser/parse-tree.cpp b/flang/lib/Parser/parse-tree.cpp
index 948ad04a091a8c..60aef1666e9ba7 100644
--- a/flang/lib/Parser/parse-tree.cpp
+++ b/flang/lib/Parser/parse-tree.cpp
@@ -252,6 +252,23 @@ CharBlock Variable::GetSource() const {
llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const Name &x) {
return os << x.ToString();
}
+
+OmpTaskDependenceType::Type OmpDependClause::GetDepType() const {
+ return common::visit(
+ common::visitors{
+ [&](const parser::OmpDependClause::Source &) {
+ return parser::OmpTaskDependenceType::Type::Source;
+ },
+ [&](const parser::OmpDependClause::Sink &) {
+ return parser::OmpTaskDependenceType::Type::Sink;
+ },
+ [&](const parser::OmpDependClause::InOut &y) {
+ return std::get<parser::OmpTaskDependenceType>(y.t).v;
+ },
+ },
+ u);
+}
+
} // namespace Fortran::parser
template <typename C> static llvm::omp::Clause getClauseIdForClass(C &&) {
diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index 39fcb61609e33b..32fe530e16f634 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -2215,11 +2215,9 @@ class UnparseVisitor {
Walk(std::get<std::optional<OmpDependSinkVecLength>>(x.t));
}
void Unparse(const OmpDependClause::InOut &x) {
- Put("(");
Walk(std::get<OmpTaskDependenceType>(x.t));
Put(":");
Walk(std::get<OmpObjectList>(x.t));
- Put(")");
}
bool Pre(const OmpDependClause &x) {
return common::visit(
@@ -2706,6 +2704,16 @@ class UnparseVisitor {
},
x.u);
}
+ void Unparse(const OpenMPDepobjConstruct &x) {
+ BeginOpenMP();
+ Word("!$OMP DEPOBJ");
+ Put("(");
+ Walk(std::get<OmpObject>(x.t));
+ Put(") ");
+ Walk(std::get<OmpClause>(x.t));
+ Put("\n");
+ EndOpenMP();
+ }
void Unparse(const OpenMPFlushConstruct &x) {
BeginOpenMP();
Word("!$OMP FLUSH ");
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 8f3eb9fefee678..64c2254b277502 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -1261,6 +1261,39 @@ void OmpStructureChecker::Leave(const parser::OpenMPDeclareSimdConstruct &) {
dirContext_.pop_back();
}
+void OmpStructureChecker::Enter(const parser::OpenMPDepobjConstruct &x) {
+ const auto &dir{std::get<parser::Verbatim>(x.t)};
+ PushContextAndClauseSets(dir.source, llvm::omp::Directive::OMPD_depobj);
+
+ // [5.2:73:27-28]
+ // If the destroy clause appears on a depobj construct, destroy-var must
+ // refer to the same depend object as the depobj argument of the construct.
+ auto &clause{std::get<parser::OmpClause>(x.t)};
+ if (clause.Id() == llvm::omp::Clause::OMPC_destroy) {
+ auto getSymbol = [&](const parser::OmpObject &obj) {
+ return common::visit(
+ [&](auto &&s) { return GetLastName(s).symbol; }, obj.u);
+ };
+
+ auto &wrapper{std::get<parser::OmpClause::Destroy>(clause.u)};
+ if (const std::optional<parser::OmpDestroyClause> &destroy{wrapper.v}) {
+ const Symbol *constrSym = getSymbol(std::get<parser::OmpObject>(x.t));
+ const Symbol *clauseSym = getSymbol(destroy->v);
+ assert(constrSym && "Unresolved depobj construct symbol");
+ assert(clauseSym && "Unresolved destroy symbol on depobj construct");
+ if (constrSym != clauseSym) {
+ context_.Say(x.source,
+ "The DESTROY clause must refer to the same object as the "
+ "DEPOBJ construct"_err_en_US);
+ }
+ }
+ }
+}
+
+void OmpStructureChecker::Leave(const parser::OpenMPDepobjConstruct &x) {
+ dirContext_.pop_back();
+}
+
void OmpStructureChecker::Enter(const parser::OpenMPRequiresConstruct &x) {
const auto &dir{std::get<parser::Verbatim>(x.t)};
PushContextAndClauseSets(dir.source, llvm::omp::Directive::OMPD_requires);
@@ -2476,7 +2509,6 @@ CHECK_SIMPLE_CLAUSE(Capture, OMPC_capture)
CHECK_SIMPLE_CLAUSE(Contains, OMPC_contains)
CHECK_SIMPLE_CLAUSE(Default, OMPC_default)
CHECK_SIMPLE_CLAUSE(Depobj, OMPC_depobj)
-CHECK_SIMPLE_CLAUSE(Destroy, OMPC_destroy)
CHECK_SIMPLE_CLAUSE(Detach, OMPC_detach)
CHECK_SIMPLE_CLAUSE(DeviceType, OMPC_device_type)
CHECK_SIMPLE_CLAUSE(DistSchedule, OMPC_dist_schedule)
@@ -2519,7 +2551,6 @@ CHECK_SIMPLE_CLAUSE(Uniform, OMPC_uniform)
CHECK_SIMPLE_CLAUSE(Unknown, OMPC_unknown)
CHECK_SIMPLE_CLAUSE(Untied, OMPC_untied)
CHECK_SIMPLE_CLAUSE(UsesAllocators, OMPC_uses_allocators)
-CHECK_SIMPLE_CLAUSE(Update, OMPC_update)
CHECK_SIMPLE_CLAUSE(Write, OMPC_write)
CHECK_SIMPLE_CLAUSE(Init, OMPC_init)
CHECK_SIMPLE_CLAUSE(Use, OMPC_use)
@@ -2555,6 +2586,22 @@ CHECK_REQ_CONSTANT_SCALAR_INT_CLAUSE(Simdlen, OMPC_simdlen)
// Restrictions specific to each clause are implemented apart from the
// generalized restrictions.
+
+void OmpStructureChecker::Enter(const parser::OmpClause::Destroy &x) {
+ CheckAllowedClause(llvm::omp::Clause::OMPC_destroy);
+
+ llvm::omp::Directive dir{GetContext().directive};
+ unsigned version{context_.langOptions().OpenMPVersion};
+ if (dir == llvm::omp::Directive::OMPD_depobj) {
+ if (version < 52) {
+ context_.Say(GetContext().clauseSource,
+ "The object parameter in DESTROY clause in DEPOPJ construct "
+ "was introduced in %s"_port_en_US,
+ ThisVersion(52));
+ }
+ }
+}
+
void OmpStructureChecker::Enter(const parser::OmpClause::Reduction &x) {
CheckAllowedClause(llvm::omp::Clause::OMPC_reduction);
if (CheckReductionOperators(x)) {
@@ -3285,16 +3332,63 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Device &x) {
void OmpStructureChecker::Enter(const parser::OmpClause::Depend &x) {
CheckAllowedClause(llvm::omp::Clause::OMPC_depend);
- if ((std::holds_alternative<parser::OmpDependClause::Source>(x.v.u) ||
- std::holds_alternative<parser::OmpDependClause::Sink>(x.v.u)) &&
- GetContext().directive != llvm::omp::OMPD_ordered) {
- context_.Say(GetContext().clauseSource,
- "DEPEND(SOURCE) or DEPEND(SINK : vec) can be used only with the ordered"
- " directive. Used here in the %s construct."_err_en_US,
- parser::ToUpperCaseLetters(getDirectiveName(GetContext().directive)));
+ llvm::omp::Directive directive{GetContext().directive};
+ unsigned version{context_.langOptions().OpenMPVersion};
+
+ using DepType = parser::OmpTaskDependenceType::Type;
+ DepType depType = x.v.GetDepType();
+
+ if (version >= 52) {
+ switch (depType) {
+ case DepType::Sink:
+ case DepType::Source:
+ context_.Say(GetContext().clauseSource,
+ "The %s task-dependence-type is deprecated in %s"_warn_en_US,
+ parser::ToUpperCaseLetters(
+ parser::OmpTaskDependenceType::EnumToString(depType)),
+ ThisVersion(version));
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (directive == llvm::omp::OMPD_depobj) {
+ // [5.0:255:11], [5.1:288:3]
+ // A depend clause on a depobj construct must not have source, sink [or
+ // depobj](5.0) as dependence-type.
+ if (version >= 50) {
+ bool invalidDep{depType == DepType::Source || depType == DepType::Sink};
+ if (version == 50) {
+ invalidDep = invalidDep || depType == DepType::Depobj;
+ }
+ if (invalidDep) {
+ context_.Say(GetContext().clauseSource,
+ "A DEPEND clause on a DEPOBJ construct must not have SOURCE%s "
+ "as dependence-type"_err_en_US,
+ version == 50 ? ", SINK or DEPOBJ" : " or SINK");
+ }
+ }
+ } else if (directive != llvm::omp::OMPD_ordered) {
+ if (depType == DepType::Source || depType == DepType::Sink) {
+ context_.Say(GetContext().clauseSource,
+ "DEPEND(SOURCE) or DEPEND(SINK : vec) can be used only with the "
+ "ordered directive. Used here in the %s construct."_err_en_US,
+ parser::ToUpperCaseLetters(getDirectiveName(directive)));
+ }
}
if (const auto *inOut{std::get_if<parser::OmpDependClause::InOut>(&x.v.u)}) {
- for (const auto &object : std::get<parser::OmpObjectList>(inOut->t).v) {
+ auto &objList{std::get<parser::OmpObjectList>(inOut->t)};
+ if (directive == llvm::omp::OMPD_depobj) {
+ // [5.0:255:13], [5.1:288:6], [5.2:322:26]
+ // A depend clause on a depobj construct must only specify one locator.
+ if (objList.v.size() != 1) {
+ context_.Say(GetContext().clauseSource,
+ "A DEPEND clause on a DEPOBJ construct must only specify "
+ "one locator"_err_en_US);
+ }
+ }
+ for (const auto &object : objList.v) {
if (const auto *name{std::get_if<parser::Name>(&object.u)}) {
context_.Say(GetContext().clauseSource,
"Common block name ('%s') cannot appear in a DEPEND "
@@ -3313,12 +3407,18 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Depend &x) {
}
}
if (std::get<std::optional<parser::OmpIteratorModifier>>(inOut->t)) {
- unsigned version{context_.langOptions().OpenMPVersion};
unsigned allowedInVersion{50};
if (version < allowedInVersion) {
context_.Say(GetContext().clauseSource,
"Iterator modifiers are not supported in %s, %s"_warn_en_US,
ThisVersion(version), TryVersion(allowedInVersion));
+ } else {
+ if (directive == llvm::omp::OMPD_depobj) {
+ context_.Say(GetContext().clauseSource,
+ "An iterator-modifier may specify multiple locators, "
+ "a DEPEND clause on a DEPOBJ construct must only specify "
+ "one locator"_warn_en_US);
+ }
}
}
}
@@ -3433,6 +3533,34 @@ void OmpStructureChecker::CheckStructureElement(
return;
}
+void OmpStructureChecker::Enter(const parser::OmpClause::Update &x) {
+ CheckAllowedClause(llvm::omp::Clause::OMPC_update);
+ llvm::omp::Directive directive{GetContext().directive};
+ unsigned version{context_.langOptions().OpenMPVersion};
+
+ // [5.1:288:4-5]
+ // An update clause on a depobj construct must not have source, sink or depobj
+ // as dependence-type.
+ // [5.2:322:3]
+ // task-dependence-type must not be depobj.
+ if (directive == llvm::omp::OMPD_depobj) {
+ if (version >= 51) {
+ // Update -> OmpUpdateClause -> OmpTaskDependenceType -> Type
+ switch (x.v.v.v) {
+ case parser::OmpTaskDependenceType::Type::Source:
+ case parser::OmpTaskDependenceType::Type::Sink:
+ case parser::OmpTaskDependenceType::Type::Depobj:
+ context_.Say(GetContext().clauseSource,
+ "An UPDATE clause on a DEPOBJ construct must not have SOURCE, "
+ "SINK or DEPOBJ as dependence-type"_err_en_US);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
+
void OmpStructureChecker::Enter(const parser::OmpClause::UseDevicePtr &x) {
CheckStructureElement(x.v, llvm::omp::Clause::OMPC_use_device_ptr);
CheckAllowedClause(llvm::omp::Clause::OMPC_use_device_ptr);
@@ -3616,7 +3744,7 @@ void OmpStructureChecker::CheckDependList(const parser::DataRef &d) {
context_.Say(GetContext().clauseSource,
"Coarrays are not supported in DEPEND clause"_err_en_US);
},
- [&](const parser::Name &) { return; },
+ [&](const parser::Name &) {},
},
d.u);
}
diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index 237569bc40c483..d5fd558cea2372 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -92,6 +92,8 @@ class OmpStructureChecker
void Leave(const parser::OpenMPDeclarativeAllocate &);
void Enter(const parser::OpenMPDeclareTargetConstruct &);
void Leave(const parser::OpenMPDeclareTargetConstruct &);
+ void Enter(const parser::OpenMPDepobjConstruct &);
+ void Leave(const parser::OpenMPDepobjConstruct &);
void Enter(const parser::OmpDeclareTargetWithList &);
void Enter(const parser::OmpDeclareTargetWithClause &);
void Leave(const parser::OmpDeclareTargetWithClause &);
diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index 014b7987a658bd..d85109fc9cda83 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -383,6 +383,14 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
}
void Post(const parser::OpenMPDeclareSimdConstruct &) { PopContext(); }
+ bool Pre(const parser::OpenMPDepobjConstruct &x) {
+ PushContext(x.source, llvm::omp::Directive::OMPD_depobj);
+ auto &object{std::get<parser::OmpObject>(x.t)};
+ ResolveOmpObject(object, Symbol::Flag::OmpDependObject);
+ return true;
+ }
+ void Post(const parser::OpenMPDepobjConstruct &) { PopContext(); }
+
bool Pre(const parser::OpenMPRequiresConstruct &x) {
using Flags = WithOmpDeclarative::RequiresFlags;
using Requires = WithOmpDeclarative::RequiresFlag;
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index add4e4befd3a2b..e0a8246ebc752e 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -1538,6 +1538,13 @@ class OmpVisitor : public virtual DeclarationVisitor {
void Post(const parser::OpenMPDeclarativeConstruct &) {
messageHandler().set_currStmtSource(std::nullopt);
}
+ bool Pre(const parser::OpenMPDepobjConstruct &x) {
+ AddOmpSourceRange(x.source);
+ return true;
+ }
+ void Post(const parser::OpenMPDepobjConstruct &x) {
+ messageHandler().set_currStmtSource(std::nullopt);
+ }
bool Pre(const parser::OpenMPAtomicConstruct &x) {
return common::visit(common::visitors{[&](const auto &u) -> bool {
AddOmpSourceRange(u.source);
diff --git a/flang/test/Lower/OpenMP/Todo/depobj-construct.f90 b/flang/test/Lower/OpenMP/Todo/depobj-construct.f90
new file mode 100644
index 00000000000000..2b3c4d92c4a4f8
--- /dev/null
+++ b/flang/test/Lower/OpenMP/Todo/depobj-construct.f90
@@ -0,0 +1,9 @@
+!RUN: %not_todo_cmd bbc -emit-hlfir -fopenmp -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s
+!RUN: %not_todo_cmd %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s
+
+!CHECK: not yet implemented: OpenMPDepobjConstruct
+subroutine f00()
+ integer :: obj
+ integer :: x
+ !$omp depobj(obj) depend(in: x)
+end
diff --git a/flang/test/Parser/OpenMP/depobj-construct.f90 b/flang/test/Parser/OpenMP/depobj-construct.f90
new file mode 100644
index 00000000000000..7c474071bc1e67
--- /dev/null
+++ b/flang/test/Parser/OpenMP/depobj-construct.f90
@@ -0,0 +1,64 @@
+!RUN: %flang_fc1 -fdebug-unparse -fopenmp -fopenmp-version=52 %s | FileCheck --ignore-case --check-prefix="UNPARSE" %s
+!RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp -fopenmp-version=52 %s | FileCheck --check-prefix="PARSE-TREE" %s
+
+subroutine f00
+ integer :: x, y
+ !$omp depobj(x) depend(in: y)
+end
+
+!UNPARSE: SUBROUTINE f00
+!UNPARSE: INTEGER x, y
+!UNPARSE: !$OMP DEPOBJ(x) DEPEND(IN:y)
+!UNPARSE: END SUBROUTINE
+
+!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPDepobjConstruct
+!PARSE-TREE: | Verbatim
+!PARSE-TREE: | OmpObject -> Designator -> DataRef -> Name = 'x'
+!PARSE-TREE: | OmpClause -> Depend -> OmpDependClause -> InOut
+!PARSE-TREE: | | OmpTaskDependenceType -> Type = In
+!PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'y'
+
+subroutine f01
+ integer :: x
+ !$omp depobj(x) update(out)
+end
+
+!UNPARSE: SUBROUTINE f01
+!UNPARSE: INTEGER x
+!UNPARSE: !$OMP DEPOBJ(x) UPDATE(OUT)
+!UNPARSE: END SUBROUTINE
+
+!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPDepobjConstruct
+!PARSE-TREE: | Verbatim
+!PARSE-TREE: | OmpObject -> Designator -> DataRef -> Name = 'x'
+!PARSE-TREE: | OmpClause -> Update -> OmpUpdateClause -> OmpTaskDependenceType -> Type = Out
+
+subroutine f02
+ integer :: x
+ !$omp depobj(x) destroy(x)
+end
+
+!UNPARSE: SUBROUTINE f02
+!UNPARSE: INTEGER x
+!UNPARSE: !$OMP DEPOBJ(x) DESTROY(x)
+!UNPARSE: END SUBROUTINE
+
+!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPDepobjConstruct
+!PARSE-TREE: | Verbatim
+!PARSE-TREE: | OmpObject -> Designator -> DataRef -> Name = 'x'
+!PARSE-TREE: | OmpClause -> Destroy -> OmpDestroyClause -> OmpObject -> Designator -> DataRef -> Name = 'x'
+
+subroutine f03
+ integer :: x
+ !$omp depobj(x) destroy
+end
+
+!UNPARSE: SUBROUTINE f03
+!UNPARSE: INTEGER x
+!UNPARSE: !$OMP DEPOBJ(x) DESTROY
+!UNPARSE: END SUBROUTINE
+
+!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPDepobjConstruct
+!PARSE-TREE: | Verbatim
+!PARSE-TREE: | OmpObject -> Designator -> DataRef -> Name = 'x'
+!PARSE-TREE: | OmpClause -> Destroy ->
diff --git a/flang/test/Semantics/OpenMP/depobj-construct-v50.f90 b/flang/test/Semantics/OpenMP/depobj-construct-v50.f90
new file mode 100644
index 00000000000000..e7fa24d521b63b
--- /dev/null
+++ b/flang/test/Semantics/OpenMP/depobj-construct-v50.f90
@@ -0,0 +1,28 @@
+!RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=50
+
+subroutine f00
+ integer :: obj
+!ERROR: A DEPEND clause on a DEPOBJ construct must not have SOURCE, SINK or DEPOBJ as dependence-type
+ !$omp depobj(obj) depend(source)
+end
+
+subroutine f01
+ integer :: obj
+ integer :: x, y
+!ERROR: A DEPEND clause on a DEPOBJ construct must only specify one locator
+ !$omp depobj(obj) depend(in: x, y)
+end
+
+subroutine f02
+ integer :: obj
+ integer :: x(10)
+!WARNING: An iterator-modifier may specify multiple locators, a DEPEND clause on a DEPOBJ construct must only specify one locator
+ !$omp depobj(obj) depend(iterator(i = 1:10), in: x(i))
+end
+
+subroutine f03
+ integer :: obj, jbo
+!ERROR: The DESTROY clause must refer to the same object as the DEPOBJ construct
+!PORTABILITY: The object parameter in DESTROY clause in DEPOPJ construct was introduced in OpenMP v5.2
+ !$omp depobj(obj) destroy(jbo)
+end
diff --git a/flang/test/Semantics/OpenMP/depobj-construct-v51.f90 b/flang/test/Semantics/OpenMP/depobj-construct-v51.f90
new file mode 100644
index 00000000000000..fa0c025a110100
--- /dev/null
+++ b/flang/test/Semantics/OpenMP/depobj-construct-v51.f90
@@ -0,0 +1,13 @@
+!RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=51
+
+subroutine f04
+ integer :: obj
+!ERROR: An UPDATE clause on a DEPOBJ construct must not have SOURCE, SINK or DEPOBJ as dependence-type
+ !$omp depobj(obj) update(source)
+end
+
+subroutine f05
+ integer :: obj
+!ERROR: An UPDATE clause on a DEPOBJ construct must not have SOURCE, SINK or DEPOBJ as dependence-type
+ !$omp depobj(obj) update(depobj)
+end
diff --git a/flang/test/Semantics/OpenMP/depobj-construct-v52.f90 b/flang/test/Semantics/OpenMP/depobj-construct-v52.f90
new file mode 100644
index 00000000000000..f2e66485c6c801
--- /dev/null
+++ b/flang/test/Semantics/OpenMP/depobj-construct-v52.f90
@@ -0,0 +1,15 @@
+!RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=52
+
+subroutine f00
+ integer :: obj
+!WARNING: The SOURCE task-dependence-type is deprecated in OpenMP v5.2
+!ERROR: A DEPEND clause on a DEPOBJ construct must not have SOURCE or SINK as dependence-type
+ !$omp depobj(obj) depend(source)
+end
+
+subroutine f03
+ integer :: obj, jbo
+!Note: no portability message
+!ERROR: The DESTROY clause must refer to the same object as the DEPOBJ construct
+ !$omp depobj(obj) destroy(jbo)
+end
diff --git a/llvm/include/llvm/Frontend/OpenMP/ClauseT.h b/llvm/include/llvm/Frontend/OpenMP/ClauseT.h
index 2a890905dc6323..8ff15b51f1abdf 100644
--- a/llvm/include/llvm/Frontend/OpenMP/ClauseT.h
+++ b/llvm/include/llvm/Frontend/OpenMP/ClauseT.h
@@ -239,7 +239,8 @@ struct MapperT {
ENUM(MemoryOrder, AcqRel, Acquire, Relaxed, Release, SeqCst);
ENUM(MotionExpectation, Present);
// V5.2: [15.9.1] `task-dependence-type` modifier
-ENUM(TaskDependenceType, In, Out, Inout, Mutexinoutset, Inoutset, Depobj);
+ENUM(TaskDependenceType, Depobj, In, Inout, Inoutset, Mutexinoutset, Out, Sink,
+ Source);
template <typename I, typename E> //
struct LoopIterationT {
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td
index 70179bab475779..97496d4aae5ae2 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMP.td
+++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td
@@ -130,6 +130,8 @@ def OMPC_Depobj : Clause<"depobj"> {
}
def OMPC_Destroy : Clause<"destroy"> {
let clangClass = "OMPDestroyClause";
+ let flangClass = "OmpDestroyClause";
+ let isValueOptional = true;
}
def OMPC_Detach : Clause<"detach"> {
let clangClass = "OMPDetachClause";
@@ -481,6 +483,7 @@ def OMPC_Untied : Clause<"untied"> {
}
def OMPC_Update : Clause<"update"> {
let clangClass = "OMPUpdateClause";
+ let flangClass = "OmpUpdateClause";
}
def OMPC_Use : Clause<"use"> {
let clangClass = "OMPUseClause";
More information about the llvm-commits
mailing list