[llvm-branch-commits] [flang] [flang][OpenMP] Use new modifier code in ORDER and SCHEDULE clauses (PR #117081)

Krzysztof Parzyszek via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Wed Nov 20 16:19:05 PST 2024


https://github.com/kparzysz created https://github.com/llvm/llvm-project/pull/117081

This actually simplifies the AST node for the schedule clause: the two allowed modifiers can be easily classified as the ordering-modifier and the chunk-modifier during parsing without the need to create additional classes.

>From 43bdfcdb48328fcdfe762734bd5a4c1df3987c4b Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Mon, 18 Nov 2024 13:01:30 -0600
Subject: [PATCH] [flang][OpenMP] Use new modifier code in ORDER and SCHEDULE
 clauses

This actually simplifies the AST node for the schedule clause: the two
allowed modifiers can be easily classified as the ordering-modifier and
the chunk-modifier during parsing without the need to create additional
classes.
---
 flang/examples/FeatureList/FeatureList.cpp    | 13 ++-
 .../FlangOmpReport/FlangOmpReportVisitor.cpp  | 10 ++-
 .../FlangOmpReport/FlangOmpReportVisitor.h    |  3 +-
 flang/include/flang/Parser/dump-parse-tree.h  | 17 ++--
 flang/include/flang/Parser/parse-tree.h       | 81 ++++++++++++-------
 .../flang/Semantics/openmp-modifiers.h        |  6 ++
 flang/lib/Lower/OpenMP/Clauses.cpp            | 75 ++++++-----------
 flang/lib/Lower/OpenMP/Clauses.h              | 10 +++
 flang/lib/Parser/openmp-parsers.cpp           | 71 ++++++++--------
 flang/lib/Parser/unparse.cpp                  | 23 +++---
 flang/lib/Semantics/check-omp-structure.cpp   | 58 ++++++-------
 flang/lib/Semantics/check-omp-structure.h     |  2 -
 flang/lib/Semantics/openmp-modifiers.cpp      | 48 +++++++++++
 flang/test/Parser/OpenMP/order-clause01.f90   | 50 ++++++------
 14 files changed, 263 insertions(+), 204 deletions(-)

diff --git a/flang/examples/FeatureList/FeatureList.cpp b/flang/examples/FeatureList/FeatureList.cpp
index 753ecb918a9ccb..e1c42586c62c94 100644
--- a/flang/examples/FeatureList/FeatureList.cpp
+++ b/flang/examples/FeatureList/FeatureList.cpp
@@ -505,9 +505,9 @@ struct NodeVisitor {
   READ_FEATURE(OmpObject)
   READ_FEATURE(OmpObjectList)
   READ_FEATURE(OmpOrderClause)
-  READ_FEATURE(OmpOrderClause::Type)
+  READ_FEATURE(OmpOrderClause::Ordering)
   READ_FEATURE(OmpOrderModifier)
-  READ_FEATURE(OmpOrderModifier::Kind)
+  READ_FEATURE(OmpOrderModifier::Value)
   READ_FEATURE(OmpProcBindClause)
   READ_FEATURE(OmpProcBindClause::Type)
   READ_FEATURE(OmpReductionClause)
@@ -527,11 +527,10 @@ struct NodeVisitor {
   READ_FEATURE(OmpDeviceClause::DeviceModifier)
   READ_FEATURE(OmpDeviceTypeClause)
   READ_FEATURE(OmpDeviceTypeClause::Type)
-  READ_FEATURE(OmpScheduleModifier)
-  READ_FEATURE(OmpScheduleModifier::Modifier1)
-  READ_FEATURE(OmpScheduleModifier::Modifier2)
-  READ_FEATURE(OmpScheduleModifierType)
-  READ_FEATURE(OmpScheduleModifierType::ModType)
+  READ_FEATURE(OmpChunkModifier)
+  READ_FEATURE(OmpChunkModifier::Value)
+  READ_FEATURE(OmpOrderingModifier)
+  READ_FEATURE(OmpOrderingModifier::Value)
   READ_FEATURE(OmpSectionBlocks)
   READ_FEATURE(OmpSectionsDirective)
   READ_FEATURE(OmpSimpleStandaloneDirective)
diff --git a/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp b/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp
index a9ff163f8243ce..a3d9b0cfdc79b8 100644
--- a/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp
+++ b/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp
@@ -213,14 +213,18 @@ void OpenMPCounterVisitor::Post(const OmpVariableCategory::Value &c) {
       "variable_category=" + std::string{OmpVariableCategory::EnumToString(c)} +
       ";";
 }
-void OpenMPCounterVisitor::Post(const OmpScheduleModifierType::ModType &c) {
+void OpenMPCounterVisitor::Post(const OmpChunkModifier::Value &c) {
   clauseDetails +=
-      "modifier=" + std::string{OmpScheduleModifierType::EnumToString(c)} + ";";
+      "modifier=" + std::string{OmpChunkModifier::EnumToString(c)} + ";";
 }
 void OpenMPCounterVisitor::Post(const OmpLinearModifier::Value &c) {
   clauseDetails +=
       "modifier=" + std::string{OmpLinearModifier::EnumToString(c)} + ";";
 }
+void OpenMPCounterVisitor::Post(const OmpOrderingModifier::Value &c) {
+  clauseDetails +=
+      "modifier=" + std::string{OmpOrderingModifier::EnumToString(c)} + ";";
+}
 void OpenMPCounterVisitor::Post(const OmpTaskDependenceType::Value &c) {
   clauseDetails +=
       "type=" + std::string{OmpTaskDependenceType::EnumToString(c)} + ";";
@@ -228,7 +232,7 @@ void OpenMPCounterVisitor::Post(const OmpTaskDependenceType::Value &c) {
 void OpenMPCounterVisitor::Post(const OmpMapClause::Type &c) {
   clauseDetails += "type=" + std::string{OmpMapClause::EnumToString(c)} + ";";
 }
-void OpenMPCounterVisitor::Post(const OmpScheduleClause::ScheduleType &c) {
+void OpenMPCounterVisitor::Post(const OmpScheduleClause::Kind &c) {
   clauseDetails +=
       "type=" + std::string{OmpScheduleClause::EnumToString(c)} + ";";
 }
diff --git a/flang/examples/FlangOmpReport/FlangOmpReportVisitor.h b/flang/examples/FlangOmpReport/FlangOmpReportVisitor.h
index 83bd3644577e1c..608cb5a2241b83 100644
--- a/flang/examples/FlangOmpReport/FlangOmpReportVisitor.h
+++ b/flang/examples/FlangOmpReport/FlangOmpReportVisitor.h
@@ -71,8 +71,9 @@ struct OpenMPCounterVisitor {
   void Post(const OmpDefaultmapClause::ImplicitBehavior &c);
   void Post(const OmpVariableCategory::Value &c);
   void Post(const OmpDeviceTypeClause::Type &c);
-  void Post(const OmpScheduleModifierType::ModType &c);
+  void Post(const OmpChunkModifier::Value &c);
   void Post(const OmpLinearModifier::Value &c);
+  void Post(const OmpOrderingModifier::Value &c);
   void Post(const OmpTaskDependenceType::Value &c);
   void Post(const OmpMapClause::Type &c);
   void Post(const OmpScheduleClause::ScheduleType &c);
diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h
index e9c149758c1493..6d1e7329d5cce8 100644
--- a/flang/include/flang/Parser/dump-parse-tree.h
+++ b/flang/include/flang/Parser/dump-parse-tree.h
@@ -559,9 +559,10 @@ class ParseTreeDumper {
   NODE(parser, OmpObject)
   NODE(parser, OmpObjectList)
   NODE(parser, OmpOrderClause)
-  NODE_ENUM(OmpOrderClause, Type)
+  NODE(OmpOrderClause, Modifier)
+  NODE_ENUM(OmpOrderClause, Ordering)
   NODE(parser, OmpOrderModifier)
-  NODE_ENUM(OmpOrderModifier, Kind)
+  NODE_ENUM(OmpOrderModifier, Value)
   NODE(parser, OmpGrainsizeClause)
   NODE_ENUM(OmpGrainsizeClause, Prescriptiveness)
   NODE(parser, OmpNumTasksClause)
@@ -585,17 +586,17 @@ class ParseTreeDumper {
   NODE(OmpAllocateClause::AllocateModifier, ComplexModifier)
   NODE(OmpAllocateClause::AllocateModifier, Align)
   NODE(parser, OmpScheduleClause)
-  NODE_ENUM(OmpScheduleClause, ScheduleType)
+  NODE(OmpScheduleClause, Modifier)
+  NODE_ENUM(OmpScheduleClause, Kind)
   NODE(parser, OmpDeviceClause)
   NODE_ENUM(OmpDeviceClause, DeviceModifier)
   NODE(parser, OmpDeviceTypeClause)
   NODE_ENUM(OmpDeviceTypeClause, Type)
   NODE(parser, OmpUpdateClause)
-  NODE(parser, OmpScheduleModifier)
-  NODE(OmpScheduleModifier, Modifier1)
-  NODE(OmpScheduleModifier, Modifier2)
-  NODE(parser, OmpScheduleModifierType)
-  NODE_ENUM(OmpScheduleModifierType, ModType)
+  NODE(parser, OmpChunkModifier)
+  NODE_ENUM(OmpChunkModifier, Value)
+  NODE(parser, OmpOrderingModifier)
+  NODE_ENUM(OmpOrderingModifier, Value)
   NODE(parser, OmpSectionBlocks)
   NODE(parser, OmpSectionsDirective)
   NODE(parser, OmpSimpleStandaloneDirective)
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index 32ebaa7fbffcae..de179f47be8fca 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -3457,6 +3457,17 @@ inline namespace modifier {
 //   ENUM_CLASS(Value, Keyword1, Keyword2);
 // };
 
+// Ref: [5.2:252-254]
+//
+// chunk-modifier ->
+//    SIMD                                          // since 5.2
+//
+// Prior to 5.2 "chunk-modifier" was a part of "modifier" on SCHEDULE clause.
+struct OmpChunkModifier {
+  ENUM_CLASS(Value, Simd)
+  WRAPPER_CLASS_BOILERPLATE(OmpChunkModifier, Value);
+};
+
 // Ref: [5.0:47-49], [5.1:49-51], [5.2:67-69]
 //
 // iterator-specifier ->
@@ -3508,6 +3519,30 @@ struct OmpLinearModifier {
   WRAPPER_CLASS_BOILERPLATE(OmpLinearModifier, Value);
 };
 
+// Ref: [4.5:56-63], [5.0:101-109], [5.1:126-133], [5.2:252-254]
+//
+// modifier ->
+//    MONOTONIC | NONMONOTONIC | SIMD               // since 4.5, until 5.1
+// ordering-modifier ->
+//    MONOTONIC | NONMONOTONIC                      // since 5.2
+//
+// Until 5.1, the SCHEDULE clause accepted up to two instances of "modifier".
+// Since 5.2 "modifier" was replaced with "ordering-modifier" and "chunk-
+// modifier".
+struct OmpOrderingModifier {
+  ENUM_CLASS(Value, Monotonic, Nonmonotonic, Simd)
+  WRAPPER_CLASS_BOILERPLATE(OmpOrderingModifier, Value);
+};
+
+// Ref: [5.1:125-126], [5.2:233-234]
+//
+// order-modifier ->
+//    REPRODUCIBLE | UNCONSTRAINED                  // since 5.1
+struct OmpOrderModifier {
+  ENUM_CLASS(Value, Reproducible, Unconstrained)
+  WRAPPER_CLASS_BOILERPLATE(OmpOrderModifier, Value);
+};
+
 // Ref: [4.5:201-207], [5.0:293-299], [5.1:325-331], [5.2:124]
 //
 // reduction-identifier ->
@@ -3786,16 +3821,16 @@ struct OmpMapClause {
       t;
 };
 
-// 2.9.5 order-clause -> ORDER ([order-modifier :]concurrent)
-struct OmpOrderModifier {
-  ENUM_CLASS(Kind, Reproducible, Unconstrained)
-  WRAPPER_CLASS_BOILERPLATE(OmpOrderModifier, Kind);
-};
-
+// Ref: [5.0:101-109], [5.1:126-134], [5.2:233-234]
+//
+// order-clause ->
+//    ORDER(CONCURRENT) |                           // since 5.0
+//    ORDER([order-modifier:] CONCURRENT)           // since 5.1
 struct OmpOrderClause {
   TUPLE_CLASS_BOILERPLATE(OmpOrderClause);
-  ENUM_CLASS(Type, Concurrent)
-  std::tuple<std::optional<OmpOrderModifier>, Type> t;
+  ENUM_CLASS(Ordering, Concurrent)
+  MODIFIER_BOILERPLATE(OmpOrderModifier);
+  std::tuple<MODIFIERS(), Ordering> t;
 };
 
 // 2.5 proc-bind-clause -> PROC_BIND (MASTER | CLOSE | SPREAD)
@@ -3816,27 +3851,19 @@ struct OmpReductionClause {
   std::tuple<MODIFIERS(), OmpObjectList> t;
 };
 
-// 2.7.1 sched-modifier -> MONOTONIC | NONMONOTONIC | SIMD
-struct OmpScheduleModifierType {
-  ENUM_CLASS(ModType, Monotonic, Nonmonotonic, Simd)
-  WRAPPER_CLASS_BOILERPLATE(OmpScheduleModifierType, ModType);
-};
-
-struct OmpScheduleModifier {
-  TUPLE_CLASS_BOILERPLATE(OmpScheduleModifier);
-  WRAPPER_CLASS(Modifier1, OmpScheduleModifierType);
-  WRAPPER_CLASS(Modifier2, OmpScheduleModifierType);
-  std::tuple<Modifier1, std::optional<Modifier2>> t;
-};
-
-// 2.7.1 schedule-clause -> SCHEDULE ([sched-modifier1] [, sched-modifier2]:]
-//                                    kind[, chunk_size])
+// Ref: [4.5:56-63], [5.0:101-109], [5.1:126-133], [5.2:252-254]
+//
+// schedule-clause ->
+//    SCHEDULE([modifier[, modifier]:]
+//        kind[, chunk-size])                       // since 4.5, until 5.1
+// schedule-clause ->
+//    SCHEDULE([ordering-modifier], chunk-modifier],
+//        kind[, chunk_size])                       // since 5.2
 struct OmpScheduleClause {
   TUPLE_CLASS_BOILERPLATE(OmpScheduleClause);
-  ENUM_CLASS(ScheduleType, Static, Dynamic, Guided, Auto, Runtime)
-  std::tuple<std::optional<OmpScheduleModifier>, ScheduleType,
-      std::optional<ScalarIntExpr>>
-      t;
+  ENUM_CLASS(Kind, Static, Dynamic, Guided, Auto, Runtime)
+  MODIFIER_BOILERPLATE(OmpOrderingModifier, OmpChunkModifier);
+  std::tuple<MODIFIERS(), Kind, std::optional<ScalarIntExpr>> t;
 };
 
 // Ref: [4.5:107-109], [5.0:176-180], [5.1:205-210], [5.2:167-168]
diff --git a/flang/include/flang/Semantics/openmp-modifiers.h b/flang/include/flang/Semantics/openmp-modifiers.h
index 28fec7314cd8b5..fd6bd86fb280d8 100644
--- a/flang/include/flang/Semantics/openmp-modifiers.h
+++ b/flang/include/flang/Semantics/openmp-modifiers.h
@@ -61,6 +61,8 @@ struct OmpModifierDescriptor {
 
 template <typename SpecificTy> const OmpModifierDescriptor &OmpGetDescriptor();
 
+template <>
+const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpChunkModifier>();
 template <>
 const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpDependenceType>();
 template <>
@@ -68,6 +70,10 @@ const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpIterator>();
 template <>
 const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpLinearModifier>();
 template <>
+const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpOrderModifier>();
+template <>
+const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpOrderingModifier>();
+template <>
 const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpReductionIdentifier>();
 template <>
 const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpReductionModifier>();
diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp
index 4f9e7a7c1d78c3..8639d08827f4ed 100644
--- a/flang/lib/Lower/OpenMP/Clauses.cpp
+++ b/flang/lib/Lower/OpenMP/Clauses.cpp
@@ -1109,7 +1109,7 @@ Order make(const parser::OmpClause::Order &inp,
   using wrapped = parser::OmpOrderClause;
 
   CLAUSET_ENUM_CONVERT( //
-      convert1, parser::OmpOrderModifier::Kind, Order::OrderModifier,
+      convert1, parser::OmpOrderModifier::Value, Order::OrderModifier,
       // clang-format off
       MS(Reproducible,   Reproducible)
       MS(Unconstrained,  Unconstrained)
@@ -1117,20 +1117,18 @@ Order make(const parser::OmpClause::Order &inp,
   );
 
   CLAUSET_ENUM_CONVERT( //
-      convert2, wrapped::Type, Order::Ordering,
+      convert2, wrapped::Ordering, Order::Ordering,
       // clang-format off
       MS(Concurrent, Concurrent)
       // clang-format on
   );
 
-  auto &t0 = std::get<std::optional<parser::OmpOrderModifier>>(inp.v.t);
-  auto &t1 = std::get<wrapped::Type>(inp.v.t);
+  auto &mods = semantics::OmpGetModifiers(inp.v);
+  auto *t0 = semantics::OmpGetUniqueModifier<parser::OmpOrderModifier>(mods);
+  auto &t1 = std::get<wrapped::Ordering>(inp.v.t);
 
-  auto convert3 = [&](const parser::OmpOrderModifier &s) {
-    return convert1(s.v);
-  };
-  return Order{
-      {/*OrderModifier=*/maybeApply(convert3, t0), /*Ordering=*/convert2(t1)}};
+  return Order{{/*OrderModifier=*/maybeApplyToV(convert1, t0),
+                /*Ordering=*/convert2(t1)}};
 }
 
 Ordered make(const parser::OmpClause::Ordered &inp,
@@ -1197,10 +1195,10 @@ Reduction make(const parser::OmpClause::Reduction &inp,
   auto *t1 =
       semantics::OmpGetUniqueModifier<parser::OmpReductionIdentifier>(mods);
   auto &t2 = std::get<parser::OmpObjectList>(inp.v.t);
+  assert(t1 && "OmpReductionIdentifier is required");
+
   return Reduction{
-      {/*ReductionModifier=*/t0
-           ? std::make_optional<Reduction::ReductionModifier>(convert(t0->v))
-           : std::nullopt,
+      {/*ReductionModifier=*/maybeApplyToV(convert, t0),
        /*ReductionIdentifiers=*/{makeReductionOperator(*t1, semaCtx)},
        /*List=*/makeObjects(t2, semaCtx)}};
 }
@@ -1221,7 +1219,7 @@ Schedule make(const parser::OmpClause::Schedule &inp,
   using wrapped = parser::OmpScheduleClause;
 
   CLAUSET_ENUM_CONVERT( //
-      convert1, wrapped::ScheduleType, Schedule::Kind,
+      convert1, wrapped::Kind, Schedule::Kind,
       // clang-format off
       MS(Static,   Static)
       MS(Dynamic,  Dynamic)
@@ -1232,8 +1230,7 @@ Schedule make(const parser::OmpClause::Schedule &inp,
   );
 
   CLAUSET_ENUM_CONVERT( //
-      convert2, parser::OmpScheduleModifierType::ModType,
-      Schedule::OrderingModifier,
+      convert2, parser::OmpOrderingModifier::Value, Schedule::OrderingModifier,
       // clang-format off
       MS(Monotonic,    Monotonic)
       MS(Nonmonotonic, Nonmonotonic)
@@ -1241,48 +1238,22 @@ Schedule make(const parser::OmpClause::Schedule &inp,
   );
 
   CLAUSET_ENUM_CONVERT( //
-      convert3, parser::OmpScheduleModifierType::ModType,
-      Schedule::ChunkModifier,
+      convert3, parser::OmpChunkModifier::Value, Schedule::ChunkModifier,
       // clang-format off
       MS(Simd, Simd)
       // clang-format on
   );
 
-  auto &t0 = std::get<std::optional<parser::OmpScheduleModifier>>(inp.v.t);
-  auto &t1 = std::get<wrapped::ScheduleType>(inp.v.t);
-  auto &t2 = std::get<std::optional<parser::ScalarIntExpr>>(inp.v.t);
-
-  if (!t0) {
-    return Schedule{{/*Kind=*/convert1(t1), /*OrderingModifier=*/std::nullopt,
-                     /*ChunkModifier=*/std::nullopt,
-                     /*ChunkSize=*/maybeApply(makeExprFn(semaCtx), t2)}};
-  }
-
-  // The members of parser::OmpScheduleModifier correspond to OrderingModifier,
-  // and ChunkModifier, but they can appear in any order.
-  auto &m1 = std::get<parser::OmpScheduleModifier::Modifier1>(t0->t);
-  auto &m2 =
-      std::get<std::optional<parser::OmpScheduleModifier::Modifier2>>(t0->t);
-
-  std::optional<Schedule::OrderingModifier> omod;
-  std::optional<Schedule::ChunkModifier> cmod;
-
-  if (m1.v.v == parser::OmpScheduleModifierType::ModType::Simd) {
-    // m1 is chunk-modifier
-    cmod = convert3(m1.v.v);
-    if (m2)
-      omod = convert2(m2->v.v);
-  } else {
-    // m1 is ordering-modifier
-    omod = convert2(m1.v.v);
-    if (m2)
-      cmod = convert3(m2->v.v);
-  }
+  auto &mods = semantics::OmpGetModifiers(inp.v);
+  auto *t0 = semantics::OmpGetUniqueModifier<parser::OmpOrderingModifier>(mods);
+  auto *t1 = semantics::OmpGetUniqueModifier<parser::OmpChunkModifier>(mods);
+  auto &t2 = std::get<wrapped::Kind>(inp.v.t);
+  auto &t3 = std::get<std::optional<parser::ScalarIntExpr>>(inp.v.t);
 
-  return Schedule{{/*Kind=*/convert1(t1),
-                   /*OrderingModifier=*/omod,
-                   /*ChunkModifier=*/cmod,
-                   /*ChunkSize=*/maybeApply(makeExprFn(semaCtx), t2)}};
+  return Schedule{{/*Kind=*/convert1(t2),
+                   /*OrderingModifier=*/maybeApplyToV(convert2, t0),
+                   /*ChunkModifier=*/maybeApplyToV(convert3, t1),
+                   /*ChunkSize=*/maybeApply(makeExprFn(semaCtx), t3)}};
 }
 
 // SeqCst: empty
@@ -1326,6 +1297,8 @@ TaskReduction make(const parser::OmpClause::TaskReduction &inp,
   auto *t0 =
       semantics::OmpGetUniqueModifier<parser::OmpReductionIdentifier>(mods);
   auto &t1 = std::get<parser::OmpObjectList>(inp.v.t);
+  assert(t0 && "OmpReductionIdentifier is required");
+
   return TaskReduction{
       {/*ReductionIdentifiers=*/{makeReductionOperator(*t0, semaCtx)},
        /*List=*/makeObjects(t1, semaCtx)}};
diff --git a/flang/lib/Lower/OpenMP/Clauses.h b/flang/lib/Lower/OpenMP/Clauses.h
index ada50e0488837b..9c053e2213c675 100644
--- a/flang/lib/Lower/OpenMP/Clauses.h
+++ b/flang/lib/Lower/OpenMP/Clauses.h
@@ -153,6 +153,16 @@ std::optional<ResultTy> maybeApply(FuncTy &&func,
   return std::move(func(*arg));
 }
 
+template <
+    typename FuncTy, //
+    typename ArgTy,  //
+    typename ResultTy = std::invoke_result_t<FuncTy, typename ArgTy::Value>>
+std::optional<ResultTy> maybeApplyToV(FuncTy &&func, const ArgTy *arg) {
+  if (!arg)
+    return std::nullopt;
+  return std::move(func(arg->v));
+}
+
 std::optional<Object> getBaseObject(const Object &object,
                                     semantics::SemanticsContext &semaCtx);
 
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index a1d368d73ab83a..ceae20270d13d0 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -228,6 +228,18 @@ TYPE_PARSER(construct<OmpLinearModifier>( //
 TYPE_PARSER(construct<OmpReductionIdentifier>(Parser<DefinedOperator>{}) ||
     construct<OmpReductionIdentifier>(Parser<ProcedureDesignator>{}))
 
+TYPE_PARSER(construct<OmpChunkModifier>( //
+    "SIMD" >> pure(OmpChunkModifier::Value::Simd)))
+
+TYPE_PARSER(construct<OmpOrderModifier>(
+    "REPRODUCIBLE" >> pure(OmpOrderModifier::Value::Reproducible) ||
+    "UNCONSTRAINED" >> pure(OmpOrderModifier::Value::Unconstrained)))
+
+TYPE_PARSER(construct<OmpOrderingModifier>(
+    "MONOTONIC" >> pure(OmpOrderingModifier::Value::Monotonic) ||
+    "NONMONOTONIC" >> pure(OmpOrderingModifier::Value::Nonmonotonic) ||
+    "SIMD" >> pure(OmpOrderingModifier::Value::Simd)))
+
 TYPE_PARSER(construct<OmpReductionModifier>(
     "INSCAN" >> pure(OmpReductionModifier::Value::Inscan) ||
     "TASK" >> pure(OmpReductionModifier::Value::Task) ||
@@ -241,12 +253,6 @@ TYPE_PARSER(construct<OmpTaskDependenceType>(
     "MUTEXINOUTSET" >> pure(OmpTaskDependenceType::Value::Mutexinoutset) ||
     "OUT" >> pure(OmpTaskDependenceType::Value::Out)))
 
-// This could be auto-generated.
-TYPE_PARSER(sourced(construct<OmpReductionClause::Modifier>(sourced(
-    construct<OmpReductionClause::Modifier>(Parser<OmpReductionModifier>{}) ||
-    construct<OmpReductionClause::Modifier>(
-        Parser<OmpReductionIdentifier>{})))))
-
 TYPE_PARSER(construct<OmpVariableCategory>(
     "AGGREGATE" >> pure(OmpVariableCategory::Value::Aggregate) ||
     "ALL"_id >> pure(OmpVariableCategory::Value::All) ||
@@ -254,6 +260,19 @@ TYPE_PARSER(construct<OmpVariableCategory>(
     "POINTER" >> pure(OmpVariableCategory::Value::Pointer) ||
     "SCALAR" >> pure(OmpVariableCategory::Value::Scalar)))
 
+// This could be auto-generated.
+TYPE_PARSER(
+    sourced(construct<OmpOrderClause::Modifier>(Parser<OmpOrderModifier>{})))
+
+TYPE_PARSER(sourced(construct<OmpReductionClause::Modifier>(sourced(
+    construct<OmpReductionClause::Modifier>(Parser<OmpReductionModifier>{}) ||
+    construct<OmpReductionClause::Modifier>(
+        Parser<OmpReductionIdentifier>{})))))
+
+TYPE_PARSER(sourced(construct<OmpScheduleClause::Modifier>(sourced(
+    construct<OmpScheduleClause::Modifier>(Parser<OmpChunkModifier>{}) ||
+    construct<OmpScheduleClause::Modifier>(Parser<OmpOrderingModifier>{})))))
+
 TYPE_PARSER(sourced(
     construct<OmpDefaultmapClause::Modifier>(Parser<OmpVariableCategory>{})))
 
@@ -336,25 +355,16 @@ TYPE_PARSER(construct<OmpDefaultmapClause>(
         "DEFAULT" >> pure(OmpDefaultmapClause::ImplicitBehavior::Default)),
     maybe(":" >> nonemptyList(Parser<OmpDefaultmapClause::Modifier>{}))))
 
-// 2.7.1 SCHEDULE ([modifier1 [, modifier2]:]kind[, chunk_size])
-//       Modifier ->  MONITONIC | NONMONOTONIC | SIMD
-//       kind -> STATIC | DYNAMIC | GUIDED | AUTO | RUNTIME
-//       chunk_size -> ScalarIntExpr
-TYPE_PARSER(construct<OmpScheduleModifierType>(
-    "MONOTONIC" >> pure(OmpScheduleModifierType::ModType::Monotonic) ||
-    "NONMONOTONIC" >> pure(OmpScheduleModifierType::ModType::Nonmonotonic) ||
-    "SIMD" >> pure(OmpScheduleModifierType::ModType::Simd)))
-
-TYPE_PARSER(construct<OmpScheduleModifier>(Parser<OmpScheduleModifierType>{},
-    maybe("," >> Parser<OmpScheduleModifierType>{}) / ":"))
-
-TYPE_PARSER(construct<OmpScheduleClause>(maybe(Parser<OmpScheduleModifier>{}),
-    "STATIC" >> pure(OmpScheduleClause::ScheduleType::Static) ||
-        "DYNAMIC" >> pure(OmpScheduleClause::ScheduleType::Dynamic) ||
-        "GUIDED" >> pure(OmpScheduleClause::ScheduleType::Guided) ||
-        "AUTO" >> pure(OmpScheduleClause::ScheduleType::Auto) ||
-        "RUNTIME" >> pure(OmpScheduleClause::ScheduleType::Runtime),
-    maybe("," >> scalarIntExpr)))
+TYPE_PARSER(construct<OmpScheduleClause::Kind>(
+    "STATIC" >> pure(OmpScheduleClause::Kind::Static) ||
+    "DYNAMIC" >> pure(OmpScheduleClause::Kind::Dynamic) ||
+    "GUIDED" >> pure(OmpScheduleClause::Kind::Guided) ||
+    "AUTO" >> pure(OmpScheduleClause::Kind::Auto) ||
+    "RUNTIME" >> pure(OmpScheduleClause::Kind::Runtime)))
+
+TYPE_PARSER(construct<OmpScheduleClause>(
+    maybe(nonemptyList(Parser<OmpScheduleClause::Modifier>{}) / ":"),
+    Parser<OmpScheduleClause::Kind>{}, maybe("," >> scalarIntExpr)))
 
 // device([ device-modifier :] scalar-integer-expression)
 TYPE_PARSER(construct<OmpDeviceClause>(
@@ -497,14 +507,9 @@ TYPE_PARSER(construct<OmpUpdateClause>(
     construct<OmpUpdateClause>(Parser<OmpDependenceType>{}) ||
     construct<OmpUpdateClause>(Parser<OmpTaskDependenceType>{})))
 
-// 2.9.5 ORDER ([order-modifier :]concurrent)
-TYPE_PARSER(construct<OmpOrderModifier>(
-                "REPRODUCIBLE" >> pure(OmpOrderModifier::Kind::Reproducible)) ||
-    construct<OmpOrderModifier>(
-        "UNCONSTRAINED" >> pure(OmpOrderModifier::Kind::Unconstrained)))
-
-TYPE_PARSER(construct<OmpOrderClause>(maybe(Parser<OmpOrderModifier>{} / ":"),
-    "CONCURRENT" >> pure(OmpOrderClause::Type::Concurrent)))
+TYPE_PARSER(construct<OmpOrderClause>(
+    maybe(nonemptyList(Parser<OmpOrderClause::Modifier>{}) / ":"),
+    "CONCURRENT" >> pure(OmpOrderClause::Ordering::Concurrent)))
 
 // OMP 5.2 12.6.1 grainsize([ prescriptiveness :] scalar-integer-expression)
 TYPE_PARSER(construct<OmpGrainsizeClause>(
diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index 72123ae0d318d1..4881da848c3473 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -2133,13 +2133,10 @@ class UnparseVisitor {
     }
     Walk(std::get<OmpObjectList>(x.t));
   }
-  void Unparse(const OmpScheduleModifier &x) {
-    Walk(std::get<OmpScheduleModifier::Modifier1>(x.t));
-    Walk(",", std::get<std::optional<OmpScheduleModifier::Modifier2>>(x.t));
-  }
   void Unparse(const OmpScheduleClause &x) {
-    Walk(std::get<std::optional<OmpScheduleModifier>>(x.t), ":");
-    Walk(std::get<OmpScheduleClause::ScheduleType>(x.t));
+    using Modifier = OmpScheduleClause::Modifier;
+    Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ":");
+    Walk(std::get<OmpScheduleClause::Kind>(x.t));
     Walk(",", std::get<std::optional<ScalarIntExpr>>(x.t));
   }
   void Unparse(const OmpDeviceClause &x) {
@@ -2230,8 +2227,9 @@ class UnparseVisitor {
     Put(")");
   }
   void Unparse(const OmpOrderClause &x) {
-    Walk(std::get<std::optional<OmpOrderModifier>>(x.t), ":");
-    Walk(std::get<OmpOrderClause::Type>(x.t));
+    using Modifier = OmpOrderClause::Modifier;
+    Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ":");
+    Walk(std::get<OmpOrderClause::Ordering>(x.t));
   }
   void Unparse(const OmpGrainsizeClause &x) {
     Walk(std::get<std::optional<OmpGrainsizeClause::Prescriptiveness>>(x.t),
@@ -2907,18 +2905,19 @@ class UnparseVisitor {
   WALK_NESTED_ENUM(OmpVariableCategory, Value) // OMP variable-category
   WALK_NESTED_ENUM(
       OmpLastprivateClause, LastprivateModifier) // OMP lastprivate-modifier
-  WALK_NESTED_ENUM(OmpScheduleModifierType, ModType) // OMP schedule-modifier
+  WALK_NESTED_ENUM(OmpChunkModifier, Value) // OMP chunk-modifier
   WALK_NESTED_ENUM(OmpLinearModifier, Value) // OMP linear-modifier
+  WALK_NESTED_ENUM(OmpOrderingModifier, Value) // OMP ordering-modifier
   WALK_NESTED_ENUM(OmpTaskDependenceType, Value) // OMP task-dependence-type
-  WALK_NESTED_ENUM(OmpScheduleClause, ScheduleType) // OMP schedule-type
+  WALK_NESTED_ENUM(OmpScheduleClause, Kind) // OMP schedule-kind
   WALK_NESTED_ENUM(OmpDeviceClause, DeviceModifier) // OMP device modifier
   WALK_NESTED_ENUM(OmpDeviceTypeClause, Type) // OMP DEVICE_TYPE
   WALK_NESTED_ENUM(OmpReductionModifier, Value) // OMP reduction-modifier
   WALK_NESTED_ENUM(OmpFromClause, Expectation) // OMP motion-expectation
   WALK_NESTED_ENUM(OmpIfClause, DirectiveNameModifier) // OMP directive-modifier
   WALK_NESTED_ENUM(OmpCancelType, Type) // OMP cancel-type
-  WALK_NESTED_ENUM(OmpOrderClause, Type) // OMP order-type
-  WALK_NESTED_ENUM(OmpOrderModifier, Kind) // OMP order-modifier
+  WALK_NESTED_ENUM(OmpOrderClause, Ordering) // OMP ordering
+  WALK_NESTED_ENUM(OmpOrderModifier, Value) // OMP order-modifier
   WALK_NESTED_ENUM(
       OmpGrainsizeClause, Prescriptiveness) // OMP grainsize-modifier
   WALK_NESTED_ENUM(OmpNumTasksClause, Prescriptiveness) // OMP numtasks-modifier
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 079d0fd17bfac1..a4af1ce5771a89 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -2576,19 +2576,16 @@ void OmpStructureChecker::Leave(const parser::OmpClauseList &) {
     if (auto *clause{FindClause(llvm::omp::Clause::OMPC_schedule)}) {
       // only one schedule clause is allowed
       const auto &schedClause{std::get<parser::OmpClause::Schedule>(clause->u)};
-      if (ScheduleModifierHasType(schedClause.v,
-              parser::OmpScheduleModifierType::ModType::Nonmonotonic)) {
+      auto &modifiers{OmpGetModifiers(schedClause.v)};
+      auto *ordering{
+          OmpGetUniqueModifier<parser::OmpOrderingModifier>(modifiers)};
+      if (ordering &&
+          ordering->v == parser::OmpOrderingModifier::Value::Nonmonotonic) {
         if (FindClause(llvm::omp::Clause::OMPC_ordered)) {
           context_.Say(clause->source,
               "The NONMONOTONIC modifier cannot be specified "
               "if an ORDERED clause is specified"_err_en_US);
         }
-        if (ScheduleModifierHasType(schedClause.v,
-                parser::OmpScheduleModifierType::ModType::Monotonic)) {
-          context_.Say(clause->source,
-              "The MONOTONIC and NONMONOTONIC modifiers "
-              "cannot be both specified"_err_en_US);
-        }
       }
     }
 
@@ -2648,8 +2645,8 @@ void OmpStructureChecker::Leave(const parser::OmpClauseList &) {
       if (auto *o_clause{FindClause(llvm::omp::Clause::OMPC_order)}) {
         const auto &orderClause{
             std::get<parser::OmpClause::Order>(o_clause->u)};
-        if (std::get<parser::OmpOrderClause::Type>(orderClause.v.t) ==
-            parser::OmpOrderClause::Type::Concurrent) {
+        if (std::get<parser::OmpOrderClause::Ordering>(orderClause.v.t) ==
+            parser::OmpOrderClause::Ordering::Concurrent) {
           context_.Say(sl_clause->source,
               "The `SAFELEN` clause cannot appear in the `SIMD` directive "
               "with `ORDER(CONCURRENT)` clause"_err_en_US);
@@ -3553,34 +3550,23 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Map &x) {
   }
 }
 
-bool OmpStructureChecker::ScheduleModifierHasType(
-    const parser::OmpScheduleClause &x,
-    const parser::OmpScheduleModifierType::ModType &type) {
-  const auto &modifier{
-      std::get<std::optional<parser::OmpScheduleModifier>>(x.t)};
-  if (modifier) {
-    const auto &modType1{
-        std::get<parser::OmpScheduleModifier::Modifier1>(modifier->t)};
-    const auto &modType2{
-        std::get<std::optional<parser::OmpScheduleModifier::Modifier2>>(
-            modifier->t)};
-    if (modType1.v.v == type || (modType2 && modType2->v.v == type)) {
-      return true;
-    }
-  }
-  return false;
-}
 void OmpStructureChecker::Enter(const parser::OmpClause::Schedule &x) {
   CheckAllowedClause(llvm::omp::Clause::OMPC_schedule);
   const parser::OmpScheduleClause &scheduleClause = x.v;
+  if (!OmpVerifyModifiers(
+          scheduleClause, GetContext().clauseSource, context_)) {
+    return;
+  }
 
   // 2.7 Loop Construct Restriction
   if (llvm::omp::allDoSet.test(GetContext().directive)) {
-    const auto &kind{std::get<1>(scheduleClause.t)};
-    const auto &chunk{std::get<2>(scheduleClause.t)};
+    auto &modifiers{OmpGetModifiers(scheduleClause)};
+    auto kind{std::get<parser::OmpScheduleClause::Kind>(scheduleClause.t)};
+    auto &chunk{
+        std::get<std::optional<parser::ScalarIntExpr>>(scheduleClause.t)};
     if (chunk) {
-      if (kind == parser::OmpScheduleClause::ScheduleType::Runtime ||
-          kind == parser::OmpScheduleClause::ScheduleType::Auto) {
+      if (kind == parser::OmpScheduleClause::Kind::Runtime ||
+          kind == parser::OmpScheduleClause::Kind::Auto) {
         context_.Say(GetContext().clauseSource,
             "When SCHEDULE clause has %s specified, "
             "it must not have chunk size specified"_err_en_US,
@@ -3594,10 +3580,12 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Schedule &x) {
       }
     }
 
-    if (ScheduleModifierHasType(scheduleClause,
-            parser::OmpScheduleModifierType::ModType::Nonmonotonic)) {
-      if (kind != parser::OmpScheduleClause::ScheduleType::Dynamic &&
-          kind != parser::OmpScheduleClause::ScheduleType::Guided) {
+    auto *ordering{
+        OmpGetUniqueModifier<parser::OmpOrderingModifier>(modifiers)};
+    if (ordering &&
+        ordering->v == parser::OmpOrderingModifier::Value::Nonmonotonic) {
+      if (kind != parser::OmpScheduleClause::Kind::Dynamic &&
+          kind != parser::OmpScheduleClause::Kind::Guided) {
         context_.Say(GetContext().clauseSource,
             "The NONMONOTONIC modifier can only be specified with "
             "SCHEDULE(DYNAMIC) or SCHEDULE(GUIDED)"_err_en_US);
diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index af61215ecc403d..cd0a4759376130 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -161,8 +161,6 @@ class OmpStructureChecker
   void HasInvalidDistributeNesting(const parser::OpenMPLoopConstruct &x);
   void HasInvalidLoopBinding(const parser::OpenMPLoopConstruct &x);
   // specific clause related
-  bool ScheduleModifierHasType(const parser::OmpScheduleClause &,
-      const parser::OmpScheduleModifierType::ModType &);
   void CheckAllowedMapTypes(const parser::OmpMapClause::Type &,
       const std::list<parser::OmpMapClause::Type> &);
   llvm::StringRef getClauseName(llvm::omp::Clause clause) override;
diff --git a/flang/lib/Semantics/openmp-modifiers.cpp b/flang/lib/Semantics/openmp-modifiers.cpp
index a425eec76a36d8..e0d73e605c73b0 100644
--- a/flang/lib/Semantics/openmp-modifiers.cpp
+++ b/flang/lib/Semantics/openmp-modifiers.cpp
@@ -55,6 +55,22 @@ const OmpClauses &OmpModifierDescriptor::clauses(unsigned version) const {
 // Note: The intent for these functions is to have them be automatically-
 // generated in the future.
 
+template <>
+const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpChunkModifier>() {
+  static const OmpModifierDescriptor desc{
+      /*name=*/"chunk-modifier",
+      /*props=*/
+      {
+          {45, {OmpProperty::Unique}},
+      },
+      /*clauses=*/
+      {
+          {45, {Clause::OMPC_schedule}},
+      },
+  };
+  return desc;
+}
+
 template <>
 const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpDependenceType>() {
   static const OmpModifierDescriptor desc{
@@ -108,6 +124,38 @@ const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpLinearModifier>() {
   return desc;
 }
 
+template <>
+const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpOrderModifier>() {
+  static const OmpModifierDescriptor desc{
+      /*name=*/"order-modifier",
+      /*props=*/
+      {
+          {51, {OmpProperty::Unique}},
+      },
+      /*clauses=*/
+      {
+          {51, {Clause::OMPC_order}},
+      },
+  };
+  return desc;
+}
+
+template <>
+const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpOrderingModifier>() {
+  static const OmpModifierDescriptor desc{
+      /*name=*/"ordering-modifier",
+      /*props=*/
+      {
+          {45, {OmpProperty::Unique}},
+      },
+      /*clauses=*/
+      {
+          {45, {Clause::OMPC_schedule}},
+      },
+  };
+  return desc;
+}
+
 template <>
 const OmpModifierDescriptor &
 OmpGetDescriptor<parser::OmpReductionIdentifier>() {
diff --git a/flang/test/Parser/OpenMP/order-clause01.f90 b/flang/test/Parser/OpenMP/order-clause01.f90
index 41e131f9b5428e..f810eb74ee29d0 100644
--- a/flang/test/Parser/OpenMP/order-clause01.f90
+++ b/flang/test/Parser/OpenMP/order-clause01.f90
@@ -17,7 +17,7 @@ subroutine test_do_order()
 !PARSE-TREE-NEXT: OmpBeginLoopDirective
 !PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = do
 !PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Order -> OmpOrderClause
-!PARSE-TREE-NEXT: Type = Concurrent
+!PARSE-TREE-NEXT: Ordering = Concurrent
 
 subroutine test_simd_order_reproducible()
  integer :: i, j = 1
@@ -33,8 +33,8 @@ subroutine test_simd_order_reproducible()
 !PARSE-TREE-NEXT: OmpBeginLoopDirective
 !PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = simd
 !PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Order -> OmpOrderClause
-!PARSE-TREE-NEXT: Kind = Reproducible
-!PARSE-TREE-NEXT: Type = Concurrent
+!PARSE-TREE-NEXT: OmpOrderModifier -> Value = Reproducible
+!PARSE-TREE-NEXT: Ordering = Concurrent
 
 subroutine test_do_simd_order_unconstrained()
  integer :: i, j = 1
@@ -50,8 +50,8 @@ subroutine test_do_simd_order_unconstrained()
 !PARSE-TREE-NEXT: OmpBeginLoopDirective
 !PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = do simd
 !PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Order -> OmpOrderClause
-!PARSE-TREE-NEXT: Kind = Unconstrained
-!PARSE-TREE-NEXT: Type = Concurrent
+!PARSE-TREE-NEXT: OmpOrderModifier -> Value = Unconstrained
+!PARSE-TREE-NEXT: Ordering = Concurrent
 
 subroutine test_parallel_do_order()
  integer :: i, j = 1
@@ -67,7 +67,7 @@ subroutine test_parallel_do_order()
 !PARSE-TREE-NEXT: OmpBeginLoopDirective
 !PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = parallel do
 !PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Order -> OmpOrderClause
-!PARSE-TREE-NEXT: Type = Concurrent
+!PARSE-TREE-NEXT: Ordering = Concurrent
 
 subroutine test_parallel_do_simd_order_reproducible()
  integer :: i, j = 1
@@ -83,8 +83,8 @@ subroutine test_parallel_do_simd_order_reproducible()
 !PARSE-TREE-NEXT: OmpBeginLoopDirective
 !PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = parallel do simd
 !PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Order -> OmpOrderClause
-!PARSE-TREE-NEXT: Kind = Reproducible
-!PARSE-TREE-NEXT: Type = Concurrent
+!PARSE-TREE-NEXT: OmpOrderModifier -> Value = Reproducible
+!PARSE-TREE-NEXT: Ordering = Concurrent
 
 subroutine test_target_simd_order_unconstrained()
  integer :: i, j = 1
@@ -100,8 +100,8 @@ subroutine test_target_simd_order_unconstrained()
 !PARSE-TREE-NEXT: OmpBeginLoopDirective
 !PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = target simd
 !PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Order -> OmpOrderClause
-!PARSE-TREE-NEXT: Kind = Unconstrained
-!PARSE-TREE-NEXT: Type = Concurrent
+!PARSE-TREE-NEXT: OmpOrderModifier -> Value = Unconstrained
+!PARSE-TREE-NEXT: Ordering = Concurrent
 
 subroutine test_target_parallel_do_order()
  integer :: i, j = 1
@@ -117,7 +117,7 @@ subroutine test_target_parallel_do_order()
 !PARSE-TREE-NEXT: OmpBeginLoopDirective
 !PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = target parallel do
 !PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Order -> OmpOrderClause
-!PARSE-TREE-NEXT: Type = Concurrent
+!PARSE-TREE-NEXT: Ordering = Concurrent
 
 subroutine test_target_parallel_do_simd_order_reproducible()
  integer :: i, j = 1
@@ -133,8 +133,8 @@ subroutine test_target_parallel_do_simd_order_reproducible()
 !PARSE-TREE-NEXT: OmpBeginLoopDirective
 !PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = target parallel do simd
 !PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Order -> OmpOrderClause
-!PARSE-TREE-NEXT: Kind = Reproducible
-!PARSE-TREE-NEXT: Type = Concurrent
+!PARSE-TREE-NEXT: OmpOrderModifier -> Value = Reproducible
+!PARSE-TREE-NEXT: Ordering = Concurrent
 
 subroutine test_teams_distribute_simd_order_unconstrained()
  integer :: i, j = 1
@@ -150,8 +150,8 @@ subroutine test_teams_distribute_simd_order_unconstrained()
 !PARSE-TREE-NEXT: OmpBeginLoopDirective
 !PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = teams distribute simd
 !PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Order -> OmpOrderClause
-!PARSE-TREE-NEXT: Kind = Unconstrained
-!PARSE-TREE-NEXT: Type = Concurrent
+!PARSE-TREE-NEXT: OmpOrderModifier -> Value = Unconstrained
+!PARSE-TREE-NEXT: Ordering = Concurrent
 
 subroutine test_teams_distribute_parallel_do_order()
  integer :: i, j = 1
@@ -167,7 +167,7 @@ subroutine test_teams_distribute_parallel_do_order()
 !PARSE-TREE-NEXT: OmpBeginLoopDirective
 !PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = teams distribute parallel do
 !PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Order -> OmpOrderClause
-!PARSE-TREE-NEXT: Type = Concurrent
+!PARSE-TREE-NEXT: Ordering = Concurrent
 
 subroutine test_teams_distribute_parallel_do_simd_order_reproducible()
  integer :: i, j = 1
@@ -183,8 +183,8 @@ subroutine test_teams_distribute_parallel_do_simd_order_reproducible()
 !PARSE-TREE-NEXT: OmpBeginLoopDirective
 !PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = teams distribute parallel do simd
 !PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Order -> OmpOrderClause
-!PARSE-TREE-NEXT: Kind = Reproducible
-!PARSE-TREE-NEXT: Type = Concurrent
+!PARSE-TREE-NEXT: OmpOrderModifier -> Value = Reproducible
+!PARSE-TREE-NEXT: Ordering = Concurrent
 
 subroutine test_target_teams_distribute_simd_order_unconstrained()
  integer :: i, j = 1
@@ -200,8 +200,8 @@ subroutine test_target_teams_distribute_simd_order_unconstrained()
 !PARSE-TREE-NEXT: OmpBeginLoopDirective
 !PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = target teams distribute simd
 !PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Order -> OmpOrderClause
-!PARSE-TREE-NEXT: Kind = Unconstrained
-!PARSE-TREE-NEXT: Type = Concurrent
+!PARSE-TREE-NEXT: OmpOrderModifier -> Value = Unconstrained
+!PARSE-TREE-NEXT: Ordering = Concurrent
 
 subroutine test_target_teams_distribute_parallel_do_order()
  integer :: i, j = 1
@@ -217,7 +217,7 @@ subroutine test_target_teams_distribute_parallel_do_order()
 !PARSE-TREE-NEXT: OmpBeginLoopDirective
 !PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = target teams distribute parallel do
 !PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Order -> OmpOrderClause
-!PARSE-TREE-NEXT: Type = Concurrent
+!PARSE-TREE-NEXT: Ordering = Concurrent
 
 subroutine test_target_teams_distribute_parallel_do_simd_order_reproducible()
  integer :: i, j = 1
@@ -233,8 +233,8 @@ subroutine test_target_teams_distribute_parallel_do_simd_order_reproducible()
 !PARSE-TREE-NEXT: OmpBeginLoopDirective
 !PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = target teams distribute parallel do simd
 !PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Order -> OmpOrderClause
-!PARSE-TREE-NEXT: Kind = Reproducible
-!PARSE-TREE-NEXT: Type = Concurrent
+!PARSE-TREE-NEXT: OmpOrderModifier -> Value = Reproducible
+!PARSE-TREE-NEXT: Ordering = Concurrent
 
 subroutine test_taskloop_simd_order_unconstrained()
  integer :: i, j = 1
@@ -250,5 +250,5 @@ subroutine test_taskloop_simd_order_unconstrained()
 !PARSE-TREE-NEXT: OmpBeginLoopDirective
 !PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = taskloop simd
 !PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Order -> OmpOrderClause
-!PARSE-TREE-NEXT: Kind = Unconstrained
-!PARSE-TREE-NEXT: Type = Concurrent
+!PARSE-TREE-NEXT: OmpOrderModifier -> Value = Unconstrained
+!PARSE-TREE-NEXT: Ordering = Concurrent



More information about the llvm-branch-commits mailing list