From c4e13f6be84ca391458f3ee5e83242be2145f2df Mon Sep 17 00:00:00 2001 From: "Jinxin (Brian) Yang" Date: Tue, 6 Aug 2019 11:59:40 -0700 Subject: [PATCH] [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@a77aa7ed84880927dea3e2b1bb6433350f99f1ac Reviewed-on: https://github.com/flang-compiler/f18/pull/627 --- flang/lib/parser/dump-parse-tree.h | 7 ++- flang/lib/parser/openmp-grammar.h | 61 ++++++++++++------------ flang/lib/parser/parse-tree.h | 44 ++++++++++-------- flang/lib/parser/unparse.cc | 43 ++++++++--------- flang/lib/semantics/check-omp-structure.cc | 64 ++++++++++++++++++++++++-- flang/lib/semantics/check-omp-structure.h | 10 ++++ flang/test/semantics/omp-clause-validity01.f90 | 21 ++++++++- 7 files changed, 169 insertions(+), 81 deletions(-) diff --git a/flang/lib/parser/dump-parse-tree.h b/flang/lib/parser/dump-parse-tree.h index ca61cc5..468f526 100644 --- a/flang/lib/parser/dump-parse-tree.h +++ b/flang/lib/parser/dump-parse-tree.h @@ -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) diff --git a/flang/lib/parser/openmp-grammar.h b/flang/lib/parser/openmp-grammar.h index 9040d73..f4f2588 100644 --- a/flang/lib/parser/openmp-grammar.h +++ b/flang/lib/parser/openmp-grammar.h @@ -297,25 +297,42 @@ TYPE_PARSER(sourced(construct( "TASKGROUP" >> pure(OmpCancelType::Type::Taskgroup))))) // Cancellation Point construct -TYPE_PARSER(construct( - sourced("CANCELLATION POINT" >> Parser{}))) +TYPE_PARSER(sourced(construct( + verbatim("CANCELLATION POINT"_tok), Parser{}))) // Cancel construct -TYPE_PARSER(construct( - sourced("CANCEL" >> Parser{}), - maybe("IF" >> parenthesized(scalarLogicalExpr)))) +TYPE_PARSER(sourced(construct(verbatim("CANCEL"_tok), + Parser{}, maybe("IF" >> parenthesized(scalarLogicalExpr))))) // Flush construct TYPE_PARSER(sourced(construct( - "FLUSH" >> maybe(parenthesized(Parser{}))))) + verbatim("FLUSH"_tok), maybe(parenthesized(Parser{}))))) -// Standalone directives -TYPE_PARSER(sourced(construct(first( +// Simple Standalone Directives +TYPE_PARSER(sourced(construct(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( + Parser{}, Parser{}))) + +// Standalone Constructs +TYPE_PARSER( + sourced(construct( + Parser{}) || + construct(Parser{}) || + construct(Parser{}) || + construct( + Parser{})) / + endOfLine) // Directives enclosing structured-block TYPE_PARSER(sourced(construct( @@ -454,17 +471,6 @@ TYPE_PARSER(construct(Parser{}, Parser{} / endOmpLine, block, Parser{})) -// Simple constructs without clauses -TYPE_PARSER( - sourced(construct(first( - "BARRIER" >> pure(OpenMPSimpleConstruct::Directive::Barrier), - "TASKWAIT" >> pure(OpenMPSimpleConstruct::Directive::Taskwait), - "TASKYIELD" >> pure(OpenMPSimpleConstruct::Directive::Taskyield)))) / - endOmpLine) - -TYPE_PARSER(construct( - Parser{}, Parser{} / endOmpLine)) - // OMP SINGLE TYPE_PARSER(startOmpLine >> construct(verbatim("END SINGLE"_tok), Parser{}) / @@ -507,21 +513,18 @@ TYPE_PARSER(construct(verbatim("SECTION"_tok) / endOmpLine)) TYPE_CONTEXT_PARSER("OpenMP construct"_en_US, startOmpLine >> - first(construct(Parser{}), - construct(Parser{}), - construct(Parser{}), + first(construct(Parser{}), construct(Parser{}), construct( Parser{}), construct(Parser{}), construct(Parser{}), construct(Parser{}), + // OpenMPBlockConstruct is attempted before + // OpenMPStandaloneConstruct to resolve !$OMP ORDERED + construct(Parser{}), construct(Parser{}), construct(Parser{}), - construct(Parser{}), - construct( - Parser{}), - construct(Parser{}), construct(Parser{}))) // END OMP Block directives diff --git a/flang/lib/parser/parse-tree.h b/flang/lib/parser/parse-tree.h index 1e624b2..93b0136 100644 --- a/flang/lib/parser/parse-tree.h +++ b/flang/lib/parser/parse-tree.h @@ -3666,38 +3666,47 @@ struct OmpCancelType { }; // CANCELLATION POINT -WRAPPER_CLASS(OpenMPCancellationPointConstruct, OmpCancelType); +struct OpenMPCancellationPointConstruct { + TUPLE_CLASS_BOILERPLATE(OpenMPCancellationPointConstruct); + CharBlock source; + std::tuple t; +}; // CANCEL struct OpenMPCancelConstruct { TUPLE_CLASS_BOILERPLATE(OpenMPCancelConstruct); WRAPPER_CLASS(If, ScalarLogicalExpr); - std::tuple> t; + CharBlock source; + std::tuple> t; }; // FLUSH struct OpenMPFlushConstruct { - WRAPPER_CLASS_BOILERPLATE(OpenMPFlushConstruct, std::optional); + TUPLE_CLASS_BOILERPLATE(OpenMPFlushConstruct); CharBlock source; + std::tuple> 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 t; }; struct OpenMPStandaloneConstruct { - TUPLE_CLASS_BOILERPLATE(OpenMPStandaloneConstruct); - std::tuple t; + UNION_CLASS_BOILERPLATE(OpenMPStandaloneConstruct); + CharBlock source; + std::variant + u; }; WRAPPER_CLASS(OmpEndBlockDirective, OmpBlockDirective); @@ -3722,13 +3731,10 @@ struct OpenMPLoopConstruct { struct OpenMPConstruct { UNION_CLASS_BOILERPLATE(OpenMPConstruct); - std::variant + std::variant u; }; } diff --git a/flang/lib/parser/unparse.cc b/flang/lib/parser/unparse.cc index 224a787..4810dc7 100644 --- a/flang/lib/parser/unparse.cc +++ b/flang/lib/parser/unparse.cc @@ -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(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>(x.t), ")"); Put("\n"); EndOpenMP(); } @@ -2338,21 +2346,10 @@ public: EndOpenMP(); } void Unparse(const OmpClauseList &x) { Walk(" ", x.v, " "); } - void Unparse(const OpenMPSimpleConstruct &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) { + void Unparse(const OpenMPSimpleStandaloneConstruct &x) { BeginOpenMP(); Word("!$OMP "); - Walk(std::get(x.t)); + Walk(std::get(x.t)); Walk(std::get(x.t)); Put("\n"); EndOpenMP(); diff --git a/flang/lib/semantics/check-omp-structure.cc b/flang/lib/semantics/check-omp-structure.cc index 26df196..5505fe8 100644 --- a/flang/lib/semantics/check-omp-structure.cc +++ b/flang/lib/semantics/check-omp-structure.cc @@ -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(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(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(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(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 | diff --git a/flang/lib/semantics/check-omp-structure.h b/flang/lib/semantics/check-omp-structure.h index 3fd734c..928a5f6 100644 --- a/flang/lib/semantics/check-omp-structure.h +++ b/flang/lib/semantics/check-omp-structure.h @@ -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 &); diff --git a/flang/test/semantics/omp-clause-validity01.f90 b/flang/test/semantics/omp-clause-validity01.f90 index e6fae7e..7f8c13f 100644 --- a/flang/test/semantics/omp-clause-validity01.f90 +++ b/flang/test/semantics/omp-clause-validity01.f90 @@ -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 -- 2.7.4