[flang] [OpenMP] parse tree changes for standalone directives (flang-compiler/f18...
authorJinxin (Brian) Yang <jinxiny@nvidia.com>
Tue, 6 Aug 2019 18:59:40 +0000 (11:59 -0700)
committerGitHub <noreply@github.com>
Tue, 6 Aug 2019 18:59:40 +0000 (11:59 -0700)
* [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
flang/lib/parser/openmp-grammar.h
flang/lib/parser/parse-tree.h
flang/lib/parser/unparse.cc
flang/lib/semantics/check-omp-structure.cc
flang/lib/semantics/check-omp-structure.h
flang/test/semantics/omp-clause-validity01.f90

index ca61cc5..468f526 100644 (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)
index 9040d73..f4f2588 100644 (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
index 1e624b2..93b0136 100644 (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;
 };
 }
index 224a787..4810dc7 100644 (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) {
-    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<OmpStandaloneDirective>(x.t));
+    Walk(std::get<OmpSimpleStandaloneDirective>(x.t));
     Walk(std::get<OmpClauseList>(x.t));
     Put("\n");
     EndOpenMP();
index 26df196..5505fe8 100644 (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 |
index 3fd734c..928a5f6 100644 (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 &);
index e6fae7e..7f8c13f 100644 (file)
   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 |
         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