]> granicus.if.org Git - clang/commitdiff
[OPENMP 4.1] Add 'simd' clause for 'ordered' directive.
authorAlexey Bataev <a.bataev@hotmail.com>
Mon, 28 Sep 2015 06:39:35 +0000 (06:39 +0000)
committerAlexey Bataev <a.bataev@hotmail.com>
Mon, 28 Sep 2015 06:39:35 +0000 (06:39 +0000)
Parsing and sema analysis for 'simd' clause in 'ordered' directive.
Description
If the simd clause is specified, the ordered regions encountered by any thread will use only a single SIMD lane to execute the ordered
regions in the order of the loop iterations.
Restrictions
An ordered construct with the simd clause is the only OpenMP construct that can appear in the simd region

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@248696 91177308-0d34-0410-b5e6-96231b3b80d8

17 files changed:
include/clang/AST/DataRecursiveASTVisitor.h
include/clang/AST/OpenMPClause.h
include/clang/AST/RecursiveASTVisitor.h
include/clang/Basic/OpenMPKinds.def
include/clang/Sema/Sema.h
lib/AST/StmtPrinter.cpp
lib/AST/StmtProfile.cpp
lib/Basic/OpenMPKinds.cpp
lib/CodeGen/CGStmtOpenMP.cpp
lib/Parse/ParseOpenMP.cpp
lib/Sema/SemaOpenMP.cpp
lib/Sema/TreeTransform.h
lib/Serialization/ASTReaderStmt.cpp
lib/Serialization/ASTWriterStmt.cpp
test/OpenMP/ordered_ast_print.cpp
test/OpenMP/ordered_messages.cpp
tools/libclang/CIndex.cpp

index 79203b9117ad79ca6ad0cb164f877e18b84c407b..12ba21645a291850fb92d5044f7ea9926fe17dcf 100644 (file)
@@ -2539,6 +2539,11 @@ bool RecursiveASTVisitor<Derived>::VisitOMPThreadsClause(OMPThreadsClause *) {
   return true;
 }
 
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPSIMDClause(OMPSIMDClause *) {
+  return true;
+}
+
 template <typename Derived>
 template <typename T>
 bool RecursiveASTVisitor<Derived>::VisitOMPClauseList(T *Node) {
index a0736db8b7c578eb1d92c145c380dc2c66376aa6..1f807a5bb94126b5bf0b9618f94cf982aa7f9e9c 100644 (file)
@@ -2561,6 +2561,36 @@ public:
   }
 };
 
+/// \brief This represents 'simd' clause in the '#pragma omp ...' directive.
+///
+/// \code
+/// #pragma omp ordered simd
+/// \endcode
+/// In this example directive '#pragma omp ordered' has simple 'simd' clause.
+///
+class OMPSIMDClause : public OMPClause {
+public:
+  /// \brief Build 'simd' clause.
+  ///
+  /// \param StartLoc Starting location of the clause.
+  /// \param EndLoc Ending location of the clause.
+  ///
+  OMPSIMDClause(SourceLocation StartLoc, SourceLocation EndLoc)
+      : OMPClause(OMPC_simd, StartLoc, EndLoc) {}
+
+  /// \brief Build an empty clause.
+  ///
+  OMPSIMDClause() : OMPClause(OMPC_simd, SourceLocation(), SourceLocation()) {}
+
+  static bool classof(const OMPClause *T) {
+    return T->getClauseKind() == OMPC_simd;
+  }
+
+  child_range children() {
+    return child_range(child_iterator(), child_iterator());
+  }
+};
+
 } // end namespace clang
 
 #endif
index e8125f20e43ebef5fb7969c1ad24a5cea3b66e66..e632536ee14b5e1dcbea7a3e4ace8db507760a39 100644 (file)
@@ -2571,6 +2571,11 @@ bool RecursiveASTVisitor<Derived>::VisitOMPThreadsClause(OMPThreadsClause *) {
   return true;
 }
 
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPSIMDClause(OMPSIMDClause *) {
+  return true;
+}
+
 template <typename Derived>
 template <typename T>
 bool RecursiveASTVisitor<Derived>::VisitOMPClauseList(T *Node) {
index efc0d42a813ed94d7c3bf2f822d82d51af868db8..ee99b42ded46787a79c16e4f6eee888d975af0c6 100644 (file)
@@ -145,6 +145,7 @@ OPENMP_CLAUSE(seq_cst, OMPSeqCstClause)
 OPENMP_CLAUSE(depend, OMPDependClause)
 OPENMP_CLAUSE(device, OMPDeviceClause)
 OPENMP_CLAUSE(threads, OMPThreadsClause)
+OPENMP_CLAUSE(simd, OMPSIMDClause)
 
 // Clauses allowed for OpenMP directive 'parallel'.
 OPENMP_PARALLEL_CLAUSE(if)
@@ -318,6 +319,7 @@ OPENMP_TEAMS_CLAUSE(reduction)
 // Clauses allowed for OpenMP directive 'ordered'.
 // TODO More clauses for 'ordered' directive.
 OPENMP_ORDERED_CLAUSE(threads)
+OPENMP_ORDERED_CLAUSE(simd)
 
 #undef OPENMP_LINEAR_KIND
 #undef OPENMP_DEPEND_KIND
index f166402efa015a73cdf284f965dc23023ab2755b..09b46ce77b659a0dc8b58db79044ec46e9c87ccd 100644 (file)
@@ -7997,7 +7997,10 @@ public:
                                      SourceLocation EndLoc);
   /// \brief Called on well-formed 'threads' clause.
   OMPClause *ActOnOpenMPThreadsClause(SourceLocation StartLoc,
-                                     SourceLocation EndLoc);
+                                      SourceLocation EndLoc);
+  /// \brief Called on well-formed 'simd' clause.
+  OMPClause *ActOnOpenMPSIMDClause(SourceLocation StartLoc,
+                                   SourceLocation EndLoc);
 
   OMPClause *ActOnOpenMPVarListClause(
       OpenMPClauseKind Kind, ArrayRef<Expr *> Vars, Expr *TailExpr,
index 3ab8acbb1e107b6ece9b97eaacaf723a526cad86..d0603478e6ab3f422a2b32a777179f5bb46c6497 100644 (file)
@@ -701,6 +701,8 @@ void OMPClausePrinter::VisitOMPThreadsClause(OMPThreadsClause *) {
   OS << "threads";
 }
 
+void OMPClausePrinter::VisitOMPSIMDClause(OMPSIMDClause *) { OS << "simd"; }
+
 void OMPClausePrinter::VisitOMPDeviceClause(OMPDeviceClause *Node) {
   OS << "device(";
   Node->getDevice()->printPretty(OS, nullptr, Policy, 0);
index 874aee1ebec5bcee71314facf90fc605e99760ca..c807f5e2f9c3b1e6b41dfb39ae3880ef9582d02f 100644 (file)
@@ -335,6 +335,8 @@ void OMPClauseProfiler::VisitOMPSeqCstClause(const OMPSeqCstClause *) {}
 
 void OMPClauseProfiler::VisitOMPThreadsClause(const OMPThreadsClause *) {}
 
+void OMPClauseProfiler::VisitOMPSIMDClause(const OMPSIMDClause *) {}
+
 template<typename T>
 void OMPClauseProfiler::VisitOMPClauseList(T *Node) {
   for (auto *E : Node->varlists()) {
index ea99387cb942c25aa0670342bd9aaf73eddfac9b..28194680b2314d115c3b313402f7035fc37099d0 100644 (file)
@@ -129,6 +129,7 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind,
   case OMPC_seq_cst:
   case OMPC_device:
   case OMPC_threads:
+  case OMPC_simd:
     break;
   }
   llvm_unreachable("Invalid OpenMP simple clause kind");
@@ -214,6 +215,7 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
   case OMPC_seq_cst:
   case OMPC_device:
   case OMPC_threads:
+  case OMPC_simd:
     break;
   }
   llvm_unreachable("Invalid OpenMP simple clause kind");
index 341ccaad54269798b90aac39c4eeabe2ca142250..a06b0a2492539319ce53ac3e04d96894d3bc4e58 100644 (file)
@@ -2210,6 +2210,7 @@ static void EmitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind,
   case OMPC_mergeable:
   case OMPC_device:
   case OMPC_threads:
+  case OMPC_simd:
     llvm_unreachable("Clause is not allowed in 'omp atomic'.");
   }
 }
index 5f32c63cf3069b4a6fe03f48f4fb71a92029b063..37eeabae10a7f1a44c9031154ecf1bfdbda2dd38 100644 (file)
@@ -394,7 +394,7 @@ bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
 ///       schedule-clause | copyin-clause | copyprivate-clause | untied-clause |
 ///       mergeable-clause | flush-clause | read-clause | write-clause |
 ///       update-clause | capture-clause | seq_cst-clause | device-clause |
-///       simdlen-clause | threads-clause
+///       simdlen-clause | threads-clause | simd-clause
 ///
 OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
                                      OpenMPClauseKind CKind, bool FirstClause) {
@@ -473,6 +473,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
   case OMPC_capture:
   case OMPC_seq_cst:
   case OMPC_threads:
+  case OMPC_simd:
     // OpenMP [2.7.1, Restrictions, p. 9]
     //  Only one ordered clause can appear on a loop directive.
     // OpenMP [2.7.1, Restrictions, C/C++, p. 4]
@@ -605,6 +606,9 @@ OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) {
 ///    threads-clause:
 ///         'threads'
 ///
+///    simd-clause:
+///         'simd'
+///
 OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind) {
   SourceLocation Loc = Tok.getLocation();
   ConsumeAnyToken();
index 9045724aa2b2fe473a62f28330e1680669e5bc80..44096860d6d7a5f089ac24b2fba91e59a3895bd8 100644 (file)
@@ -1547,7 +1547,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
   // | simd             | taskwait        |                                    |
   // | simd             | taskgroup       |                                    |
   // | simd             | flush           |                                    |
-  // | simd             | ordered         |                                    |
+  // | simd             | ordered         | + (with simd clause)               |
   // | simd             | atomic          |                                    |
   // | simd             | target          |                                    |
   // | simd             | teams           |                                    |
@@ -1573,7 +1573,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
   // | for simd         | taskwait        |                                    |
   // | for simd         | taskgroup       |                                    |
   // | for simd         | flush           |                                    |
-  // | for simd         | ordered         |                                    |
+  // | for simd         | ordered         | + (with simd clause)               |
   // | for simd         | atomic          |                                    |
   // | for simd         | target          |                                    |
   // | for simd         | teams           |                                    |
@@ -1599,7 +1599,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
   // | parallel for simd| taskwait        |                                    |
   // | parallel for simd| taskgroup       |                                    |
   // | parallel for simd| flush           |                                    |
-  // | parallel for simd| ordered         |                                    |
+  // | parallel for simd| ordered         | + (with simd clause)               |
   // | parallel for simd| atomic          |                                    |
   // | parallel for simd| target          |                                    |
   // | parallel for simd| teams           |                                    |
@@ -1877,9 +1877,12 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
       ShouldBeInOrderedRegion,
       ShouldBeInTargetRegion
     } Recommend = NoRecommend;
-    if (isOpenMPSimdDirective(ParentRegion)) {
+    if (isOpenMPSimdDirective(ParentRegion) && CurrentRegion != OMPD_ordered) {
       // OpenMP [2.16, Nesting of Regions]
       // OpenMP constructs may not be nested inside a simd region.
+      // OpenMP [2.8.1,simd Construct, Restrictions]
+      // An ordered construct with the simd clause is the only OpenMP construct
+      // that can appear in the simd region.
       SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_simd);
       return true;
     }
@@ -1987,9 +1990,13 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
       // atomic, or explicit task region.
       // An ordered region must be closely nested inside a loop region (or
       // parallel loop region) with an ordered clause.
+      // OpenMP [2.8.1,simd Construct, Restrictions]
+      // An ordered construct with the simd clause is the only OpenMP construct
+      // that can appear in the simd region.
       NestingProhibited = ParentRegion == OMPD_critical ||
                           ParentRegion == OMPD_task ||
-                          !Stack->isParentOrderedRegion();
+                          !(isOpenMPSimdDirective(ParentRegion) ||
+                            Stack->isParentOrderedRegion());
       Recommend = ShouldBeInOrderedRegion;
     } else if (isOpenMPTeamsDirective(CurrentRegion)) {
       // OpenMP [2.16, Nesting of Regions]
@@ -4146,9 +4153,12 @@ StmtResult Sema::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
   getCurFunction()->setHasBranchProtectedScope();
 
   OMPThreadsClause *TC = nullptr;
+  OMPSIMDClause *SC = nullptr;
   for (auto *C: Clauses) {
     if (C->getClauseKind() == OMPC_threads)
       TC = cast<OMPThreadsClause>(C);
+    else if (C->getClauseKind() == OMPC_simd)
+      SC = cast<OMPSIMDClause>(C);
   }
 
   // TODO: this must happen only if 'threads' clause specified or if no clauses
@@ -4159,6 +4169,13 @@ StmtResult Sema::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
     Diag(Param->getLocStart(), diag::note_omp_ordered_param);
     return StmtError();
   }
+  if (!SC && isOpenMPSimdDirective(DSAStack->getParentDirective())) {
+    // OpenMP [2.8.1,simd Construct, Restrictions]
+    // An ordered construct with the simd clause is the only OpenMP construct
+    // that can appear in the simd region.
+    Diag(StartLoc, diag::err_omp_prohibited_region_simd);
+    return StmtError();
+  }
 
   return OMPOrderedDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
 }
@@ -5009,6 +5026,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
   case OMPC_seq_cst:
   case OMPC_depend:
   case OMPC_threads:
+  case OMPC_simd:
   case OMPC_unknown:
     llvm_unreachable("Clause is not allowed.");
   }
@@ -5270,6 +5288,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause(
   case OMPC_depend:
   case OMPC_device:
   case OMPC_threads:
+  case OMPC_simd:
   case OMPC_unknown:
     llvm_unreachable("Clause is not allowed.");
   }
@@ -5398,6 +5417,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(
   case OMPC_depend:
   case OMPC_device:
   case OMPC_threads:
+  case OMPC_simd:
   case OMPC_unknown:
     llvm_unreachable("Clause is not allowed.");
   }
@@ -5504,6 +5524,9 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind,
   case OMPC_threads:
     Res = ActOnOpenMPThreadsClause(StartLoc, EndLoc);
     break;
+  case OMPC_simd:
+    Res = ActOnOpenMPSIMDClause(StartLoc, EndLoc);
+    break;
   case OMPC_if:
   case OMPC_final:
   case OMPC_num_threads:
@@ -5578,6 +5601,11 @@ OMPClause *Sema::ActOnOpenMPThreadsClause(SourceLocation StartLoc,
   return new (Context) OMPThreadsClause(StartLoc, EndLoc);
 }
 
+OMPClause *Sema::ActOnOpenMPSIMDClause(SourceLocation StartLoc,
+                                       SourceLocation EndLoc) {
+  return new (Context) OMPSIMDClause(StartLoc, EndLoc);
+}
+
 OMPClause *Sema::ActOnOpenMPVarListClause(
     OpenMPClauseKind Kind, ArrayRef<Expr *> VarList, Expr *TailExpr,
     SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
@@ -5644,6 +5672,7 @@ OMPClause *Sema::ActOnOpenMPVarListClause(
   case OMPC_seq_cst:
   case OMPC_device:
   case OMPC_threads:
+  case OMPC_simd:
   case OMPC_unknown:
     llvm_unreachable("Clause is not allowed.");
   }
index df998a06fb5b9ffc12529d4a8c6871c862cf403c..de368ea90caaeb7edb227c20afc765ab1359a517 100644 (file)
@@ -7372,6 +7372,12 @@ TreeTransform<Derived>::TransformOMPThreadsClause(OMPThreadsClause *C) {
   return C;
 }
 
+template <typename Derived>
+OMPClause *TreeTransform<Derived>::TransformOMPSIMDClause(OMPSIMDClause *C) {
+  // No need to rebuild this clause, no template-dependent parameters.
+  return C;
+}
+
 template <typename Derived>
 OMPClause *
 TreeTransform<Derived>::TransformOMPPrivateClause(OMPPrivateClause *C) {
index 6969823030db4fe78a063b2a0a822e9c1cc4dbd2..4d55deeaa50d9a979e38690deef12f544c2c07b1 100644 (file)
@@ -1780,6 +1780,9 @@ OMPClause *OMPClauseReader::readClause() {
   case OMPC_threads:
     C = new (Context) OMPThreadsClause();
     break;
+  case OMPC_simd:
+    C = new (Context) OMPSIMDClause();
+    break;
   case OMPC_private:
     C = OMPPrivateClause::CreateEmpty(Context, Record[Idx++]);
     break;
@@ -1904,6 +1907,8 @@ void OMPClauseReader::VisitOMPSeqCstClause(OMPSeqCstClause *) {}
 
 void OMPClauseReader::VisitOMPThreadsClause(OMPThreadsClause *) {}
 
+void OMPClauseReader::VisitOMPSIMDClause(OMPSIMDClause *) {}
+
 void OMPClauseReader::VisitOMPPrivateClause(OMPPrivateClause *C) {
   C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
   unsigned NumVars = C->varlist_size();
index 5c86dc1b4f52f3fd40b46923f473219895ba5f58..33cffaf115e538be5eef1510bf3d16f1801985f2 100644 (file)
@@ -1812,6 +1812,8 @@ void OMPClauseWriter::VisitOMPSeqCstClause(OMPSeqCstClause *) {}
 
 void OMPClauseWriter::VisitOMPThreadsClause(OMPThreadsClause *) {}
 
+void OMPClauseWriter::VisitOMPSIMDClause(OMPSIMDClause *) {}
+
 void OMPClauseWriter::VisitOMPPrivateClause(OMPPrivateClause *C) {
   Record.push_back(C->varlist_size());
   Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
index f8601c51bad09ca7183ba29418bcf30bf1d09880..6328ec0d7660f986e7d8dbfce09d9c6b59f517d8 100644 (file)
@@ -24,6 +24,24 @@ T tmain (T argc) {
   {
     a=2;
   }
+  #pragma omp simd
+  for (int i =0 ; i < argc; ++i)
+  #pragma omp ordered simd
+  {
+    a=2;
+  }
+  #pragma omp for simd
+  for (int i =0 ; i < argc; ++i)
+  #pragma omp ordered simd
+  {
+    a=2;
+  }
+  #pragma omp parallel for simd
+  for (int i =0 ; i < argc; ++i)
+  #pragma omp ordered simd
+  {
+    a=2;
+  }
   return (0);
 }
 
@@ -40,6 +58,24 @@ T tmain (T argc) {
 // CHECK-NEXT: {
 // CHECK-NEXT: a = 2;
 // CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp simd
+// CHECK-NEXT: for (int i = 0; i < argc; ++i)
+// CHECK-NEXT: #pragma omp ordered simd
+// CHECK-NEXT: {
+// CHECK-NEXT: a = 2;
+// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp for simd
+// CHECK-NEXT: for (int i = 0; i < argc; ++i)
+// CHECK-NEXT: #pragma omp ordered simd
+// CHECK-NEXT: {
+// CHECK-NEXT: a = 2;
+// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp parallel for simd
+// CHECK-NEXT: for (int i = 0; i < argc; ++i)
+// CHECK-NEXT: #pragma omp ordered simd
+// CHECK-NEXT: {
+// CHECK-NEXT: a = 2;
+// CHECK-NEXT: }
 
 // CHECK: static T a;
 // CHECK-NEXT: #pragma omp for ordered
@@ -54,6 +90,24 @@ T tmain (T argc) {
 // CHECK-NEXT: {
 // CHECK-NEXT: a = 2;
 // CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp simd
+// CHECK-NEXT: for (int i = 0; i < argc; ++i)
+// CHECK-NEXT: #pragma omp ordered simd
+// CHECK-NEXT: {
+// CHECK-NEXT: a = 2;
+// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp for simd
+// CHECK-NEXT: for (int i = 0; i < argc; ++i)
+// CHECK-NEXT: #pragma omp ordered simd
+// CHECK-NEXT: {
+// CHECK-NEXT: a = 2;
+// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp parallel for simd
+// CHECK-NEXT: for (int i = 0; i < argc; ++i)
+// CHECK-NEXT: #pragma omp ordered simd
+// CHECK-NEXT: {
+// CHECK-NEXT: a = 2;
+// CHECK-NEXT: }
 
 int main (int argc, char **argv) {
   int b = argc, c, d, e, f, g;
@@ -71,6 +125,24 @@ int main (int argc, char **argv) {
   {
     a=2;
   }
+  #pragma omp simd
+  for (int i =0 ; i < argc; ++i)
+  #pragma omp ordered simd
+  {
+    a=2;
+  }
+  #pragma omp for simd
+  for (int i =0 ; i < argc; ++i)
+  #pragma omp ordered simd
+  {
+    a=2;
+  }
+  #pragma omp parallel for simd
+  for (int i =0 ; i < argc; ++i)
+  #pragma omp ordered simd
+  {
+    a=2;
+  }
 // CHECK-NEXT: #pragma omp for ordered
 // CHECK-NEXT: for (int i = 0; i < argc; ++i)
 // CHECK-NEXT: #pragma omp ordered
@@ -82,6 +154,24 @@ int main (int argc, char **argv) {
 // CHECK-NEXT: #pragma omp ordered threads
 // CHECK-NEXT: {
 // CHECK-NEXT: a = 2;
+// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp simd
+// CHECK-NEXT: for (int i = 0; i < argc; ++i)
+// CHECK-NEXT: #pragma omp ordered simd
+// CHECK-NEXT: {
+// CHECK-NEXT: a = 2;
+// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp for simd
+// CHECK-NEXT: for (int i = 0; i < argc; ++i)
+// CHECK-NEXT: #pragma omp ordered simd
+// CHECK-NEXT: {
+// CHECK-NEXT: a = 2;
+// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp parallel for simd
+// CHECK-NEXT: for (int i = 0; i < argc; ++i)
+// CHECK-NEXT: #pragma omp ordered simd
+// CHECK-NEXT: {
+// CHECK-NEXT: a = 2;
 // CHECK-NEXT: }
   return tmain(argc);
 }
index 039a2b5fbf570a43d4777a1f23ffb833f9d7b462..559a6b06f222588aab5d2c43b671b1f0812c41d6 100644 (file)
@@ -45,6 +45,52 @@ T foo() {
       foo();
     }
   }
+  #pragma omp ordered simd simd // expected-error {{directive '#pragma omp ordered' cannot contain more than one 'simd' clause}}
+  {
+    foo();
+  }
+  #pragma omp simd
+  for (int i = 0; i < 10; ++i) {
+    #pragma omp ordered // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+    {
+      foo();
+    }
+  }
+  #pragma omp simd
+  for (int i = 0; i < 10; ++i) {
+    #pragma omp ordered threads // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+    {
+      foo();
+    }
+  }
+  #pragma omp for simd
+  for (int i = 0; i < 10; ++i) {
+    #pragma omp ordered // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+    {
+      foo();
+    }
+  }
+  #pragma omp for simd
+  for (int i = 0; i < 10; ++i) {
+    #pragma omp ordered threads // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+    {
+      foo();
+    }
+  }
+  #pragma omp parallel for simd
+  for (int i = 0; i < 10; ++i) {
+    #pragma omp ordered // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+    {
+      foo();
+    }
+  }
+  #pragma omp parallel for simd
+  for (int i = 0; i < 10; ++i) {
+    #pragma omp ordered threads // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+    {
+      foo();
+    }
+  }
 
   return T();
 }
@@ -91,6 +137,52 @@ int foo() {
       foo();
     }
   }
+  #pragma omp ordered simd simd // expected-error {{directive '#pragma omp ordered' cannot contain more than one 'simd' clause}}
+  {
+    foo();
+  }
+  #pragma omp simd
+  for (int i = 0; i < 10; ++i) {
+    #pragma omp ordered // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+    {
+      foo();
+    }
+  }
+  #pragma omp simd
+  for (int i = 0; i < 10; ++i) {
+    #pragma omp ordered threads // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+    {
+      foo();
+    }
+  }
+  #pragma omp for simd
+  for (int i = 0; i < 10; ++i) {
+    #pragma omp ordered // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+    {
+      foo();
+    }
+  }
+  #pragma omp for simd
+  for (int i = 0; i < 10; ++i) {
+    #pragma omp ordered threads // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+    {
+      foo();
+    }
+  }
+  #pragma omp parallel for simd
+  for (int i = 0; i < 10; ++i) {
+    #pragma omp ordered // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+    {
+      foo();
+    }
+  }
+  #pragma omp parallel for simd
+  for (int i = 0; i < 10; ++i) {
+    #pragma omp ordered threads // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+    {
+      foo();
+    }
+  }
 
   return foo<int>();
 }
index 829cab736d793c3b1b9d85f0c97594183ac422f3..c3bac878df968c1dc73ceb831b7e8ff8801f152c 100644 (file)
@@ -2068,6 +2068,8 @@ void OMPClauseEnqueue::VisitOMPSeqCstClause(const OMPSeqCstClause *) {}
 
 void OMPClauseEnqueue::VisitOMPThreadsClause(const OMPThreadsClause *) {}
 
+void OMPClauseEnqueue::VisitOMPSIMDClause(const OMPSIMDClause *) {}
+
 void OMPClauseEnqueue::VisitOMPDeviceClause(const OMPDeviceClause *C) {
   Visitor->AddStmt(C->getDevice());
 }