-
Notifications
You must be signed in to change notification settings - Fork 15.1k
[flang][OpenMP] Use OmpDirectiveSpecification in ALLOCATE #165865
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
Conversation
For ALLOCATORS and executable ALLOCATE first perform list item checks in the context of an individual ALLOCATE clause or directive respectively, then perform "global" checks, e.g. whether all list items are present on the ALLOCATE statement. These changes allowed to simplify the checks for presence on ALLOCATE statement and the use of a predefined allocator. Additionally, allow variable list item lists to be empty, add a test for the related spec restriction. This is a first step towards unifying OpenMPDeclarativeAllocate and OpenMPExecutableAllocate into a single directive.
The ALLOCATE directive has two forms:
- A declarative form with a standalone directive:
!$OMP ALLOCATE (variable-list-item...)
- An executable form that consists of several diretives followed by an
ALLOCATE statement:
!$OMP ALLOCATE (variable-list-item...)
!$OMP ALLOCATE (variable-list-item...)
...
ALLOCATE (...)
The second form was deprecated in OpenMP 5.2 in favor of the ALLOCATORS
construct.
Since in the parse tree every type corresponding to a directive only
corresponds to a single directive, the executable form is represented by
a sequence of nested OmpAlocateDirectives, e.g.
!$OMP ALLOCATE(x)
!$OMP ALLOCATE(y)
ALLOCATE(x, y)
will become
OmpAllocateDirective
|- ALLOCATE(x) // begin directive
`- OmpAllocateDirective // block
|- ALLOCATE(y) // begin directive
`- ALLOCATE(x, y) // block
With this change all AST nodes for directives use OmpDirectiveSpecification
as the directive representation.
|
@llvm/pr-subscribers-flang-parser @llvm/pr-subscribers-flang-semantics Author: Krzysztof Parzyszek (kparzysz) ChangesThe ALLOCATE directive has two forms:
The second form was deprecated in OpenMP 5.2 in favor of the ALLOCATORS construct. Since in the parse tree every type corresponding to a directive only corresponds to a single directive, the executable form is represented by a sequence of nested OmpAlocateDirectives, e.g. will become With this change all AST nodes for directives use OmpDirectiveSpecification as the directive representation. Patch is 69.27 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/165865.diff 27 Files Affected:
diff --git a/flang/examples/FeatureList/FeatureList.cpp b/flang/examples/FeatureList/FeatureList.cpp
index 225a6558ef956..ef58da61e371b 100644
--- a/flang/examples/FeatureList/FeatureList.cpp
+++ b/flang/examples/FeatureList/FeatureList.cpp
@@ -445,6 +445,7 @@ struct NodeVisitor {
READ_FEATURE(ObjectDecl)
READ_FEATURE(OldParameterStmt)
READ_FEATURE(OmpAlignedClause)
+ READ_FEATURE(OmpAllocateDirective)
READ_FEATURE(OmpBeginDirective)
READ_FEATURE(OmpBeginLoopDirective)
READ_FEATURE(OmpBeginSectionsDirective)
@@ -541,7 +542,6 @@ struct NodeVisitor {
READ_FEATURE(OpenMPCancellationPointConstruct)
READ_FEATURE(OpenMPConstruct)
READ_FEATURE(OpenMPCriticalConstruct)
- READ_FEATURE(OpenMPDeclarativeAllocate)
READ_FEATURE(OpenMPDeclarativeConstruct)
READ_FEATURE(OpenMPDeclareReductionConstruct)
READ_FEATURE(OpenMPDeclareSimdConstruct)
@@ -550,7 +550,6 @@ struct NodeVisitor {
READ_FEATURE(OmpAtomicDefaultMemOrderClause)
READ_FEATURE(OpenMPFlushConstruct)
READ_FEATURE(OpenMPLoopConstruct)
- READ_FEATURE(OpenMPExecutableAllocate)
READ_FEATURE(OpenMPAllocatorsConstruct)
READ_FEATURE(OpenMPRequiresConstruct)
READ_FEATURE(OpenMPSimpleStandaloneConstruct)
diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h
index a7398a4ef970f..de2716410d6cd 100644
--- a/flang/include/flang/Parser/dump-parse-tree.h
+++ b/flang/include/flang/Parser/dump-parse-tree.h
@@ -512,6 +512,7 @@ class ParseTreeDumper {
NODE(parser, OmpAlignModifier)
NODE(parser, OmpAllocateClause)
NODE(OmpAllocateClause, Modifier)
+ NODE(parser, OmpAllocateDirective)
NODE(parser, OmpAllocatorComplexModifier)
NODE(parser, OmpAllocatorSimpleModifier)
NODE(parser, OmpAlwaysModifier)
@@ -739,7 +740,6 @@ class ParseTreeDumper {
NODE(parser, OpenMPCancellationPointConstruct)
NODE(parser, OpenMPConstruct)
NODE(parser, OpenMPCriticalConstruct)
- NODE(parser, OpenMPDeclarativeAllocate)
NODE(parser, OpenMPDeclarativeAssumes)
NODE(parser, OpenMPDeclarativeConstruct)
NODE(parser, OpenMPDeclareMapperConstruct)
@@ -748,7 +748,6 @@ class ParseTreeDumper {
NODE(parser, OpenMPDeclareTargetConstruct)
NODE(parser, OpenMPDepobjConstruct)
NODE(parser, OpenMPDispatchConstruct)
- NODE(parser, OpenMPExecutableAllocate)
NODE(parser, OpenMPFlushConstruct)
NODE(parser, OpenMPGroupprivate)
NODE(parser, OpenMPLoopConstruct)
diff --git a/flang/include/flang/Parser/openmp-utils.h b/flang/include/flang/Parser/openmp-utils.h
index 49db091af93a7..8fa4a84aff06d 100644
--- a/flang/include/flang/Parser/openmp-utils.h
+++ b/flang/include/flang/Parser/openmp-utils.h
@@ -22,6 +22,7 @@
#include <type_traits>
#include <utility>
#include <variant>
+#include <vector>
namespace Fortran::parser::omp {
@@ -33,23 +34,6 @@ template <typename T> constexpr auto addr_if(const std::optional<T> &x) {
}
namespace detail {
-using D = llvm::omp::Directive;
-
-template <typename Construct> //
-struct ConstructId {
- static constexpr llvm::omp::Directive id{D::OMPD_unknown};
-};
-
-#define MAKE_CONSTR_ID(Construct, Id) \
- template <> struct ConstructId<Construct> { \
- static constexpr llvm::omp::Directive id{Id}; \
- }
-
-MAKE_CONSTR_ID(OpenMPDeclarativeAllocate, D::OMPD_allocate);
-MAKE_CONSTR_ID(OpenMPExecutableAllocate, D::OMPD_allocate);
-
-#undef MAKE_CONSTR_ID
-
struct DirectiveNameScope {
static OmpDirectiveName MakeName(CharBlock source = {},
llvm::omp::Directive id = llvm::omp::Directive::OMPD_unknown) {
@@ -97,9 +81,6 @@ struct DirectiveNameScope {
} else if constexpr (TupleTrait<T>) {
if constexpr (std::is_base_of_v<OmpBlockConstruct, T>) {
return std::get<OmpBeginDirective>(x.t).DirName();
- } else if constexpr (std::is_same_v<T, OpenMPDeclarativeAllocate> ||
- std::is_same_v<T, OpenMPExecutableAllocate>) {
- return MakeName(std::get<Verbatim>(x.t).source, ConstructId<T>::id);
} else {
return GetFromTuple(
x.t, std::make_index_sequence<std::tuple_size_v<decltype(x.t)>>{});
@@ -139,6 +120,9 @@ template <typename T> OmpDirectiveName GetOmpDirectiveName(const T &x) {
return detail::DirectiveNameScope::GetOmpDirectiveName(x);
}
+const OpenMPDeclarativeConstruct *GetOmp(const DeclarationConstruct &x);
+const OpenMPConstruct *GetOmp(const ExecutionPartConstruct &x);
+
const OmpObjectList *GetOmpObjectList(const OmpClause &clause);
template <typename T>
@@ -158,6 +142,13 @@ const OmpCombinerExpression *GetCombinerExpr(
const OmpReductionSpecifier &rspec);
const OmpInitializerExpression *GetInitializerExpr(const OmpClause &init);
+struct OmpAllocateInfo {
+ std::vector<const OmpAllocateDirective *> dirs;
+ const ExecutionPartConstruct *body{nullptr};
+};
+
+OmpAllocateInfo SplitOmpAllocate(const OmpAllocateDirective &x);
+
} // namespace Fortran::parser::omp
#endif // FORTRAN_PARSER_OPENMP_UTILS_H
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index 4dd5e84f60dfe..8c7578f7a1941 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -5151,17 +5151,42 @@ struct OpenMPThreadprivate {
CharBlock source;
};
-// 2.11.3 allocate -> ALLOCATE (variable-name-list) [clause]
-struct OpenMPDeclarativeAllocate {
- TUPLE_CLASS_BOILERPLATE(OpenMPDeclarativeAllocate);
- CharBlock source;
- std::tuple<Verbatim, std::optional<OmpObjectList>, OmpClauseList> t;
+// Ref: [4.5:310-312], [5.0:156-158], [5.1:181-184], [5.2:176-177],
+// [6.0:310-312]
+//
+// allocate-directive ->
+// ALLOCATE (variable-list-item...) | // since 4.5
+// ALLOCATE (variable-list-item...) // since 5.0, until 5.1
+// ...
+// allocate-stmt
+//
+// The first form is the "declarative-allocate", and is a declarative
+// directive. The second is the "executable-allocate" and is an executable
+// directive. The executable form was deprecated in 5.2.
+//
+// The executable-allocate consists of several ALLOCATE directives. Since
+// in the parse tree every type corresponding to a directive only corresponds
+// to a single directive, the executable form is represented by a sequence
+// of nested OmpAlocateDirectives, e.g.
+// !$OMP ALLOCATE(x)
+// !$OMP ALLOCATE(y)
+// ALLOCATE(x, y)
+// will become
+// OmpAllocateDirective
+// |- ALLOCATE(x) // begin directive
+// `- OmpAllocateDirective // block
+// |- ALLOCATE(y) // begin directive
+// `- ALLOCATE(x, y) // block
+//
+// The block in the declarative-allocate will be empty.
+struct OmpAllocateDirective : public OmpBlockConstruct {
+ INHERITED_TUPLE_CLASS_BOILERPLATE(OmpAllocateDirective, OmpBlockConstruct);
};
struct OpenMPDeclarativeConstruct {
UNION_CLASS_BOILERPLATE(OpenMPDeclarativeConstruct);
CharBlock source;
- std::variant<OpenMPDeclarativeAllocate, OpenMPDeclarativeAssumes,
+ std::variant<OmpAllocateDirective, OpenMPDeclarativeAssumes,
OpenMPDeclareMapperConstruct, OpenMPDeclareReductionConstruct,
OpenMPDeclareSimdConstruct, OpenMPDeclareTargetConstruct,
OmpDeclareVariantDirective, OpenMPGroupprivate, OpenMPThreadprivate,
@@ -5174,19 +5199,6 @@ struct OpenMPCriticalConstruct : public OmpBlockConstruct {
INHERITED_TUPLE_CLASS_BOILERPLATE(OpenMPCriticalConstruct, OmpBlockConstruct);
};
-// 2.11.3 allocate -> ALLOCATE [(variable-name-list)] [clause]
-// [ALLOCATE (variable-name-list) [clause] [...]]
-// allocate-statement
-// clause -> allocator-clause
-struct OpenMPExecutableAllocate {
- TUPLE_CLASS_BOILERPLATE(OpenMPExecutableAllocate);
- CharBlock source;
- std::tuple<Verbatim, std::optional<OmpObjectList>, OmpClauseList,
- std::optional<std::list<OpenMPDeclarativeAllocate>>,
- Statement<AllocateStmt>>
- t;
-};
-
// Ref: [5.2:180-181], [6.0:315]
//
// allocators-construct ->
@@ -5342,9 +5354,9 @@ struct OpenMPConstruct {
UNION_CLASS_BOILERPLATE(OpenMPConstruct);
std::variant<OpenMPStandaloneConstruct, OpenMPSectionsConstruct,
OpenMPSectionConstruct, OpenMPLoopConstruct, OmpBlockConstruct,
- OpenMPAtomicConstruct, OpenMPDeclarativeAllocate, OpenMPDispatchConstruct,
- OpenMPUtilityConstruct, OpenMPExecutableAllocate,
- OpenMPAllocatorsConstruct, OpenMPAssumeConstruct, OpenMPCriticalConstruct>
+ OpenMPAtomicConstruct, OmpAllocateDirective, OpenMPDispatchConstruct,
+ OpenMPUtilityConstruct, OpenMPAllocatorsConstruct, OpenMPAssumeConstruct,
+ OpenMPCriticalConstruct>
u;
};
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index 71067283d13f7..b901f24ae366e 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -3506,9 +3506,9 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
static void
genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval,
- const parser::OpenMPDeclarativeAllocate &declarativeAllocate) {
+ const parser::OmpAllocateDirective &allocate) {
if (!semaCtx.langOptions().OpenMPSimd)
- TODO(converter.getCurrentLocation(), "OpenMPDeclarativeAllocate");
+ TODO(converter.getCurrentLocation(), "OmpAllocateDirective");
}
static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
@@ -3899,14 +3899,6 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
TODO(converter.getCurrentLocation(), "OpenMPDispatchConstruct");
}
-static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
- semantics::SemanticsContext &semaCtx,
- lower::pft::Evaluation &eval,
- const parser::OpenMPExecutableAllocate &execAllocConstruct) {
- if (!semaCtx.langOptions().OpenMPSimd)
- TODO(converter.getCurrentLocation(), "OpenMPExecutableAllocate");
-}
-
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 a9de26ea09ff8..4374acbbe51bf 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -1778,6 +1778,31 @@ struct OmpBlockConstructParser {
llvm::omp::Directive dir_;
};
+struct OmpDeclarativeAllocateParser {
+ using resultType = OmpAllocateDirective;
+
+ std::optional<resultType> Parse(ParseState &state) const {
+ constexpr llvm::omp::Directive dir{llvm::omp::Directive::OMPD_allocate};
+ if (auto &&begin{attempt(OmpBeginDirectiveParser(dir)).Parse(state)}) {
+ Block empty;
+ auto end{maybe(OmpEndDirectiveParser{dir}).Parse(state)};
+ return OmpAllocateDirective{std::move(*begin), std::move(empty),
+ llvm::transformOptional(std::move(*end),
+ [](auto &&s) { return OmpEndDirective(std::move(s)); })};
+ }
+ return std::nullopt;
+ }
+};
+
+struct OmpExecutableAllocateParser {
+ using resultType = OmpAllocateDirective;
+
+ std::optional<resultType> Parse(ParseState &state) const {
+ OmpStatementConstructParser p{llvm::omp::Directive::OMPD_allocate};
+ return construct<OmpAllocateDirective>(p).Parse(state);
+ }
+};
+
TYPE_PARSER(sourced(construct<OpenMPAllocatorsConstruct>(
OmpStatementConstructParser{llvm::omp::Directive::OMPD_allocators})))
@@ -2044,14 +2069,6 @@ TYPE_PARSER(construct<OmpInitializerExpression>(OmpStylizedExpressionParser{}))
TYPE_PARSER(sourced(construct<OpenMPCriticalConstruct>(
OmpBlockConstructParser{llvm::omp::Directive::OMPD_critical})))
-// 2.11.3 Executable Allocate directive
-TYPE_PARSER(sourced(construct<OpenMPExecutableAllocate>(
- verbatim("ALLOCATE"_tok), maybe(parenthesized(Parser<OmpObjectList>{})),
- Parser<OmpClauseList>{},
- maybe(nonemptyList(startOmpLine >> Parser<OpenMPDeclarativeAllocate>{})) /
- endOmpLine,
- statement(allocateStmt))))
-
// 2.8.2 Declare Simd construct
TYPE_PARSER(sourced(construct<OpenMPDeclareSimdConstruct>(
predicated(Parser<OmpDirectiveName>{},
@@ -2077,13 +2094,6 @@ TYPE_PARSER(sourced( //
IsDirective(llvm::omp::Directive::OMPD_threadprivate)) >=
Parser<OmpDirectiveSpecification>{})))
-// 2.11.3 Declarative Allocate directive
-TYPE_PARSER(
- sourced(construct<OpenMPDeclarativeAllocate>(verbatim("ALLOCATE"_tok),
- maybe(parenthesized(Parser<OmpObjectList>{})),
- Parser<OmpClauseList>{})) /
- lookAhead(endOmpLine / !statement(allocateStmt)))
-
// Assumes Construct
TYPE_PARSER(sourced(construct<OpenMPDeclarativeAssumes>(
predicated(OmpDirectiveNameParser{},
@@ -2106,7 +2116,7 @@ TYPE_PARSER(
construct<OpenMPDeclarativeConstruct>(
Parser<OmpDeclareVariantDirective>{}) ||
construct<OpenMPDeclarativeConstruct>(
- Parser<OpenMPDeclarativeAllocate>{}) ||
+ sourced(OmpDeclarativeAllocateParser{})) ||
construct<OpenMPDeclarativeConstruct>(
Parser<OpenMPGroupprivate>{}) ||
construct<OpenMPDeclarativeConstruct>(
@@ -2194,6 +2204,8 @@ TYPE_CONTEXT_PARSER("OpenMP construct"_en_US,
withMessage("expected OpenMP construct"_err_en_US,
first(construct<OpenMPConstruct>(Parser<OpenMPSectionsConstruct>{}),
construct<OpenMPConstruct>(Parser<OpenMPLoopConstruct>{}),
+ construct<OpenMPConstruct>(
+ sourced(OmpExecutableAllocateParser{})),
construct<OpenMPConstruct>(Parser<OmpBlockConstruct>{}),
// OmpBlockConstruct is attempted before
// OpenMPStandaloneConstruct to resolve !$OMP ORDERED
@@ -2201,9 +2213,7 @@ TYPE_CONTEXT_PARSER("OpenMP construct"_en_US,
construct<OpenMPConstruct>(Parser<OpenMPAtomicConstruct>{}),
construct<OpenMPConstruct>(Parser<OpenMPUtilityConstruct>{}),
construct<OpenMPConstruct>(Parser<OpenMPDispatchConstruct>{}),
- construct<OpenMPConstruct>(Parser<OpenMPExecutableAllocate>{}),
construct<OpenMPConstruct>(Parser<OpenMPAllocatorsConstruct>{}),
- construct<OpenMPConstruct>(Parser<OpenMPDeclarativeAllocate>{}),
construct<OpenMPConstruct>(Parser<OpenMPAssumeConstruct>{}),
construct<OpenMPConstruct>(Parser<OpenMPCriticalConstruct>{}))))
diff --git a/flang/lib/Parser/openmp-utils.cpp b/flang/lib/Parser/openmp-utils.cpp
index 95ad3f60770f5..b9d3763cdd06d 100644
--- a/flang/lib/Parser/openmp-utils.cpp
+++ b/flang/lib/Parser/openmp-utils.cpp
@@ -22,6 +22,25 @@
namespace Fortran::parser::omp {
+const OpenMPDeclarativeConstruct *GetOmp(const DeclarationConstruct &x) {
+ if (auto *y = std::get_if<SpecificationConstruct>(&x.u)) {
+ if (auto *z{std::get_if<common::Indirection<OpenMPDeclarativeConstruct>>(
+ &y->u)}) {
+ return &z->value();
+ }
+ }
+ return nullptr;
+}
+
+const OpenMPConstruct *GetOmp(const ExecutionPartConstruct &x) {
+ if (auto *y{std::get_if<ExecutableConstruct>(&x.u)}) {
+ if (auto *z{std::get_if<common::Indirection<OpenMPConstruct>>(&y->u)}) {
+ return &z->value();
+ }
+ }
+ return nullptr;
+}
+
const OmpObjectList *GetOmpObjectList(const OmpClause &clause) {
// Clauses with OmpObjectList as its data member
using MemberObjectListClauses = std::tuple<OmpClause::Copyin,
@@ -86,4 +105,24 @@ const OmpInitializerExpression *GetInitializerExpr(const OmpClause &init) {
return nullptr;
}
+static void SplitOmpAllocateHelper(
+ OmpAllocateInfo &n, const OmpAllocateDirective &x) {
+ n.dirs.push_back(&x);
+ const Block &body{std::get<Block>(x.t)};
+ if (!body.empty()) {
+ if (auto *omp{GetOmp(body.front())}) {
+ if (auto *ad{std::get_if<OmpAllocateDirective>(&omp->u)}) {
+ return SplitOmpAllocateHelper(n, *ad);
+ }
+ }
+ n.body = &body.front();
+ }
+}
+
+OmpAllocateInfo SplitOmpAllocate(const OmpAllocateDirective &x) {
+ OmpAllocateInfo info;
+ SplitOmpAllocateHelper(info, x);
+ return info;
+}
+
} // namespace Fortran::parser::omp
diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index b3a395c4d72e1..84123030195e9 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -2482,32 +2482,8 @@ class UnparseVisitor {
Unparse(static_cast<const OmpBlockConstruct &>(x));
}
- void Unparse(const OpenMPExecutableAllocate &x) {
- const auto &fields =
- std::get<std::optional<std::list<parser::OpenMPDeclarativeAllocate>>>(
- x.t);
- if (fields) {
- for (const auto &decl : *fields) {
- Walk(decl);
- }
- }
- BeginOpenMP();
- Word("!$OMP ALLOCATE");
- Walk(" (", std::get<std::optional<OmpObjectList>>(x.t), ")");
- Walk(std::get<OmpClauseList>(x.t));
- Put("\n");
- EndOpenMP();
- Walk(std::get<Statement<AllocateStmt>>(x.t));
- }
- void Unparse(const OpenMPDeclarativeAllocate &x) {
- BeginOpenMP();
- Word("!$OMP ALLOCATE");
- Put(" (");
- Walk(std::get<std::optional<OmpObjectList>>(x.t));
- Put(")");
- Walk(std::get<OmpClauseList>(x.t));
- Put("\n");
- EndOpenMP();
+ void Unparse(const OmpAllocateDirective &x) {
+ Unparse(static_cast<const OmpBlockConstruct &>(x));
}
void Unparse(const OpenMPAllocatorsConstruct &x) {
Unparse(static_cast<const OmpBlockConstruct &>(x));
diff --git a/flang/lib/Semantics/canonicalize-omp.cpp b/flang/lib/Semantics/canonicalize-omp.cpp
index c884658bf464a..039dd7f564758 100644
--- a/flang/lib/Semantics/canonicalize-omp.cpp
+++ b/flang/lib/Semantics/canonicalize-omp.cpp
@@ -51,8 +51,6 @@ class CanonicalizationOfOmp {
} // Block list
}
- void Post(parser::ExecutionPart &body) { RewriteOmpAllocations(body); }
-
// Pre-visit all constructs that have both a specification part and
// an execution part, and store the connection between the two.
bool Pre(parser::BlockConstruct &x) {
@@ -88,6 +86,7 @@ class CanonicalizationOfOmp {
void Post(parser::SpecificationPart &spec) {
CanonicalizeUtilityConstructs(spec);
+ CanonicalizeAllocateDirectives(spec);
}
void Post(parser::OmpMapClause &map) { CanonicalizeMapModifiers(map); }
@@ -239,33 +238,138 @@ class CanonicalizationOfOmp {
}
}
- void RewriteOmpAllocations(parser::ExecutionPart &body) {
- // Rewrite leading declarative allocations so they are nested
- // within their respective executable allocate directive
- //
- // Original:
- // ExecutionPartConstruct -> OpenMPDeclarativeAllocate
- // ExecutionPartConstruct -> OpenMPDeclarativeAllocate
- // ExecutionPartConstruct -> OpenMPExecutableAllocate
- //
- // After rewriting:
- // ExecutionPartConstruct -> OpenMPExecutableAllocate
- // ExecutionPartConstruct -> OpenMPDeclarativeAllocate
- // ExecutionPartConstruct -> OpenMPDeclarativeAllocate
- for (auto it = body.v.rbegin(); it != body.v.rend();) {
- if (auto *exec = GetOmpIf<parser::OpenMPExecutableAllocate>(*(it++))) {
- parser::OpenMPDeclarativeAllocate *decl;
- std::list<parser::OpenMPDeclarativeAllocate> subAllocates;
- while (it != body.v.rend() &&
- (decl = GetOmpIf<parser::OpenMPDeclarativeAllocate>(*it))) {
- subAllocates.push_front(std::move(*decl));
- it = decltype(it)(body.v.erase(std::next(it).base()));
+ // Canonicalization of allocate directives
+ //
+ // In OpenMP 5.0 and 5.1 the allocate directive could either be a declarative
+ // one or an executable one. As usual in such cases, this poses a problem
+ // when the directive appears at the boundary between the specification part
+ // and the execution part.
+ // The executable form can actually consist of several adjacent directives,
+ // whereas the declarative form is always standalone. Additionally, the
+ // executable form must be associated with an allocate statement.
+ //
+ // The parser tries to parse declarative statements first, so in the
+ // fo...
[truncated]
|
|
@llvm/pr-subscribers-flang-fir-hlfir Author: Krzysztof Parzyszek (kparzysz) ChangesThe ALLOCATE directive has two forms:
The second form was deprecated in OpenMP 5.2 in favor of the ALLOCATORS construct. Since in the parse tree every type corresponding to a directive only corresponds to a single directive, the executable form is represented by a sequence of nested OmpAlocateDirectives, e.g. will become With this change all AST nodes for directives use OmpDirectiveSpecification as the directive representation. Patch is 69.27 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/165865.diff 27 Files Affected:
diff --git a/flang/examples/FeatureList/FeatureList.cpp b/flang/examples/FeatureList/FeatureList.cpp
index 225a6558ef956..ef58da61e371b 100644
--- a/flang/examples/FeatureList/FeatureList.cpp
+++ b/flang/examples/FeatureList/FeatureList.cpp
@@ -445,6 +445,7 @@ struct NodeVisitor {
READ_FEATURE(ObjectDecl)
READ_FEATURE(OldParameterStmt)
READ_FEATURE(OmpAlignedClause)
+ READ_FEATURE(OmpAllocateDirective)
READ_FEATURE(OmpBeginDirective)
READ_FEATURE(OmpBeginLoopDirective)
READ_FEATURE(OmpBeginSectionsDirective)
@@ -541,7 +542,6 @@ struct NodeVisitor {
READ_FEATURE(OpenMPCancellationPointConstruct)
READ_FEATURE(OpenMPConstruct)
READ_FEATURE(OpenMPCriticalConstruct)
- READ_FEATURE(OpenMPDeclarativeAllocate)
READ_FEATURE(OpenMPDeclarativeConstruct)
READ_FEATURE(OpenMPDeclareReductionConstruct)
READ_FEATURE(OpenMPDeclareSimdConstruct)
@@ -550,7 +550,6 @@ struct NodeVisitor {
READ_FEATURE(OmpAtomicDefaultMemOrderClause)
READ_FEATURE(OpenMPFlushConstruct)
READ_FEATURE(OpenMPLoopConstruct)
- READ_FEATURE(OpenMPExecutableAllocate)
READ_FEATURE(OpenMPAllocatorsConstruct)
READ_FEATURE(OpenMPRequiresConstruct)
READ_FEATURE(OpenMPSimpleStandaloneConstruct)
diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h
index a7398a4ef970f..de2716410d6cd 100644
--- a/flang/include/flang/Parser/dump-parse-tree.h
+++ b/flang/include/flang/Parser/dump-parse-tree.h
@@ -512,6 +512,7 @@ class ParseTreeDumper {
NODE(parser, OmpAlignModifier)
NODE(parser, OmpAllocateClause)
NODE(OmpAllocateClause, Modifier)
+ NODE(parser, OmpAllocateDirective)
NODE(parser, OmpAllocatorComplexModifier)
NODE(parser, OmpAllocatorSimpleModifier)
NODE(parser, OmpAlwaysModifier)
@@ -739,7 +740,6 @@ class ParseTreeDumper {
NODE(parser, OpenMPCancellationPointConstruct)
NODE(parser, OpenMPConstruct)
NODE(parser, OpenMPCriticalConstruct)
- NODE(parser, OpenMPDeclarativeAllocate)
NODE(parser, OpenMPDeclarativeAssumes)
NODE(parser, OpenMPDeclarativeConstruct)
NODE(parser, OpenMPDeclareMapperConstruct)
@@ -748,7 +748,6 @@ class ParseTreeDumper {
NODE(parser, OpenMPDeclareTargetConstruct)
NODE(parser, OpenMPDepobjConstruct)
NODE(parser, OpenMPDispatchConstruct)
- NODE(parser, OpenMPExecutableAllocate)
NODE(parser, OpenMPFlushConstruct)
NODE(parser, OpenMPGroupprivate)
NODE(parser, OpenMPLoopConstruct)
diff --git a/flang/include/flang/Parser/openmp-utils.h b/flang/include/flang/Parser/openmp-utils.h
index 49db091af93a7..8fa4a84aff06d 100644
--- a/flang/include/flang/Parser/openmp-utils.h
+++ b/flang/include/flang/Parser/openmp-utils.h
@@ -22,6 +22,7 @@
#include <type_traits>
#include <utility>
#include <variant>
+#include <vector>
namespace Fortran::parser::omp {
@@ -33,23 +34,6 @@ template <typename T> constexpr auto addr_if(const std::optional<T> &x) {
}
namespace detail {
-using D = llvm::omp::Directive;
-
-template <typename Construct> //
-struct ConstructId {
- static constexpr llvm::omp::Directive id{D::OMPD_unknown};
-};
-
-#define MAKE_CONSTR_ID(Construct, Id) \
- template <> struct ConstructId<Construct> { \
- static constexpr llvm::omp::Directive id{Id}; \
- }
-
-MAKE_CONSTR_ID(OpenMPDeclarativeAllocate, D::OMPD_allocate);
-MAKE_CONSTR_ID(OpenMPExecutableAllocate, D::OMPD_allocate);
-
-#undef MAKE_CONSTR_ID
-
struct DirectiveNameScope {
static OmpDirectiveName MakeName(CharBlock source = {},
llvm::omp::Directive id = llvm::omp::Directive::OMPD_unknown) {
@@ -97,9 +81,6 @@ struct DirectiveNameScope {
} else if constexpr (TupleTrait<T>) {
if constexpr (std::is_base_of_v<OmpBlockConstruct, T>) {
return std::get<OmpBeginDirective>(x.t).DirName();
- } else if constexpr (std::is_same_v<T, OpenMPDeclarativeAllocate> ||
- std::is_same_v<T, OpenMPExecutableAllocate>) {
- return MakeName(std::get<Verbatim>(x.t).source, ConstructId<T>::id);
} else {
return GetFromTuple(
x.t, std::make_index_sequence<std::tuple_size_v<decltype(x.t)>>{});
@@ -139,6 +120,9 @@ template <typename T> OmpDirectiveName GetOmpDirectiveName(const T &x) {
return detail::DirectiveNameScope::GetOmpDirectiveName(x);
}
+const OpenMPDeclarativeConstruct *GetOmp(const DeclarationConstruct &x);
+const OpenMPConstruct *GetOmp(const ExecutionPartConstruct &x);
+
const OmpObjectList *GetOmpObjectList(const OmpClause &clause);
template <typename T>
@@ -158,6 +142,13 @@ const OmpCombinerExpression *GetCombinerExpr(
const OmpReductionSpecifier &rspec);
const OmpInitializerExpression *GetInitializerExpr(const OmpClause &init);
+struct OmpAllocateInfo {
+ std::vector<const OmpAllocateDirective *> dirs;
+ const ExecutionPartConstruct *body{nullptr};
+};
+
+OmpAllocateInfo SplitOmpAllocate(const OmpAllocateDirective &x);
+
} // namespace Fortran::parser::omp
#endif // FORTRAN_PARSER_OPENMP_UTILS_H
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index 4dd5e84f60dfe..8c7578f7a1941 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -5151,17 +5151,42 @@ struct OpenMPThreadprivate {
CharBlock source;
};
-// 2.11.3 allocate -> ALLOCATE (variable-name-list) [clause]
-struct OpenMPDeclarativeAllocate {
- TUPLE_CLASS_BOILERPLATE(OpenMPDeclarativeAllocate);
- CharBlock source;
- std::tuple<Verbatim, std::optional<OmpObjectList>, OmpClauseList> t;
+// Ref: [4.5:310-312], [5.0:156-158], [5.1:181-184], [5.2:176-177],
+// [6.0:310-312]
+//
+// allocate-directive ->
+// ALLOCATE (variable-list-item...) | // since 4.5
+// ALLOCATE (variable-list-item...) // since 5.0, until 5.1
+// ...
+// allocate-stmt
+//
+// The first form is the "declarative-allocate", and is a declarative
+// directive. The second is the "executable-allocate" and is an executable
+// directive. The executable form was deprecated in 5.2.
+//
+// The executable-allocate consists of several ALLOCATE directives. Since
+// in the parse tree every type corresponding to a directive only corresponds
+// to a single directive, the executable form is represented by a sequence
+// of nested OmpAlocateDirectives, e.g.
+// !$OMP ALLOCATE(x)
+// !$OMP ALLOCATE(y)
+// ALLOCATE(x, y)
+// will become
+// OmpAllocateDirective
+// |- ALLOCATE(x) // begin directive
+// `- OmpAllocateDirective // block
+// |- ALLOCATE(y) // begin directive
+// `- ALLOCATE(x, y) // block
+//
+// The block in the declarative-allocate will be empty.
+struct OmpAllocateDirective : public OmpBlockConstruct {
+ INHERITED_TUPLE_CLASS_BOILERPLATE(OmpAllocateDirective, OmpBlockConstruct);
};
struct OpenMPDeclarativeConstruct {
UNION_CLASS_BOILERPLATE(OpenMPDeclarativeConstruct);
CharBlock source;
- std::variant<OpenMPDeclarativeAllocate, OpenMPDeclarativeAssumes,
+ std::variant<OmpAllocateDirective, OpenMPDeclarativeAssumes,
OpenMPDeclareMapperConstruct, OpenMPDeclareReductionConstruct,
OpenMPDeclareSimdConstruct, OpenMPDeclareTargetConstruct,
OmpDeclareVariantDirective, OpenMPGroupprivate, OpenMPThreadprivate,
@@ -5174,19 +5199,6 @@ struct OpenMPCriticalConstruct : public OmpBlockConstruct {
INHERITED_TUPLE_CLASS_BOILERPLATE(OpenMPCriticalConstruct, OmpBlockConstruct);
};
-// 2.11.3 allocate -> ALLOCATE [(variable-name-list)] [clause]
-// [ALLOCATE (variable-name-list) [clause] [...]]
-// allocate-statement
-// clause -> allocator-clause
-struct OpenMPExecutableAllocate {
- TUPLE_CLASS_BOILERPLATE(OpenMPExecutableAllocate);
- CharBlock source;
- std::tuple<Verbatim, std::optional<OmpObjectList>, OmpClauseList,
- std::optional<std::list<OpenMPDeclarativeAllocate>>,
- Statement<AllocateStmt>>
- t;
-};
-
// Ref: [5.2:180-181], [6.0:315]
//
// allocators-construct ->
@@ -5342,9 +5354,9 @@ struct OpenMPConstruct {
UNION_CLASS_BOILERPLATE(OpenMPConstruct);
std::variant<OpenMPStandaloneConstruct, OpenMPSectionsConstruct,
OpenMPSectionConstruct, OpenMPLoopConstruct, OmpBlockConstruct,
- OpenMPAtomicConstruct, OpenMPDeclarativeAllocate, OpenMPDispatchConstruct,
- OpenMPUtilityConstruct, OpenMPExecutableAllocate,
- OpenMPAllocatorsConstruct, OpenMPAssumeConstruct, OpenMPCriticalConstruct>
+ OpenMPAtomicConstruct, OmpAllocateDirective, OpenMPDispatchConstruct,
+ OpenMPUtilityConstruct, OpenMPAllocatorsConstruct, OpenMPAssumeConstruct,
+ OpenMPCriticalConstruct>
u;
};
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index 71067283d13f7..b901f24ae366e 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -3506,9 +3506,9 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
static void
genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval,
- const parser::OpenMPDeclarativeAllocate &declarativeAllocate) {
+ const parser::OmpAllocateDirective &allocate) {
if (!semaCtx.langOptions().OpenMPSimd)
- TODO(converter.getCurrentLocation(), "OpenMPDeclarativeAllocate");
+ TODO(converter.getCurrentLocation(), "OmpAllocateDirective");
}
static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
@@ -3899,14 +3899,6 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
TODO(converter.getCurrentLocation(), "OpenMPDispatchConstruct");
}
-static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
- semantics::SemanticsContext &semaCtx,
- lower::pft::Evaluation &eval,
- const parser::OpenMPExecutableAllocate &execAllocConstruct) {
- if (!semaCtx.langOptions().OpenMPSimd)
- TODO(converter.getCurrentLocation(), "OpenMPExecutableAllocate");
-}
-
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 a9de26ea09ff8..4374acbbe51bf 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -1778,6 +1778,31 @@ struct OmpBlockConstructParser {
llvm::omp::Directive dir_;
};
+struct OmpDeclarativeAllocateParser {
+ using resultType = OmpAllocateDirective;
+
+ std::optional<resultType> Parse(ParseState &state) const {
+ constexpr llvm::omp::Directive dir{llvm::omp::Directive::OMPD_allocate};
+ if (auto &&begin{attempt(OmpBeginDirectiveParser(dir)).Parse(state)}) {
+ Block empty;
+ auto end{maybe(OmpEndDirectiveParser{dir}).Parse(state)};
+ return OmpAllocateDirective{std::move(*begin), std::move(empty),
+ llvm::transformOptional(std::move(*end),
+ [](auto &&s) { return OmpEndDirective(std::move(s)); })};
+ }
+ return std::nullopt;
+ }
+};
+
+struct OmpExecutableAllocateParser {
+ using resultType = OmpAllocateDirective;
+
+ std::optional<resultType> Parse(ParseState &state) const {
+ OmpStatementConstructParser p{llvm::omp::Directive::OMPD_allocate};
+ return construct<OmpAllocateDirective>(p).Parse(state);
+ }
+};
+
TYPE_PARSER(sourced(construct<OpenMPAllocatorsConstruct>(
OmpStatementConstructParser{llvm::omp::Directive::OMPD_allocators})))
@@ -2044,14 +2069,6 @@ TYPE_PARSER(construct<OmpInitializerExpression>(OmpStylizedExpressionParser{}))
TYPE_PARSER(sourced(construct<OpenMPCriticalConstruct>(
OmpBlockConstructParser{llvm::omp::Directive::OMPD_critical})))
-// 2.11.3 Executable Allocate directive
-TYPE_PARSER(sourced(construct<OpenMPExecutableAllocate>(
- verbatim("ALLOCATE"_tok), maybe(parenthesized(Parser<OmpObjectList>{})),
- Parser<OmpClauseList>{},
- maybe(nonemptyList(startOmpLine >> Parser<OpenMPDeclarativeAllocate>{})) /
- endOmpLine,
- statement(allocateStmt))))
-
// 2.8.2 Declare Simd construct
TYPE_PARSER(sourced(construct<OpenMPDeclareSimdConstruct>(
predicated(Parser<OmpDirectiveName>{},
@@ -2077,13 +2094,6 @@ TYPE_PARSER(sourced( //
IsDirective(llvm::omp::Directive::OMPD_threadprivate)) >=
Parser<OmpDirectiveSpecification>{})))
-// 2.11.3 Declarative Allocate directive
-TYPE_PARSER(
- sourced(construct<OpenMPDeclarativeAllocate>(verbatim("ALLOCATE"_tok),
- maybe(parenthesized(Parser<OmpObjectList>{})),
- Parser<OmpClauseList>{})) /
- lookAhead(endOmpLine / !statement(allocateStmt)))
-
// Assumes Construct
TYPE_PARSER(sourced(construct<OpenMPDeclarativeAssumes>(
predicated(OmpDirectiveNameParser{},
@@ -2106,7 +2116,7 @@ TYPE_PARSER(
construct<OpenMPDeclarativeConstruct>(
Parser<OmpDeclareVariantDirective>{}) ||
construct<OpenMPDeclarativeConstruct>(
- Parser<OpenMPDeclarativeAllocate>{}) ||
+ sourced(OmpDeclarativeAllocateParser{})) ||
construct<OpenMPDeclarativeConstruct>(
Parser<OpenMPGroupprivate>{}) ||
construct<OpenMPDeclarativeConstruct>(
@@ -2194,6 +2204,8 @@ TYPE_CONTEXT_PARSER("OpenMP construct"_en_US,
withMessage("expected OpenMP construct"_err_en_US,
first(construct<OpenMPConstruct>(Parser<OpenMPSectionsConstruct>{}),
construct<OpenMPConstruct>(Parser<OpenMPLoopConstruct>{}),
+ construct<OpenMPConstruct>(
+ sourced(OmpExecutableAllocateParser{})),
construct<OpenMPConstruct>(Parser<OmpBlockConstruct>{}),
// OmpBlockConstruct is attempted before
// OpenMPStandaloneConstruct to resolve !$OMP ORDERED
@@ -2201,9 +2213,7 @@ TYPE_CONTEXT_PARSER("OpenMP construct"_en_US,
construct<OpenMPConstruct>(Parser<OpenMPAtomicConstruct>{}),
construct<OpenMPConstruct>(Parser<OpenMPUtilityConstruct>{}),
construct<OpenMPConstruct>(Parser<OpenMPDispatchConstruct>{}),
- construct<OpenMPConstruct>(Parser<OpenMPExecutableAllocate>{}),
construct<OpenMPConstruct>(Parser<OpenMPAllocatorsConstruct>{}),
- construct<OpenMPConstruct>(Parser<OpenMPDeclarativeAllocate>{}),
construct<OpenMPConstruct>(Parser<OpenMPAssumeConstruct>{}),
construct<OpenMPConstruct>(Parser<OpenMPCriticalConstruct>{}))))
diff --git a/flang/lib/Parser/openmp-utils.cpp b/flang/lib/Parser/openmp-utils.cpp
index 95ad3f60770f5..b9d3763cdd06d 100644
--- a/flang/lib/Parser/openmp-utils.cpp
+++ b/flang/lib/Parser/openmp-utils.cpp
@@ -22,6 +22,25 @@
namespace Fortran::parser::omp {
+const OpenMPDeclarativeConstruct *GetOmp(const DeclarationConstruct &x) {
+ if (auto *y = std::get_if<SpecificationConstruct>(&x.u)) {
+ if (auto *z{std::get_if<common::Indirection<OpenMPDeclarativeConstruct>>(
+ &y->u)}) {
+ return &z->value();
+ }
+ }
+ return nullptr;
+}
+
+const OpenMPConstruct *GetOmp(const ExecutionPartConstruct &x) {
+ if (auto *y{std::get_if<ExecutableConstruct>(&x.u)}) {
+ if (auto *z{std::get_if<common::Indirection<OpenMPConstruct>>(&y->u)}) {
+ return &z->value();
+ }
+ }
+ return nullptr;
+}
+
const OmpObjectList *GetOmpObjectList(const OmpClause &clause) {
// Clauses with OmpObjectList as its data member
using MemberObjectListClauses = std::tuple<OmpClause::Copyin,
@@ -86,4 +105,24 @@ const OmpInitializerExpression *GetInitializerExpr(const OmpClause &init) {
return nullptr;
}
+static void SplitOmpAllocateHelper(
+ OmpAllocateInfo &n, const OmpAllocateDirective &x) {
+ n.dirs.push_back(&x);
+ const Block &body{std::get<Block>(x.t)};
+ if (!body.empty()) {
+ if (auto *omp{GetOmp(body.front())}) {
+ if (auto *ad{std::get_if<OmpAllocateDirective>(&omp->u)}) {
+ return SplitOmpAllocateHelper(n, *ad);
+ }
+ }
+ n.body = &body.front();
+ }
+}
+
+OmpAllocateInfo SplitOmpAllocate(const OmpAllocateDirective &x) {
+ OmpAllocateInfo info;
+ SplitOmpAllocateHelper(info, x);
+ return info;
+}
+
} // namespace Fortran::parser::omp
diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index b3a395c4d72e1..84123030195e9 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -2482,32 +2482,8 @@ class UnparseVisitor {
Unparse(static_cast<const OmpBlockConstruct &>(x));
}
- void Unparse(const OpenMPExecutableAllocate &x) {
- const auto &fields =
- std::get<std::optional<std::list<parser::OpenMPDeclarativeAllocate>>>(
- x.t);
- if (fields) {
- for (const auto &decl : *fields) {
- Walk(decl);
- }
- }
- BeginOpenMP();
- Word("!$OMP ALLOCATE");
- Walk(" (", std::get<std::optional<OmpObjectList>>(x.t), ")");
- Walk(std::get<OmpClauseList>(x.t));
- Put("\n");
- EndOpenMP();
- Walk(std::get<Statement<AllocateStmt>>(x.t));
- }
- void Unparse(const OpenMPDeclarativeAllocate &x) {
- BeginOpenMP();
- Word("!$OMP ALLOCATE");
- Put(" (");
- Walk(std::get<std::optional<OmpObjectList>>(x.t));
- Put(")");
- Walk(std::get<OmpClauseList>(x.t));
- Put("\n");
- EndOpenMP();
+ void Unparse(const OmpAllocateDirective &x) {
+ Unparse(static_cast<const OmpBlockConstruct &>(x));
}
void Unparse(const OpenMPAllocatorsConstruct &x) {
Unparse(static_cast<const OmpBlockConstruct &>(x));
diff --git a/flang/lib/Semantics/canonicalize-omp.cpp b/flang/lib/Semantics/canonicalize-omp.cpp
index c884658bf464a..039dd7f564758 100644
--- a/flang/lib/Semantics/canonicalize-omp.cpp
+++ b/flang/lib/Semantics/canonicalize-omp.cpp
@@ -51,8 +51,6 @@ class CanonicalizationOfOmp {
} // Block list
}
- void Post(parser::ExecutionPart &body) { RewriteOmpAllocations(body); }
-
// Pre-visit all constructs that have both a specification part and
// an execution part, and store the connection between the two.
bool Pre(parser::BlockConstruct &x) {
@@ -88,6 +86,7 @@ class CanonicalizationOfOmp {
void Post(parser::SpecificationPart &spec) {
CanonicalizeUtilityConstructs(spec);
+ CanonicalizeAllocateDirectives(spec);
}
void Post(parser::OmpMapClause &map) { CanonicalizeMapModifiers(map); }
@@ -239,33 +238,138 @@ class CanonicalizationOfOmp {
}
}
- void RewriteOmpAllocations(parser::ExecutionPart &body) {
- // Rewrite leading declarative allocations so they are nested
- // within their respective executable allocate directive
- //
- // Original:
- // ExecutionPartConstruct -> OpenMPDeclarativeAllocate
- // ExecutionPartConstruct -> OpenMPDeclarativeAllocate
- // ExecutionPartConstruct -> OpenMPExecutableAllocate
- //
- // After rewriting:
- // ExecutionPartConstruct -> OpenMPExecutableAllocate
- // ExecutionPartConstruct -> OpenMPDeclarativeAllocate
- // ExecutionPartConstruct -> OpenMPDeclarativeAllocate
- for (auto it = body.v.rbegin(); it != body.v.rend();) {
- if (auto *exec = GetOmpIf<parser::OpenMPExecutableAllocate>(*(it++))) {
- parser::OpenMPDeclarativeAllocate *decl;
- std::list<parser::OpenMPDeclarativeAllocate> subAllocates;
- while (it != body.v.rend() &&
- (decl = GetOmpIf<parser::OpenMPDeclarativeAllocate>(*it))) {
- subAllocates.push_front(std::move(*decl));
- it = decltype(it)(body.v.erase(std::next(it).base()));
+ // Canonicalization of allocate directives
+ //
+ // In OpenMP 5.0 and 5.1 the allocate directive could either be a declarative
+ // one or an executable one. As usual in such cases, this poses a problem
+ // when the directive appears at the boundary between the specification part
+ // and the execution part.
+ // The executable form can actually consist of several adjacent directives,
+ // whereas the declarative form is always standalone. Additionally, the
+ // executable form must be associated with an allocate statement.
+ //
+ // The parser tries to parse declarative statements first, so in the
+ // fo...
[truncated]
|
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few minor comments from me.
| }; | ||
|
|
||
| std::list<parser::DeclarationConstruct>::reverse_iterator rlast = [&]() { | ||
| for (auto rit = decls.rbegin(), rend = decls.rend(); rit != rend; ++rit) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure rend is needed here, could it just be rit != decls.rend()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Strictly speaking it's not needed, but it's customary to put the end in a variable. We do that in other functions in this file as well. If you strongly dislike it, let me know. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If its matching what is already done, then thats ok with me!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
| }; | ||
|
|
||
| std::list<parser::DeclarationConstruct>::reverse_iterator rlast = [&]() { | ||
| for (auto rit = decls.rbegin(), rend = decls.rend(); rit != rend; ++rit) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If its matching what is already done, then thats ok with me!
The ALLOCATE directive has two forms:
The second form was deprecated in OpenMP 5.2 in favor of the ALLOCATORS construct.
Since in the parse tree every type corresponding to a directive only corresponds to a single directive, the executable form is represented by a sequence of nested OmpAllocateDirectives, e.g.
will become
With this change all AST nodes for directives use OmpDirectiveSpecification as the directive representation.