Skip to content

Commit cd26dd5

Browse files
authored
[flang][OpenMP] Use OmpDirectiveSpecification in simple directives (#131162)
The `OmpDirectiveSpecification` contains directive name, the list of arguments, and the list of clauses. It was introduced to store the directive specification in METADIRECTIVE, and could be reused everywhere a directive representation is needed. In the long term this would unify the handling of common directive properties, as well as creating actual constructs from METADIRECTIVE by linking the contained directive specification with any associated user code.
1 parent b350bc2 commit cd26dd5

File tree

16 files changed

+136
-130
lines changed

16 files changed

+136
-130
lines changed

flang/examples/FeatureList/FeatureList.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -533,7 +533,6 @@ struct NodeVisitor {
533533
READ_FEATURE(OmpOrderingModifier::Value)
534534
READ_FEATURE(OmpSectionBlocks)
535535
READ_FEATURE(OmpSectionsDirective)
536-
READ_FEATURE(OmpSimpleStandaloneDirective)
537536
READ_FEATURE(Only)
538537
READ_FEATURE(OpenACCAtomicConstruct)
539538
READ_FEATURE(OpenACCBlockConstruct)

flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -128,10 +128,17 @@ std::string OpenMPCounterVisitor::getName(const OpenMPConstruct &c) {
128128
Fortran::common::visitors{
129129
[&](const OpenMPStandaloneConstruct &c) -> std::string {
130130
return std::visit(
131-
[&](const auto &c) {
132-
// Get source from the directive or verbatim fields
133-
const CharBlock &source{std::get<0>(c.t).source};
134-
return normalize_construct_name(source.ToString());
131+
Fortran::common::visitors{
132+
[&](const OpenMPSimpleStandaloneConstruct &d) {
133+
const CharBlock &source{
134+
std::get<OmpDirectiveName>(d.v.t).source};
135+
return normalize_construct_name(source.ToString());
136+
},
137+
[&](const auto &c) {
138+
// Get source from the directive or verbatim fields
139+
const CharBlock &source{std::get<0>(c.t).source};
140+
return normalize_construct_name(source.ToString());
141+
},
135142
},
136143
c.u);
137144
},

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -663,7 +663,6 @@ class ParseTreeDumper {
663663
NODE_ENUM(OmpOrderingModifier, Value)
664664
NODE(parser, OmpSectionBlocks)
665665
NODE(parser, OmpSectionsDirective)
666-
NODE(parser, OmpSimpleStandaloneDirective)
667666
NODE(parser, OmpToClause)
668667
NODE(OmpToClause, Modifier)
669668
NODE(parser, Only)

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

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4934,15 +4934,10 @@ struct OpenMPFlushConstruct {
49344934
t;
49354935
};
49364936

4937-
struct OmpSimpleStandaloneDirective {
4938-
WRAPPER_CLASS_BOILERPLATE(OmpSimpleStandaloneDirective, llvm::omp::Directive);
4939-
CharBlock source;
4940-
};
4941-
49424937
struct OpenMPSimpleStandaloneConstruct {
4943-
TUPLE_CLASS_BOILERPLATE(OpenMPSimpleStandaloneConstruct);
4938+
WRAPPER_CLASS_BOILERPLATE(
4939+
OpenMPSimpleStandaloneConstruct, OmpDirectiveSpecification);
49444940
CharBlock source;
4945-
std::tuple<OmpSimpleStandaloneDirective, OmpClauseList> t;
49464941
};
49474942

49484943
struct OpenMPStandaloneConstruct {

flang/lib/Lower/OpenMP/OpenMP.cpp

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -408,8 +408,7 @@ extractOmpDirective(const parser::OpenMPConstruct &ompConstruct) {
408408
return common::visit(
409409
common::visitors{
410410
[](const parser::OpenMPSimpleStandaloneConstruct &c) {
411-
return std::get<parser::OmpSimpleStandaloneDirective>(c.t)
412-
.v;
411+
return c.v.DirId();
413412
},
414413
[](const parser::OpenMPFlushConstruct &c) {
415414
return llvm::omp::OMPD_flush;
@@ -3297,14 +3296,12 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
32973296
// OpenMPStandaloneConstruct visitors
32983297
//===----------------------------------------------------------------------===//
32993298

3300-
static void genOMP(
3301-
lower::AbstractConverter &converter, lower::SymMap &symTable,
3302-
semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval,
3303-
const parser::OpenMPSimpleStandaloneConstruct &simpleStandaloneConstruct) {
3304-
const auto &directive = std::get<parser::OmpSimpleStandaloneDirective>(
3305-
simpleStandaloneConstruct.t);
3306-
List<Clause> clauses = makeClauses(
3307-
std::get<parser::OmpClauseList>(simpleStandaloneConstruct.t), semaCtx);
3299+
static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
3300+
semantics::SemanticsContext &semaCtx,
3301+
lower::pft::Evaluation &eval,
3302+
const parser::OpenMPSimpleStandaloneConstruct &construct) {
3303+
const auto &directive = std::get<parser::OmpDirectiveName>(construct.v.t);
3304+
List<Clause> clauses = makeClauses(construct.v.Clauses(), semaCtx);
33083305
mlir::Location currentLocation = converter.genLocation(directive.source);
33093306

33103307
ConstructQueue queue{

flang/lib/Parser/openmp-parsers.cpp

Lines changed: 52 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,34 @@ constexpr auto operator>=(PA checker, PB parser) {
6464
return lookAhead(checker) >> parser;
6565
}
6666

67+
// This parser succeeds if the given parser succeeds, and the result
68+
// satisfies the given condition. Specifically, it succeeds if:
69+
// 1. The parser given as the argument succeeds, and
70+
// 2. The condition function (called with PA::resultType) returns true
71+
// for the result.
72+
template <typename PA, typename CF> struct PredicatedParser {
73+
using resultType = typename PA::resultType;
74+
75+
constexpr PredicatedParser(PA parser, CF condition)
76+
: parser_(parser), condition_(condition) {}
77+
78+
std::optional<resultType> Parse(ParseState &state) const {
79+
if (auto result{parser_.Parse(state)}; result && condition_(*result)) {
80+
return result;
81+
}
82+
return std::nullopt;
83+
}
84+
85+
private:
86+
const PA parser_;
87+
const CF condition_;
88+
};
89+
90+
template <typename PA, typename CF>
91+
constexpr auto predicated(PA parser, CF condition) {
92+
return PredicatedParser(parser, condition);
93+
}
94+
6795
/// Parse OpenMP directive name (this includes compound directives).
6896
struct OmpDirectiveNameParser {
6997
using resultType = OmpDirectiveName;
@@ -1027,6 +1055,8 @@ TYPE_PARSER(sourced(construct<OmpErrorDirective>(
10271055

10281056
// --- Parsers for directives and constructs --------------------------
10291057

1058+
TYPE_PARSER(sourced(construct<OmpDirectiveName>(OmpDirectiveNameParser{})))
1059+
10301060
OmpDirectiveSpecification static makeFlushFromOldSyntax1(Verbatim &&text,
10311061
std::optional<OmpClauseList> &&clauses,
10321062
std::optional<std::list<OmpArgument>> &&args,
@@ -1198,24 +1228,32 @@ TYPE_PARSER(sourced( //
11981228
verbatim("FLUSH"_tok), maybe(parenthesized(Parser<OmpObjectList>{})),
11991229
Parser<OmpClauseList>{}, pure(/*TrailingClauses=*/true))))
12001230

1201-
// Simple Standalone Directives
1202-
TYPE_PARSER(sourced(construct<OmpSimpleStandaloneDirective>(first(
1203-
"BARRIER" >> pure(llvm::omp::Directive::OMPD_barrier),
1204-
"ORDERED" >> pure(llvm::omp::Directive::OMPD_ordered),
1205-
"SCAN" >> pure(llvm::omp::Directive::OMPD_scan),
1206-
"TARGET ENTER DATA" >> pure(llvm::omp::Directive::OMPD_target_enter_data),
1207-
"TARGET EXIT DATA" >> pure(llvm::omp::Directive::OMPD_target_exit_data),
1208-
"TARGET UPDATE" >> pure(llvm::omp::Directive::OMPD_target_update),
1209-
"TASKWAIT" >> pure(llvm::omp::Directive::OMPD_taskwait),
1210-
"TASKYIELD" >> pure(llvm::omp::Directive::OMPD_taskyield)))))
1231+
static bool IsSimpleStandalone(const OmpDirectiveName &name) {
1232+
switch (name.v) {
1233+
case llvm::omp::Directive::OMPD_barrier:
1234+
case llvm::omp::Directive::OMPD_ordered:
1235+
case llvm::omp::Directive::OMPD_scan:
1236+
case llvm::omp::Directive::OMPD_target_enter_data:
1237+
case llvm::omp::Directive::OMPD_target_exit_data:
1238+
case llvm::omp::Directive::OMPD_target_update:
1239+
case llvm::omp::Directive::OMPD_taskwait:
1240+
case llvm::omp::Directive::OMPD_taskyield:
1241+
return true;
1242+
default:
1243+
return false;
1244+
}
1245+
}
12111246

1212-
TYPE_PARSER(sourced(construct<OpenMPSimpleStandaloneConstruct>(
1213-
Parser<OmpSimpleStandaloneDirective>{}, Parser<OmpClauseList>{})))
1247+
TYPE_PARSER(sourced( //
1248+
construct<OpenMPSimpleStandaloneConstruct>(
1249+
predicated(OmpDirectiveNameParser{}, IsSimpleStandalone) >=
1250+
Parser<OmpDirectiveSpecification>{})))
12141251

12151252
// Standalone Constructs
12161253
TYPE_PARSER(
1217-
sourced(construct<OpenMPStandaloneConstruct>(
1218-
Parser<OpenMPSimpleStandaloneConstruct>{}) ||
1254+
sourced( //
1255+
construct<OpenMPStandaloneConstruct>(
1256+
Parser<OpenMPSimpleStandaloneConstruct>{}) ||
12191257
construct<OpenMPStandaloneConstruct>(Parser<OpenMPFlushConstruct>{}) ||
12201258
// Try CANCELLATION POINT before CANCEL.
12211259
construct<OpenMPStandaloneConstruct>(

flang/lib/Parser/unparse.cpp

Lines changed: 1 addition & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2465,37 +2465,6 @@ class UnparseVisitor {
24652465
}
24662466
}
24672467
void Unparse(const OmpObjectList &x) { Walk(x.v, ","); }
2468-
void Unparse(const OmpSimpleStandaloneDirective &x) {
2469-
switch (x.v) {
2470-
case llvm::omp::Directive::OMPD_barrier:
2471-
Word("BARRIER ");
2472-
break;
2473-
case llvm::omp::Directive::OMPD_scan:
2474-
Word("SCAN ");
2475-
break;
2476-
case llvm::omp::Directive::OMPD_taskwait:
2477-
Word("TASKWAIT ");
2478-
break;
2479-
case llvm::omp::Directive::OMPD_taskyield:
2480-
Word("TASKYIELD ");
2481-
break;
2482-
case llvm::omp::Directive::OMPD_target_enter_data:
2483-
Word("TARGET ENTER DATA ");
2484-
break;
2485-
case llvm::omp::Directive::OMPD_target_exit_data:
2486-
Word("TARGET EXIT DATA ");
2487-
break;
2488-
case llvm::omp::Directive::OMPD_target_update:
2489-
Word("TARGET UPDATE ");
2490-
break;
2491-
case llvm::omp::Directive::OMPD_ordered:
2492-
Word("ORDERED ");
2493-
break;
2494-
default:
2495-
// Nothing to be done
2496-
break;
2497-
}
2498-
}
24992468
void Unparse(const OmpBlockDirective &x) {
25002469
switch (x.v) {
25012470
case llvm::omp::Directive::OMPD_masked:
@@ -2924,8 +2893,7 @@ class UnparseVisitor {
29242893
void Unparse(const OpenMPSimpleStandaloneConstruct &x) {
29252894
BeginOpenMP();
29262895
Word("!$OMP ");
2927-
Walk(std::get<OmpSimpleStandaloneDirective>(x.t));
2928-
Walk(std::get<OmpClauseList>(x.t));
2896+
Walk(x.v);
29292897
Put("\n");
29302898
EndOpenMP();
29312899
}

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

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -878,21 +878,17 @@ void OmpStructureChecker::CheckSIMDNest(const parser::OpenMPConstruct &c) {
878878
}
879879
},
880880
[&](const parser::OpenMPStandaloneConstruct &c) {
881-
if (const auto &simpleConstruct =
882-
std::get_if<parser::OpenMPSimpleStandaloneConstruct>(
883-
&c.u)) {
884-
const auto &dir{std::get<parser::OmpSimpleStandaloneDirective>(
885-
simpleConstruct->t)};
886-
if (dir.v == llvm::omp::Directive::OMPD_ordered) {
887-
const auto &clauses{
888-
std::get<parser::OmpClauseList>(simpleConstruct->t)};
889-
for (const auto &clause : clauses.v) {
890-
if (std::get_if<parser::OmpClause::Simd>(&clause.u)) {
881+
if (auto *ssc{std::get_if<parser::OpenMPSimpleStandaloneConstruct>(
882+
&c.u)}) {
883+
llvm::omp::Directive dirId{ssc->v.DirId()};
884+
if (dirId == llvm::omp::Directive::OMPD_ordered) {
885+
for (const parser::OmpClause &x : ssc->v.Clauses().v) {
886+
if (x.Id() == llvm::omp::Clause::OMPC_simd) {
891887
eligibleSIMD = true;
892888
break;
893889
}
894890
}
895-
} else if (dir.v == llvm::omp::Directive::OMPD_scan) {
891+
} else if (dirId == llvm::omp::Directive::OMPD_scan) {
896892
eligibleSIMD = true;
897893
}
898894
}
@@ -944,15 +940,15 @@ void OmpStructureChecker::CheckTargetNest(const parser::OpenMPConstruct &c) {
944940
common::visit(
945941
common::visitors{
946942
[&](const parser::OpenMPSimpleStandaloneConstruct &c) {
947-
const auto &dir{
948-
std::get<parser::OmpSimpleStandaloneDirective>(c.t)};
949-
if (dir.v == llvm::omp::Directive::OMPD_target_update ||
950-
dir.v ==
951-
llvm::omp::Directive::OMPD_target_enter_data ||
952-
dir.v ==
953-
llvm::omp::Directive::OMPD_target_exit_data) {
943+
switch (llvm::omp::Directive dirId{c.v.DirId()}) {
944+
case llvm::omp::Directive::OMPD_target_update:
945+
case llvm::omp::Directive::OMPD_target_enter_data:
946+
case llvm::omp::Directive::OMPD_target_exit_data:
954947
eligibleTarget = false;
955-
ineligibleTargetDir = dir.v;
948+
ineligibleTargetDir = dirId;
949+
break;
950+
default:
951+
break;
956952
}
957953
},
958954
[&](const auto &c) {},
@@ -1978,7 +1974,7 @@ void OmpStructureChecker::Leave(const parser::OpenMPAllocatorsConstruct &x) {
19781974

19791975
void OmpStructureChecker::CheckScan(
19801976
const parser::OpenMPSimpleStandaloneConstruct &x) {
1981-
if (std::get<parser::OmpClauseList>(x.t).v.size() != 1) {
1977+
if (x.v.Clauses().v.size() != 1) {
19821978
context_.Say(x.source,
19831979
"Exactly one of EXCLUSIVE or INCLUSIVE clause is expected"_err_en_US);
19841980
}
@@ -2183,7 +2179,7 @@ void OmpStructureChecker::CheckDependenceType(
21832179

21842180
void OmpStructureChecker::Enter(
21852181
const parser::OpenMPSimpleStandaloneConstruct &x) {
2186-
const auto &dir{std::get<parser::OmpSimpleStandaloneDirective>(x.t)};
2182+
const auto &dir{std::get<parser::OmpDirectiveName>(x.v.t)};
21872183
PushContextAndClauseSets(dir.source, dir.v);
21882184
switch (dir.v) {
21892185
case llvm::omp::Directive::OMPD_barrier:

flang/lib/Semantics/resolve-directives.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,7 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
356356
return true;
357357
}
358358
void Post(const parser::OmpDirectiveSpecification &) { PopContext(); }
359+
359360
bool Pre(const parser::OmpMetadirectiveDirective &x) {
360361
PushContext(x.source, llvm::omp::Directive::OMPD_metadirective);
361362
return true;
@@ -1652,8 +1653,7 @@ void OmpAttributeVisitor::Post(const parser::OpenMPBlockConstruct &x) {
16521653

16531654
bool OmpAttributeVisitor::Pre(
16541655
const parser::OpenMPSimpleStandaloneConstruct &x) {
1655-
const auto &standaloneDir{
1656-
std::get<parser::OmpSimpleStandaloneDirective>(x.t)};
1656+
const auto &standaloneDir{std::get<parser::OmpDirectiveName>(x.v.t)};
16571657
switch (standaloneDir.v) {
16581658
case llvm::omp::Directive::OMPD_barrier:
16591659
case llvm::omp::Directive::OMPD_ordered:

flang/lib/Semantics/resolve-names.cpp

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1440,11 +1440,13 @@ class OmpVisitor : public virtual DeclarationVisitor {
14401440
static bool NeedsScope(const parser::OpenMPBlockConstruct &);
14411441
static bool NeedsScope(const parser::OmpClause &);
14421442

1443-
bool Pre(const parser::OpenMPRequiresConstruct &x) {
1444-
AddOmpSourceRange(x.source);
1443+
bool Pre(const parser::OmpMetadirectiveDirective &) {
1444+
++metaLevel_;
14451445
return true;
14461446
}
1447-
bool Pre(const parser::OmpSimpleStandaloneDirective &x) {
1447+
void Post(const parser::OmpMetadirectiveDirective &) { --metaLevel_; }
1448+
1449+
bool Pre(const parser::OpenMPRequiresConstruct &x) {
14481450
AddOmpSourceRange(x.source);
14491451
return true;
14501452
}
@@ -1656,6 +1658,7 @@ class OmpVisitor : public virtual DeclarationVisitor {
16561658
const parser::OmpClauseList &clauses);
16571659
void ProcessReductionSpecifier(const parser::OmpReductionSpecifier &spec,
16581660
const std::optional<parser::OmpClauseList> &clauses);
1661+
int metaLevel_{0};
16591662
};
16601663

16611664
bool OmpVisitor::NeedsScope(const parser::OpenMPBlockConstruct &x) {
@@ -1801,12 +1804,16 @@ void OmpVisitor::ProcessReductionSpecifier(
18011804
}
18021805

18031806
bool OmpVisitor::Pre(const parser::OmpDirectiveSpecification &x) {
1804-
// OmpDirectiveSpecification is only used in METADIRECTIVE at the moment.
1805-
// Since it contains directives and clauses, some semantic checks may
1806-
// not be applicable.
1807-
// Disable the semantic analysis for it for now to allow the compiler to
1808-
// parse METADIRECTIVE without flagging errors.
18091807
AddOmpSourceRange(x.source);
1808+
if (metaLevel_ == 0) {
1809+
// Not in METADIRECTIVE.
1810+
return true;
1811+
}
1812+
1813+
// If OmpDirectiveSpecification (which contains clauses) is a part of
1814+
// METADIRECTIVE, some semantic checks may not be applicable.
1815+
// Disable the semantic analysis for it in such cases to allow the compiler
1816+
// to parse METADIRECTIVE without flagging errors.
18101817
auto &maybeArgs{std::get<std::optional<std::list<parser::OmpArgument>>>(x.t)};
18111818
auto &maybeClauses{std::get<std::optional<parser::OmpClauseList>>(x.t)};
18121819

0 commit comments

Comments
 (0)