From 552e1f3b9be17cf8ab2ec850e84d1aeb6753e1f5 Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Mon, 28 Sep 2015 06:39:35 +0000 Subject: [PATCH] [OPENMP 4.1] Add 'simd' clause for 'ordered' directive. 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 --- include/clang/AST/DataRecursiveASTVisitor.h | 5 ++ include/clang/AST/OpenMPClause.h | 30 +++++++ include/clang/AST/RecursiveASTVisitor.h | 5 ++ include/clang/Basic/OpenMPKinds.def | 2 + include/clang/Sema/Sema.h | 5 +- lib/AST/StmtPrinter.cpp | 2 + lib/AST/StmtProfile.cpp | 2 + lib/Basic/OpenMPKinds.cpp | 2 + lib/CodeGen/CGStmtOpenMP.cpp | 1 + lib/Parse/ParseOpenMP.cpp | 6 +- lib/Sema/SemaOpenMP.cpp | 39 +++++++-- lib/Sema/TreeTransform.h | 6 ++ lib/Serialization/ASTReaderStmt.cpp | 5 ++ lib/Serialization/ASTWriterStmt.cpp | 2 + test/OpenMP/ordered_ast_print.cpp | 90 ++++++++++++++++++++ test/OpenMP/ordered_messages.cpp | 92 +++++++++++++++++++++ tools/libclang/CIndex.cpp | 2 + 17 files changed, 289 insertions(+), 7 deletions(-) diff --git a/include/clang/AST/DataRecursiveASTVisitor.h b/include/clang/AST/DataRecursiveASTVisitor.h index 79203b9117..12ba21645a 100644 --- a/include/clang/AST/DataRecursiveASTVisitor.h +++ b/include/clang/AST/DataRecursiveASTVisitor.h @@ -2539,6 +2539,11 @@ bool RecursiveASTVisitor::VisitOMPThreadsClause(OMPThreadsClause *) { return true; } +template +bool RecursiveASTVisitor::VisitOMPSIMDClause(OMPSIMDClause *) { + return true; +} + template template bool RecursiveASTVisitor::VisitOMPClauseList(T *Node) { diff --git a/include/clang/AST/OpenMPClause.h b/include/clang/AST/OpenMPClause.h index a0736db8b7..1f807a5bb9 100644 --- a/include/clang/AST/OpenMPClause.h +++ b/include/clang/AST/OpenMPClause.h @@ -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 diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index e8125f20e4..e632536ee1 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -2571,6 +2571,11 @@ bool RecursiveASTVisitor::VisitOMPThreadsClause(OMPThreadsClause *) { return true; } +template +bool RecursiveASTVisitor::VisitOMPSIMDClause(OMPSIMDClause *) { + return true; +} + template template bool RecursiveASTVisitor::VisitOMPClauseList(T *Node) { diff --git a/include/clang/Basic/OpenMPKinds.def b/include/clang/Basic/OpenMPKinds.def index efc0d42a81..ee99b42ded 100644 --- a/include/clang/Basic/OpenMPKinds.def +++ b/include/clang/Basic/OpenMPKinds.def @@ -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 diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index f166402efa..09b46ce77b 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -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 Vars, Expr *TailExpr, diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index 3ab8acbb1e..d0603478e6 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -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); diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp index 874aee1ebe..c807f5e2f9 100644 --- a/lib/AST/StmtProfile.cpp +++ b/lib/AST/StmtProfile.cpp @@ -335,6 +335,8 @@ void OMPClauseProfiler::VisitOMPSeqCstClause(const OMPSeqCstClause *) {} void OMPClauseProfiler::VisitOMPThreadsClause(const OMPThreadsClause *) {} +void OMPClauseProfiler::VisitOMPSIMDClause(const OMPSIMDClause *) {} + template void OMPClauseProfiler::VisitOMPClauseList(T *Node) { for (auto *E : Node->varlists()) { diff --git a/lib/Basic/OpenMPKinds.cpp b/lib/Basic/OpenMPKinds.cpp index ea99387cb9..28194680b2 100644 --- a/lib/Basic/OpenMPKinds.cpp +++ b/lib/Basic/OpenMPKinds.cpp @@ -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"); diff --git a/lib/CodeGen/CGStmtOpenMP.cpp b/lib/CodeGen/CGStmtOpenMP.cpp index 341ccaad54..a06b0a2492 100644 --- a/lib/CodeGen/CGStmtOpenMP.cpp +++ b/lib/CodeGen/CGStmtOpenMP.cpp @@ -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'."); } } diff --git a/lib/Parse/ParseOpenMP.cpp b/lib/Parse/ParseOpenMP.cpp index 5f32c63cf3..37eeabae10 100644 --- a/lib/Parse/ParseOpenMP.cpp +++ b/lib/Parse/ParseOpenMP.cpp @@ -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(); diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp index 9045724aa2..44096860d6 100644 --- a/lib/Sema/SemaOpenMP.cpp +++ b/lib/Sema/SemaOpenMP.cpp @@ -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 Clauses, getCurFunction()->setHasBranchProtectedScope(); OMPThreadsClause *TC = nullptr; + OMPSIMDClause *SC = nullptr; for (auto *C: Clauses) { if (C->getClauseKind() == OMPC_threads) TC = cast(C); + else if (C->getClauseKind() == OMPC_simd) + SC = cast(C); } // TODO: this must happen only if 'threads' clause specified or if no clauses @@ -4159,6 +4169,13 @@ StmtResult Sema::ActOnOpenMPOrderedDirective(ArrayRef 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 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."); } diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index df998a06fb..de368ea90c 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -7372,6 +7372,12 @@ TreeTransform::TransformOMPThreadsClause(OMPThreadsClause *C) { return C; } +template +OMPClause *TreeTransform::TransformOMPSIMDClause(OMPSIMDClause *C) { + // No need to rebuild this clause, no template-dependent parameters. + return C; +} + template OMPClause * TreeTransform::TransformOMPPrivateClause(OMPPrivateClause *C) { diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp index 6969823030..4d55deeaa5 100644 --- a/lib/Serialization/ASTReaderStmt.cpp +++ b/lib/Serialization/ASTReaderStmt.cpp @@ -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(); diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp index 5c86dc1b4f..33cffaf115 100644 --- a/lib/Serialization/ASTWriterStmt.cpp +++ b/lib/Serialization/ASTWriterStmt.cpp @@ -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); diff --git a/test/OpenMP/ordered_ast_print.cpp b/test/OpenMP/ordered_ast_print.cpp index f8601c51ba..6328ec0d76 100644 --- a/test/OpenMP/ordered_ast_print.cpp +++ b/test/OpenMP/ordered_ast_print.cpp @@ -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); } diff --git a/test/OpenMP/ordered_messages.cpp b/test/OpenMP/ordered_messages.cpp index 039a2b5fbf..559a6b06f2 100644 --- a/test/OpenMP/ordered_messages.cpp +++ b/test/OpenMP/ordered_messages.cpp @@ -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(); } diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index 829cab736d..c3bac878df 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -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()); } -- 2.50.1