[flang] [OpenMP] parse tree changes for standalone directives (flang-compiler/f18#627)

* [OpenMP] parse tree changes for standalone directives

1. Put all standalone directives except FLUSH, CANCEL, and CANCELLATION POINT
   into one `OpenMPSimpleStandaloneConstruct` (for no-clause directive,
   validity checks will be deferred to Semantics). A top-level class will
   include all the standalone directive nodes. This simplies the logic a lot.

2. All the standalone directives now have their own source provenance for
   directive name itself.

3. Change check-omp-structure.* to avoid assertions

4. Add basic tests for standalone directives, more will be added during
   the clause validity checks in Semantics

* Resolve !$OMP ORDERED ambiguity by attempting block construct first - Peter

Original-commit: flang-compiler/f18@a77aa7ed84
Reviewed-on: https://github.com/flang-compiler/f18/pull/627
This commit is contained in:
Jinxin (Brian) Yang 2019-08-06 11:59:40 -07:00 committed by GitHub
parent fb30d812e7
commit c4e13f6be8
7 changed files with 169 additions and 81 deletions

View file

@ -512,8 +512,8 @@ public:
NODE(parser, OmpScheduleModifierType)
NODE_ENUM(parser::OmpScheduleModifierType, ModType)
NODE(parser, OmpSection)
NODE(parser, OmpStandaloneDirective)
NODE_ENUM(parser::OmpStandaloneDirective, Directive)
NODE(parser, OmpSimpleStandaloneDirective)
NODE_ENUM(parser::OmpSimpleStandaloneDirective, Directive)
NODE(parser, Only)
NODE(parser, OpenMPAtomicConstruct)
NODE(parser, OpenMPBlockConstruct)
@ -535,8 +535,7 @@ public:
NODE(parser, OpenMPEndLoopDirective)
NODE(parser, OpenMPFlushConstruct)
NODE(parser, OpenMPLoopConstruct)
NODE(parser, OpenMPSimpleConstruct)
NODE_ENUM(parser::OpenMPSimpleConstruct, Directive)
NODE(parser, OpenMPSimpleStandaloneConstruct)
NODE(parser, OpenMPStandaloneConstruct)
NODE(parser, OpenMPSectionsConstruct)
NODE(parser, OpenMPSingleConstruct)

View file

@ -297,25 +297,42 @@ TYPE_PARSER(sourced(construct<OmpCancelType>(
"TASKGROUP" >> pure(OmpCancelType::Type::Taskgroup)))))
// Cancellation Point construct
TYPE_PARSER(construct<OpenMPCancellationPointConstruct>(
sourced("CANCELLATION POINT" >> Parser<OmpCancelType>{})))
TYPE_PARSER(sourced(construct<OpenMPCancellationPointConstruct>(
verbatim("CANCELLATION POINT"_tok), Parser<OmpCancelType>{})))
// Cancel construct
TYPE_PARSER(construct<OpenMPCancelConstruct>(
sourced("CANCEL" >> Parser<OmpCancelType>{}),
maybe("IF" >> parenthesized(scalarLogicalExpr))))
TYPE_PARSER(sourced(construct<OpenMPCancelConstruct>(verbatim("CANCEL"_tok),
Parser<OmpCancelType>{}, maybe("IF" >> parenthesized(scalarLogicalExpr)))))
// Flush construct
TYPE_PARSER(sourced(construct<OpenMPFlushConstruct>(
"FLUSH" >> maybe(parenthesized(Parser<OmpObjectList>{})))))
verbatim("FLUSH"_tok), maybe(parenthesized(Parser<OmpObjectList>{})))))
// Standalone directives
TYPE_PARSER(sourced(construct<OmpStandaloneDirective>(first(
// Simple Standalone Directives
TYPE_PARSER(sourced(construct<OmpSimpleStandaloneDirective>(first(
"BARRIER" >> pure(OmpSimpleStandaloneDirective::Directive::Barrier),
"ORDERED" >> pure(OmpSimpleStandaloneDirective::Directive::Ordered),
"TARGET ENTER DATA" >>
pure(OmpStandaloneDirective::Directive::TargetEnterData),
pure(OmpSimpleStandaloneDirective::Directive::TargetEnterData),
"TARGET EXIT DATA" >>
pure(OmpStandaloneDirective::Directive::TargetExitData),
"TARGET UPDATE" >> pure(OmpStandaloneDirective::Directive::TargetUpdate)))))
pure(OmpSimpleStandaloneDirective::Directive::TargetExitData),
"TARGET UPDATE" >>
pure(OmpSimpleStandaloneDirective::Directive::TargetUpdate),
"TASKWAIT" >> pure(OmpSimpleStandaloneDirective::Directive::Taskwait),
"TASKYIELD" >> pure(OmpSimpleStandaloneDirective::Directive::Taskyield)))))
TYPE_PARSER(sourced(construct<OpenMPSimpleStandaloneConstruct>(
Parser<OmpSimpleStandaloneDirective>{}, Parser<OmpClauseList>{})))
// Standalone Constructs
TYPE_PARSER(
sourced(construct<OpenMPStandaloneConstruct>(
Parser<OpenMPSimpleStandaloneConstruct>{}) ||
construct<OpenMPStandaloneConstruct>(Parser<OpenMPFlushConstruct>{}) ||
construct<OpenMPStandaloneConstruct>(Parser<OpenMPCancelConstruct>{}) ||
construct<OpenMPStandaloneConstruct>(
Parser<OpenMPCancellationPointConstruct>{})) /
endOfLine)
// Directives enclosing structured-block
TYPE_PARSER(sourced(construct<OmpBlockDirective>(
@ -454,17 +471,6 @@ TYPE_PARSER(construct<OpenMPBlockConstruct>(Parser<OmpBlockDirective>{},
Parser<OmpClauseList>{} / endOmpLine, block,
Parser<OmpEndBlockDirective>{}))
// Simple constructs without clauses
TYPE_PARSER(
sourced(construct<OpenMPSimpleConstruct>(first(
"BARRIER" >> pure(OpenMPSimpleConstruct::Directive::Barrier),
"TASKWAIT" >> pure(OpenMPSimpleConstruct::Directive::Taskwait),
"TASKYIELD" >> pure(OpenMPSimpleConstruct::Directive::Taskyield)))) /
endOmpLine)
TYPE_PARSER(construct<OpenMPStandaloneConstruct>(
Parser<OmpStandaloneDirective>{}, Parser<OmpClauseList>{} / endOmpLine))
// OMP SINGLE
TYPE_PARSER(startOmpLine >> construct<OmpEndSingle>(verbatim("END SINGLE"_tok),
Parser<OmpClauseList>{}) /
@ -507,21 +513,18 @@ TYPE_PARSER(construct<OmpSection>(verbatim("SECTION"_tok) / endOmpLine))
TYPE_CONTEXT_PARSER("OpenMP construct"_en_US,
startOmpLine >>
first(construct<OpenMPConstruct>(Parser<OpenMPStandaloneConstruct>{}),
construct<OpenMPConstruct>(Parser<OpenMPSimpleConstruct>{}),
construct<OpenMPConstruct>(Parser<OpenMPSingleConstruct>{}),
first(construct<OpenMPConstruct>(Parser<OpenMPSingleConstruct>{}),
construct<OpenMPConstruct>(Parser<OpenMPSectionsConstruct>{}),
construct<OpenMPConstruct>(
Parser<OpenMPParallelSectionsConstruct>{}),
construct<OpenMPConstruct>(Parser<OpenMPWorkshareConstruct>{}),
construct<OpenMPConstruct>(Parser<OpenMPLoopConstruct>{}),
construct<OpenMPConstruct>(Parser<OpenMPBlockConstruct>{}),
// OpenMPBlockConstruct is attempted before
// OpenMPStandaloneConstruct to resolve !$OMP ORDERED
construct<OpenMPConstruct>(Parser<OpenMPStandaloneConstruct>{}),
construct<OpenMPConstruct>(Parser<OpenMPAtomicConstruct>{}),
construct<OpenMPConstruct>(Parser<OpenMPCriticalConstruct>{}),
construct<OpenMPConstruct>(Parser<OpenMPCancelConstruct>{}),
construct<OpenMPConstruct>(
Parser<OpenMPCancellationPointConstruct>{}),
construct<OpenMPConstruct>(Parser<OpenMPFlushConstruct>{}),
construct<OpenMPConstruct>(Parser<OmpSection>{})))
// END OMP Block directives

View file

@ -3666,38 +3666,47 @@ struct OmpCancelType {
};
// CANCELLATION POINT
WRAPPER_CLASS(OpenMPCancellationPointConstruct, OmpCancelType);
struct OpenMPCancellationPointConstruct {
TUPLE_CLASS_BOILERPLATE(OpenMPCancellationPointConstruct);
CharBlock source;
std::tuple<Verbatim, OmpCancelType> t;
};
// CANCEL
struct OpenMPCancelConstruct {
TUPLE_CLASS_BOILERPLATE(OpenMPCancelConstruct);
WRAPPER_CLASS(If, ScalarLogicalExpr);
std::tuple<OmpCancelType, std::optional<If>> t;
CharBlock source;
std::tuple<Verbatim, OmpCancelType, std::optional<If>> t;
};
// FLUSH
struct OpenMPFlushConstruct {
WRAPPER_CLASS_BOILERPLATE(OpenMPFlushConstruct, std::optional<OmpObjectList>);
TUPLE_CLASS_BOILERPLATE(OpenMPFlushConstruct);
CharBlock source;
std::tuple<Verbatim, std::optional<OmpObjectList>> t;
};
// These simple constructs do not have clauses.
struct OpenMPSimpleConstruct {
ENUM_CLASS(Directive, Barrier, Taskwait, Taskyield)
WRAPPER_CLASS_BOILERPLATE(OpenMPSimpleConstruct, Directive);
struct OmpSimpleStandaloneDirective {
ENUM_CLASS(Directive, Barrier, Taskwait, Taskyield, TargetEnterData,
TargetExitData, TargetUpdate, Ordered)
WRAPPER_CLASS_BOILERPLATE(OmpSimpleStandaloneDirective, Directive);
CharBlock source;
};
// Standalone constructs; these can have clauses.
struct OmpStandaloneDirective {
ENUM_CLASS(Directive, TargetEnterData, TargetExitData, TargetUpdate)
WRAPPER_CLASS_BOILERPLATE(OmpStandaloneDirective, Directive);
struct OpenMPSimpleStandaloneConstruct {
TUPLE_CLASS_BOILERPLATE(OpenMPSimpleStandaloneConstruct);
CharBlock source;
std::tuple<OmpSimpleStandaloneDirective, OmpClauseList> t;
};
struct OpenMPStandaloneConstruct {
TUPLE_CLASS_BOILERPLATE(OpenMPStandaloneConstruct);
std::tuple<OmpStandaloneDirective, OmpClauseList> t;
UNION_CLASS_BOILERPLATE(OpenMPStandaloneConstruct);
CharBlock source;
std::variant<OpenMPSimpleStandaloneConstruct, OpenMPFlushConstruct,
OpenMPCancelConstruct, OpenMPCancellationPointConstruct>
u;
};
WRAPPER_CLASS(OmpEndBlockDirective, OmpBlockDirective);
@ -3722,13 +3731,10 @@ struct OpenMPLoopConstruct {
struct OpenMPConstruct {
UNION_CLASS_BOILERPLATE(OpenMPConstruct);
std::variant<OpenMPStandaloneConstruct, OpenMPSimpleConstruct,
OpenMPSingleConstruct, OpenMPSectionsConstruct,
OpenMPParallelSectionsConstruct, OpenMPWorkshareConstruct,
OpenMPLoopConstruct, OpenMPBlockConstruct,
OpenMPCancellationPointConstruct, OpenMPCancelConstruct,
OpenMPFlushConstruct, OpenMPAtomicConstruct, OpenMPCriticalConstruct,
OmpSection>
std::variant<OpenMPStandaloneConstruct, OpenMPSingleConstruct,
OpenMPSectionsConstruct, OpenMPParallelSectionsConstruct,
OpenMPWorkshareConstruct, OpenMPLoopConstruct, OpenMPBlockConstruct,
OpenMPAtomicConstruct, OpenMPCriticalConstruct, OmpSection>
u;
};
}

View file

@ -2046,17 +2046,29 @@ public:
}
}
void Unparse(const OmpObjectList &x) { Walk(x.v, ","); }
void Unparse(const OmpStandaloneDirective &x) {
void Unparse(const OmpSimpleStandaloneDirective &x) {
switch (x.v) {
case OmpStandaloneDirective::Directive::TargetEnterData:
case OmpSimpleStandaloneDirective::Directive::Barrier:
Word("BARRIER ");
break;
case OmpSimpleStandaloneDirective::Directive::Taskwait:
Word("TASKWAIT ");
break;
case OmpSimpleStandaloneDirective::Directive::Taskyield:
Word("TASKYIELD ");
break;
case OmpSimpleStandaloneDirective::Directive::TargetEnterData:
Word("TARGET ENTER DATA ");
break;
case OmpStandaloneDirective::Directive::TargetExitData:
case OmpSimpleStandaloneDirective::Directive::TargetExitData:
Word("TARGET EXIT DATA ");
break;
case OmpStandaloneDirective::Directive::TargetUpdate:
case OmpSimpleStandaloneDirective::Directive::TargetUpdate:
Word("TARGET UPDATE ");
break;
case OmpSimpleStandaloneDirective::Directive::Ordered:
Word("ORDERED ");
break;
}
}
void Unparse(const OmpBlockDirective &x) {
@ -2305,7 +2317,7 @@ public:
void Unparse(const OpenMPCancellationPointConstruct &x) {
BeginOpenMP();
Word("!$OMP CANCELLATION POINT ");
Walk(x.v);
Walk(std::get<OmpCancelType>(x.t));
Put("\n");
EndOpenMP();
}
@ -2320,11 +2332,7 @@ public:
void Unparse(const OpenMPFlushConstruct &x) {
BeginOpenMP();
Word("!$OMP FLUSH");
if ((x.v).has_value()) {
Put("(");
Walk(x.v);
Put(")");
}
Walk("(", std::get<std::optional<OmpObjectList>>(x.t), ")");
Put("\n");
EndOpenMP();
}
@ -2338,21 +2346,10 @@ public:
EndOpenMP();
}
void Unparse(const OmpClauseList &x) { Walk(" ", x.v, " "); }
void Unparse(const OpenMPSimpleConstruct &x) {
void Unparse(const OpenMPSimpleStandaloneConstruct &x) {
BeginOpenMP();
Word("!$OMP ");
switch (x.v) {
case OpenMPSimpleConstruct::Directive::Barrier: Word("BARRIER"); break;
case OpenMPSimpleConstruct::Directive::Taskwait: Word("TASKWAIT"); break;
case OpenMPSimpleConstruct::Directive::Taskyield: Word("TASKYIELD"); break;
}
Put("\n");
EndOpenMP();
}
void Unparse(const OpenMPStandaloneConstruct &x) {
BeginOpenMP();
Word("!$OMP ");
Walk(std::get<OmpStandaloneDirective>(x.t));
Walk(std::get<OmpSimpleStandaloneDirective>(x.t));
Walk(std::get<OmpClauseList>(x.t));
Put("\n");
EndOpenMP();

View file

@ -104,7 +104,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPSectionsConstruct &x) {
SetContextAllowed(allowed);
}
void OmpStructureChecker::Leave(const parser::OpenMPSectionsConstruct &x) {
void OmpStructureChecker::Leave(const parser::OpenMPSectionsConstruct &) {
ompContext_.pop_back();
}
@ -126,7 +126,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPSingleConstruct &x) {
SetContextAllowed(allowed);
}
void OmpStructureChecker::Leave(const parser::OpenMPSingleConstruct &x) {
void OmpStructureChecker::Leave(const parser::OpenMPSingleConstruct &) {
ompContext_.pop_back();
}
@ -140,7 +140,7 @@ void OmpStructureChecker::Enter(const parser::OmpEndSingle &x) {
SetContextAllowedOnce(allowedOnce);
}
void OmpStructureChecker::Leave(const parser::OmpEndSingle &x) {
void OmpStructureChecker::Leave(const parser::OmpEndSingle &) {
ompContext_.pop_back();
}
@ -149,7 +149,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPWorkshareConstruct &x) {
PushContext(dir.source, OmpDirective::WORKSHARE);
}
void OmpStructureChecker::Leave(const parser::OpenMPWorkshareConstruct &x) {
void OmpStructureChecker::Leave(const parser::OpenMPWorkshareConstruct &) {
ompContext_.pop_back();
}
@ -158,10 +158,64 @@ void OmpStructureChecker::Enter(const parser::OpenMPDeclareSimdConstruct &x) {
PushContext(dir.source, OmpDirective::DECLARE_SIMD);
}
void OmpStructureChecker::Leave(const parser::OpenMPDeclareSimdConstruct &x) {
void OmpStructureChecker::Leave(const parser::OpenMPDeclareSimdConstruct &) {
ompContext_.pop_back();
}
void OmpStructureChecker::Enter(
const parser::OpenMPSimpleStandaloneConstruct &x) {
const auto &dir{std::get<parser::OmpSimpleStandaloneDirective>(x.t)};
PushContext(dir.source);
}
void OmpStructureChecker::Leave(
const parser::OpenMPSimpleStandaloneConstruct &) {
ompContext_.pop_back();
}
void OmpStructureChecker::Enter(const parser::OpenMPFlushConstruct &x) {
const auto &dir{std::get<parser::Verbatim>(x.t)};
PushContext(dir.source, OmpDirective::FLUSH);
}
void OmpStructureChecker::Leave(const parser::OpenMPFlushConstruct &) {
ompContext_.pop_back();
}
void OmpStructureChecker::Enter(const parser::OpenMPCancelConstruct &x) {
const auto &dir{std::get<parser::Verbatim>(x.t)};
PushContext(dir.source, OmpDirective::CANCEL);
}
void OmpStructureChecker::Leave(const parser::OpenMPCancelConstruct &) {
ompContext_.pop_back();
}
void OmpStructureChecker::Enter(
const parser::OpenMPCancellationPointConstruct &x) {
const auto &dir{std::get<parser::Verbatim>(x.t)};
PushContext(dir.source, OmpDirective::CANCELLATION_POINT);
}
void OmpStructureChecker::Leave(
const parser::OpenMPCancellationPointConstruct &) {
ompContext_.pop_back();
}
void OmpStructureChecker::Enter(const parser::OmpSimpleStandaloneDirective &x) {
switch (x.v) {
case parser::OmpSimpleStandaloneDirective::Directive::Ordered: {
// 2.13.8 ordered-construct-clause -> depend-clause
SetContextDirectiveEnum(OmpDirective::ORDERED);
OmpClauseSet allowed{OmpClause::DEPEND};
SetContextAllowed(allowed);
}
default:
// TODO others
break;
}
}
void OmpStructureChecker::Enter(const parser::OmpBlockDirective &x) {
switch (x.v) {
// 2.5 parallel-clause -> if-clause |

View file

@ -79,6 +79,16 @@ public:
void Enter(const parser::OpenMPDeclareSimdConstruct &);
void Leave(const parser::OpenMPDeclareSimdConstruct &);
void Enter(const parser::OpenMPSimpleStandaloneConstruct &);
void Leave(const parser::OpenMPSimpleStandaloneConstruct &);
void Enter(const parser::OmpSimpleStandaloneDirective &);
void Enter(const parser::OpenMPFlushConstruct &);
void Leave(const parser::OpenMPFlushConstruct &);
void Enter(const parser::OpenMPCancelConstruct &);
void Leave(const parser::OpenMPCancelConstruct &);
void Enter(const parser::OpenMPCancellationPointConstruct &);
void Leave(const parser::OpenMPCancellationPointConstruct &);
void Leave(const parser::OmpClauseList &);
void Enter(const parser::OmpClause &);
void Enter(const parser::OmpNowait &);

View file

@ -25,6 +25,10 @@
integer :: b = 128
integer :: c = 32
integer, parameter :: num = 16
real(8) :: arrayA(256), arrayB(512)
arrayA = 1.414
arrayB = 3.14
N = 1024
! 2.5 parallel-clause -> if-clause |
@ -276,4 +280,19 @@
a = 3.14
enddo
enddo
end
! Standalone Directives (basic)
!$omp taskyield
!$omp barrier
!$omp taskwait
! !$omp target enter data map(to:arrayA) map(alloc:arrayB)
! !$omp target update from(arrayA) to(arrayB)
! !$omp target exit data map(from:arrayA) map(delete:arrayB)
!$omp ordered depend(source)
!ERROR: Internal: no symbol found for 'i'
!$omp ordered depend(sink:i-1)
!$omp flush (c)
!$omp cancel DO
!$omp cancellation point parallel
end program