Skip to content

Commit 6984922

Browse files
authored
[flang][OpenMP] Store directive information in OpenMPSectionConstruct (#150804)
The OpenMPSectionConstruct corresponds to the `!$omp section` directive, but there is nothing in the AST node that stores the directive information. Even though the only possibility (at the moment) is "section" without any clauses, for improved generality it is helpful to have that information anyway.
1 parent 6ffcfc5 commit 6984922

File tree

11 files changed

+183
-126
lines changed

11 files changed

+183
-126
lines changed

flang/examples/FeatureList/FeatureList.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -529,7 +529,6 @@ struct NodeVisitor {
529529
READ_FEATURE(OmpChunkModifier::Value)
530530
READ_FEATURE(OmpOrderingModifier)
531531
READ_FEATURE(OmpOrderingModifier::Value)
532-
READ_FEATURE(OmpSectionBlocks)
533532
READ_FEATURE(OmpSectionsDirective)
534533
READ_FEATURE(Only)
535534
READ_FEATURE(OpenACCAtomicConstruct)

flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp

Lines changed: 3 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "FlangOmpReportVisitor.h"
10+
#include "flang/Parser/openmp-utils.h"
1011
#include "llvm/ADT/StringExtras.h"
1112
#include "llvm/Frontend/OpenMP/OMP.h"
1213

@@ -118,60 +119,8 @@ std::string OpenMPCounterVisitor::getName(const OpenMPDeclarativeConstruct &c) {
118119
c.u);
119120
}
120121
std::string OpenMPCounterVisitor::getName(const OpenMPConstruct &c) {
121-
return std::visit(
122-
Fortran::common::visitors{
123-
[&](const OpenMPStandaloneConstruct &c) -> std::string {
124-
return common::visit(
125-
common::visitors{
126-
[&](const OmpMetadirectiveDirective &d) {
127-
return normalize_construct_name(d.source.ToString());
128-
},
129-
[&](auto &&d) {
130-
const CharBlock &source{
131-
std::get<OmpDirectiveName>(d.v.t).source};
132-
return normalize_construct_name(source.ToString());
133-
},
134-
},
135-
c.u);
136-
},
137-
[&](const OpenMPExecutableAllocate &c) -> std::string {
138-
const CharBlock &source{std::get<0>(c.t).source};
139-
return normalize_construct_name(source.ToString());
140-
},
141-
[&](const OpenMPDeclarativeAllocate &c) -> std::string {
142-
const CharBlock &source{std::get<0>(c.t).source};
143-
return normalize_construct_name(source.ToString());
144-
},
145-
[&](const OpenMPAssumeConstruct &c) -> std::string {
146-
const CharBlock &source{std::get<0>(c.t).source};
147-
return normalize_construct_name(source.ToString());
148-
},
149-
[&](const OpenMPAllocatorsConstruct &c) -> std::string {
150-
const CharBlock &source{std::get<0>(c.t).source};
151-
return normalize_construct_name(source.ToString());
152-
},
153-
[&](const OpenMPAtomicConstruct &c) -> std::string {
154-
auto &dirSpec = std::get<OmpDirectiveSpecification>(c.t);
155-
auto &dirName = std::get<OmpDirectiveName>(dirSpec.t);
156-
return normalize_construct_name(dirName.source.ToString());
157-
},
158-
[&](const OpenMPUtilityConstruct &c) -> std::string {
159-
const CharBlock &source{c.source};
160-
return normalize_construct_name(source.ToString());
161-
},
162-
[&](const OpenMPSectionConstruct &c) -> std::string {
163-
return "section";
164-
},
165-
// OpenMPSectionsConstruct, OpenMPLoopConstruct,
166-
// OpenMPBlockConstruct, OpenMPCriticalConstruct Get the source from
167-
// the directive field of the begin directive or from the verbatim
168-
// field of the begin directive in Critical
169-
[&](const auto &c) -> std::string {
170-
const CharBlock &source{std::get<0>(std::get<0>(c.t).t).source};
171-
return normalize_construct_name(source.ToString());
172-
},
173-
},
174-
c.u);
122+
return normalize_construct_name(
123+
omp::GetOmpDirectiveName(c).source.ToString());
175124
}
176125

177126
bool OpenMPCounterVisitor::Pre(const OpenMPDeclarativeConstruct &c) {

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -681,7 +681,6 @@ class ParseTreeDumper {
681681
NODE_ENUM(OmpChunkModifier, Value)
682682
NODE(parser, OmpOrderingModifier)
683683
NODE_ENUM(OmpOrderingModifier, Value)
684-
NODE(parser, OmpSectionBlocks)
685684
NODE(parser, OmpSectionsDirective)
686685
NODE(parser, OmpToClause)
687686
NODE(OmpToClause, Modifier)

flang/include/flang/Parser/openmp-utils.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,14 @@ struct DirectiveNameScope {
7878
return MakeName(dir.source, dir.v);
7979
}
8080

81+
static OmpDirectiveName GetOmpDirectiveName(const OpenMPSectionConstruct &x) {
82+
if (auto &spec{std::get<std::optional<OmpDirectiveSpecification>>(x.t)}) {
83+
return spec->DirName();
84+
} else {
85+
return MakeName({}, llvm::omp::Directive::OMPD_section);
86+
}
87+
}
88+
8189
static OmpDirectiveName GetOmpDirectiveName(
8290
const OmpBeginSectionsDirective &x) {
8391
auto &dir{std::get<OmpSectionsDirective>(x.t)};

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

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4818,18 +4818,17 @@ struct OmpEndSectionsDirective {
48184818
// structured-block]
48194819
// ...
48204820
struct OpenMPSectionConstruct {
4821-
WRAPPER_CLASS_BOILERPLATE(OpenMPSectionConstruct, Block);
4821+
TUPLE_CLASS_BOILERPLATE(OpenMPSectionConstruct);
4822+
std::tuple<std::optional<OmpDirectiveSpecification>, Block> t;
48224823
CharBlock source;
48234824
};
48244825

4825-
// `OmpSectionBlocks` is a list of section constructs. The parser guarentees
4826-
// that the `OpenMPConstruct` here always encapsulates an
4827-
// `OpenMPSectionConstruct` and not any other OpenMP construct.
4828-
WRAPPER_CLASS(OmpSectionBlocks, std::list<OpenMPConstruct>);
4829-
48304826
struct OpenMPSectionsConstruct {
48314827
TUPLE_CLASS_BOILERPLATE(OpenMPSectionsConstruct);
4832-
std::tuple<OmpBeginSectionsDirective, OmpSectionBlocks,
4828+
CharBlock source;
4829+
// Each of the OpenMPConstructs in the list below contains an
4830+
// OpenMPSectionConstruct. This is guaranteed by the parser.
4831+
std::tuple<OmpBeginSectionsDirective, std::list<OpenMPConstruct>,
48334832
OmpEndSectionsDirective>
48344833
t;
48354834
};

flang/lib/Lower/OpenMP/OpenMP.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2332,7 +2332,7 @@ genSectionsOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
23322332
assert(sectionsConstruct && "Missing additional parsing information");
23332333

23342334
const auto &sectionBlocks =
2335-
std::get<parser::OmpSectionBlocks>(sectionsConstruct->t);
2335+
std::get<std::list<parser::OpenMPConstruct>>(sectionsConstruct->t);
23362336
mlir::omp::SectionsOperands clauseOps;
23372337
llvm::SmallVector<const semantics::Symbol *> reductionSyms;
23382338
genSectionsClauses(converter, semaCtx, item->clauses, loc, clauseOps,
@@ -2385,7 +2385,7 @@ genSectionsOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
23852385
// because we need to run genReductionVars on each omp.section so that the
23862386
// reduction variable gets mapped to the private version
23872387
for (auto [construct, nestedEval] :
2388-
llvm::zip(sectionBlocks.v, eval.getNestedEvaluations())) {
2388+
llvm::zip(sectionBlocks, eval.getNestedEvaluations())) {
23892389
const auto *sectionConstruct =
23902390
std::get_if<parser::OpenMPSectionConstruct>(&construct.u);
23912391
if (!sectionConstruct) {

flang/lib/Parser/openmp-parsers.cpp

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,39 @@ namespace Fortran::parser {
3434
constexpr auto startOmpLine = skipStuffBeforeStatement >> "!$OMP "_sptok;
3535
constexpr auto endOmpLine = space >> endOfLine;
3636

37+
// Given a parser for a single element, and a parser for a list of elements
38+
// of the same type, create a parser that constructs the entire list by having
39+
// the single element be the head of the list, and the rest be the tail.
40+
template <typename ParserH, typename ParserT> struct ConsParser {
41+
static_assert(std::is_same_v<std::list<typename ParserH::resultType>,
42+
typename ParserT::resultType>);
43+
44+
using resultType = typename ParserT::resultType;
45+
constexpr ConsParser(ParserH h, ParserT t) : head_(h), tail_(t) {}
46+
47+
std::optional<resultType> Parse(ParseState &state) const {
48+
if (auto &&first{head_.Parse(state)}) {
49+
if (auto rest{tail_.Parse(state)}) {
50+
rest->push_front(std::move(*first));
51+
return std::move(*rest);
52+
}
53+
}
54+
return std::nullopt;
55+
}
56+
57+
private:
58+
const ParserH head_;
59+
const ParserT tail_;
60+
};
61+
62+
template <typename ParserH, typename ParserT,
63+
typename ValueH = typename ParserH::resultType,
64+
typename ValueT = typename ParserT::resultType,
65+
typename = std::enable_if_t<std::is_same_v<std::list<ValueH>, ValueT>>>
66+
constexpr auto cons(ParserH head, ParserT tail) {
67+
return ConsParser<ParserH, ParserT>(head, tail);
68+
}
69+
3770
// Given a parser P for a wrapper class, invoke P, and if it succeeds return
3871
// the wrapped object.
3972
template <typename Parser> struct UnwrapParser {
@@ -1831,19 +1864,20 @@ TYPE_PARSER(
18311864
sourced("END"_tok >> Parser<OmpSectionsDirective>{}),
18321865
Parser<OmpClauseList>{})))
18331866

1834-
// OMP SECTION-BLOCK
1835-
1836-
TYPE_PARSER(construct<OpenMPSectionConstruct>(block))
1837-
1838-
TYPE_PARSER(maybe(startOmpLine >> "SECTION"_tok / endOmpLine) >>
1839-
construct<OmpSectionBlocks>(nonemptySeparated(
1840-
construct<OpenMPConstruct>(sourced(Parser<OpenMPSectionConstruct>{})),
1841-
startOmpLine >> "SECTION"_tok / endOmpLine)))
1867+
static constexpr auto sectionDir{
1868+
startOmpLine >> (predicated(OmpDirectiveNameParser{},
1869+
IsDirective(llvm::omp::Directive::OMPD_section)) >=
1870+
Parser<OmpDirectiveSpecification>{})};
18421871

18431872
// OMP SECTIONS (OpenMP 5.0 - 2.8.1), PARALLEL SECTIONS (OpenMP 5.0 - 2.13.3)
1844-
TYPE_PARSER(construct<OpenMPSectionsConstruct>(
1873+
TYPE_PARSER(sourced(construct<OpenMPSectionsConstruct>(
18451874
Parser<OmpBeginSectionsDirective>{} / endOmpLine,
1846-
Parser<OmpSectionBlocks>{}, Parser<OmpEndSectionsDirective>{} / endOmpLine))
1875+
cons( //
1876+
construct<OpenMPConstruct>(sourced(
1877+
construct<OpenMPSectionConstruct>(maybe(sectionDir), block))),
1878+
many(construct<OpenMPConstruct>(
1879+
sourced(construct<OpenMPSectionConstruct>(sectionDir, block))))),
1880+
Parser<OmpEndSectionsDirective>{} / endOmpLine)))
18471881

18481882
static bool IsExecutionPart(const OmpDirectiveName &name) {
18491883
return name.IsExecutionPart();

flang/lib/Parser/unparse.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2801,24 +2801,24 @@ class UnparseVisitor {
28012801
break;
28022802
}
28032803
}
2804-
void Unparse(const OmpSectionBlocks &x) {
2805-
for (const auto &y : x.v) {
2804+
void Unparse(const OpenMPSectionConstruct &x) {
2805+
if (auto &&dirSpec{
2806+
std::get<std::optional<OmpDirectiveSpecification>>(x.t)}) {
28062807
BeginOpenMP();
2807-
Word("!$OMP SECTION");
2808+
Word("!$OMP ");
2809+
Walk(*dirSpec);
28082810
Put("\n");
28092811
EndOpenMP();
2810-
// y.u is an OpenMPSectionConstruct
2811-
// (y.u).v is Block
2812-
Walk(std::get<OpenMPSectionConstruct>(y.u).v, "");
28132812
}
2813+
Walk(std::get<Block>(x.t), "");
28142814
}
28152815
void Unparse(const OpenMPSectionsConstruct &x) {
28162816
BeginOpenMP();
28172817
Word("!$OMP ");
28182818
Walk(std::get<OmpBeginSectionsDirective>(x.t));
28192819
Put("\n");
28202820
EndOpenMP();
2821-
Walk(std::get<OmpSectionBlocks>(x.t));
2821+
Walk(std::get<std::list<OpenMPConstruct>>(x.t), "");
28222822
BeginOpenMP();
28232823
Word("!$OMP END ");
28242824
Walk(std::get<OmpEndSectionsDirective>(x.t));

flang/lib/Semantics/check-omp-structure.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1057,10 +1057,11 @@ void OmpStructureChecker::Enter(const parser::OpenMPSectionsConstruct &x) {
10571057
PushContextAndClauseSets(beginDir.source, beginDir.v);
10581058
AddEndDirectiveClauses(std::get<parser::OmpClauseList>(endSectionsDir.t));
10591059

1060-
const auto &sectionBlocks{std::get<parser::OmpSectionBlocks>(x.t)};
1061-
for (const parser::OpenMPConstruct &block : sectionBlocks.v) {
1062-
CheckNoBranching(std::get<parser::OpenMPSectionConstruct>(block.u).v,
1063-
beginDir.v, beginDir.source);
1060+
const auto &sectionBlocks{std::get<std::list<parser::OpenMPConstruct>>(x.t)};
1061+
for (const parser::OpenMPConstruct &construct : sectionBlocks) {
1062+
auto &section{std::get<parser::OpenMPSectionConstruct>(construct.u)};
1063+
CheckNoBranching(
1064+
std::get<parser::Block>(section.t), beginDir.v, beginDir.source);
10641065
}
10651066
HasInvalidWorksharingNesting(
10661067
beginDir.source, llvm::omp::nestedWorkshareErrSet);

flang/test/Examples/omp-sections.f90

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ subroutine omp_sections()
1313
end subroutine omp_sections
1414

1515
!CHECK: - file: {{.*}}
16-
!CHECK: line: 9
16+
!CHECK: line: 8
1717
!CHECK: construct: section
1818
!CHECK: clauses: []
1919
!CHECK: - file: {{.*}}
20-
!CHECK: line: 11
20+
!CHECK: line: 10
2121
!CHECK: construct: section
2222
!CHECK: clauses: []
2323
!CHECK: - file: {{.*}}

0 commit comments

Comments
 (0)