From c30dd2daf9fd65364da9b1ac839b88b809de41d8 Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Thu, 18 Jun 2015 12:14:09 +0000 Subject: [PATCH] [OPENMP] Support for '#pragma omp taskgroup' directive. Added parsing, sema analysis and codegen for '#pragma omp taskgroup' directive (OpenMP 4.0). The code for directive is generated the following way: #pragma omp taskgroup void __kmpc_taskgroup(, thread_id); void __kmpc_end_taskgroup(, thread_id); llvm-svn: 240011 --- clang/include/clang-c/Index.h | 7 ++- clang/include/clang/AST/DataRecursiveASTVisitor.h | 3 + clang/include/clang/AST/RecursiveASTVisitor.h | 3 + clang/include/clang/AST/StmtOpenMP.h | 47 ++++++++++++++++ clang/include/clang/Basic/OpenMPKinds.def | 1 + clang/include/clang/Basic/StmtNodes.td | 1 + clang/include/clang/Sema/Sema.h | 3 + clang/include/clang/Serialization/ASTBitCodes.h | 1 + clang/lib/AST/Stmt.cpp | 23 +++++++- clang/lib/AST/StmtPrinter.cpp | 5 ++ clang/lib/AST/StmtProfile.cpp | 4 ++ clang/lib/Basic/OpenMPKinds.cpp | 1 + clang/lib/CodeGen/CGOpenMPRuntime.cpp | 37 ++++++++++++- clang/lib/CodeGen/CGOpenMPRuntime.h | 13 ++++- clang/lib/CodeGen/CGStmt.cpp | 3 + clang/lib/CodeGen/CGStmtOpenMP.cpp | 10 ++++ clang/lib/CodeGen/CodeGenFunction.h | 1 + clang/lib/Parse/ParseOpenMP.cpp | 7 ++- clang/lib/Sema/SemaOpenMP.cpp | 40 ++++++++++++++ clang/lib/Sema/TreeTransform.h | 11 ++++ clang/lib/Serialization/ASTReaderStmt.cpp | 9 +++ clang/lib/Serialization/ASTWriterStmt.cpp | 6 ++ clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 1 + clang/test/OpenMP/taskgroup_ast_print.cpp | 29 ++++++++++ clang/test/OpenMP/taskgroup_codegen.cpp | 56 +++++++++++++++++++ clang/test/OpenMP/taskgroup_messages.cpp | 67 +++++++++++++++++++++++ clang/tools/libclang/CIndex.cpp | 8 +++ clang/tools/libclang/CXCursor.cpp | 3 + 28 files changed, 394 insertions(+), 6 deletions(-) create mode 100644 clang/test/OpenMP/taskgroup_ast_print.cpp create mode 100644 clang/test/OpenMP/taskgroup_codegen.cpp create mode 100644 clang/test/OpenMP/taskgroup_messages.cpp diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index 3276afc..c10cc66 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -2225,7 +2225,12 @@ enum CXCursorKind { */ CXCursor_OMPTeamsDirective = 253, - CXCursor_LastStmt = CXCursor_OMPTeamsDirective, + /** \brief OpenMP taskwait directive. + */ + CXCursor_OMPTaskgroupDirective = 254, + + + CXCursor_LastStmt = CXCursor_OMPTaskgroupDirective, /** * \brief Cursor that represents the translation unit itself. diff --git a/clang/include/clang/AST/DataRecursiveASTVisitor.h b/clang/include/clang/AST/DataRecursiveASTVisitor.h index f6e2cad..ef88176 100644 --- a/clang/include/clang/AST/DataRecursiveASTVisitor.h +++ b/clang/include/clang/AST/DataRecursiveASTVisitor.h @@ -2355,6 +2355,9 @@ DEF_TRAVERSE_STMT(OMPBarrierDirective, DEF_TRAVERSE_STMT(OMPTaskwaitDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPTaskgroupDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + DEF_TRAVERSE_STMT(OMPFlushDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index 24fd43e..95d7730 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -2388,6 +2388,9 @@ DEF_TRAVERSE_STMT(OMPBarrierDirective, DEF_TRAVERSE_STMT(OMPTaskwaitDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPTaskgroupDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + DEF_TRAVERSE_STMT(OMPFlushDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) diff --git a/clang/include/clang/AST/StmtOpenMP.h b/clang/include/clang/AST/StmtOpenMP.h index 01c81a0..63f295d 100644 --- a/clang/include/clang/AST/StmtOpenMP.h +++ b/clang/include/clang/AST/StmtOpenMP.h @@ -1455,6 +1455,53 @@ public: } }; +/// \brief This represents '#pragma omp taskgroup' directive. +/// +/// \code +/// #pragma omp taskgroup +/// \endcode +/// +class OMPTaskgroupDirective : public OMPExecutableDirective { + friend class ASTStmtReader; + /// \brief Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// + OMPTaskgroupDirective(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPExecutableDirective(this, OMPTaskgroupDirectiveClass, OMPD_taskgroup, + StartLoc, EndLoc, 0, 1) {} + + /// \brief Build an empty directive. + /// + explicit OMPTaskgroupDirective() + : OMPExecutableDirective(this, OMPTaskgroupDirectiveClass, OMPD_taskgroup, + SourceLocation(), SourceLocation(), 0, 1) {} + +public: + /// \brief Creates directive. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param AssociatedStmt Statement, associated with the directive. + /// + static OMPTaskgroupDirective *Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation EndLoc, + Stmt *AssociatedStmt); + + /// \brief Creates an empty directive. + /// + /// \param C AST context. + /// + static OMPTaskgroupDirective *CreateEmpty(const ASTContext &C, EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPTaskgroupDirectiveClass; + } +}; + /// \brief This represents '#pragma omp flush' directive. /// /// \code diff --git a/clang/include/clang/Basic/OpenMPKinds.def b/clang/include/clang/Basic/OpenMPKinds.def index 0145db0..b09f012 100644 --- a/clang/include/clang/Basic/OpenMPKinds.def +++ b/clang/include/clang/Basic/OpenMPKinds.def @@ -84,6 +84,7 @@ OPENMP_DIRECTIVE(critical) OPENMP_DIRECTIVE(taskyield) OPENMP_DIRECTIVE(barrier) OPENMP_DIRECTIVE(taskwait) +OPENMP_DIRECTIVE(taskgroup) OPENMP_DIRECTIVE(flush) OPENMP_DIRECTIVE(ordered) OPENMP_DIRECTIVE(atomic) diff --git a/clang/include/clang/Basic/StmtNodes.td b/clang/include/clang/Basic/StmtNodes.td index 790250d..675e91d 100644 --- a/clang/include/clang/Basic/StmtNodes.td +++ b/clang/include/clang/Basic/StmtNodes.td @@ -199,6 +199,7 @@ def OMPTaskDirective : DStmt; def OMPTaskyieldDirective : DStmt; def OMPBarrierDirective : DStmt; def OMPTaskwaitDirective : DStmt; +def OMPTaskgroupDirective : DStmt; def OMPFlushDirective : DStmt; def OMPOrderedDirective : DStmt; def OMPAtomicDirective : DStmt; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index fbb867a..a05aa98 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -7649,6 +7649,9 @@ public: /// \brief Called on well-formed '\#pragma omp taskwait'. StmtResult ActOnOpenMPTaskwaitDirective(SourceLocation StartLoc, SourceLocation EndLoc); + /// \brief Called on well-formed '\#pragma omp taskgroup'. + StmtResult ActOnOpenMPTaskgroupDirective(Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc); /// \brief Called on well-formed '\#pragma omp flush'. StmtResult ActOnOpenMPFlushDirective(ArrayRef Clauses, SourceLocation StartLoc, diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index 3d6f824..83185a8 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -1396,6 +1396,7 @@ namespace clang { STMT_OMP_ATOMIC_DIRECTIVE, STMT_OMP_TARGET_DIRECTIVE, STMT_OMP_TEAMS_DIRECTIVE, + STMT_OMP_TASKGROUP_DIRECTIVE, // ARC EXPR_OBJC_BRIDGED_CAST, // ObjCBridgedCastExpr diff --git a/clang/lib/AST/Stmt.cpp b/clang/lib/AST/Stmt.cpp index d2a6a9c..6f4a89f 100644 --- a/clang/lib/AST/Stmt.cpp +++ b/clang/lib/AST/Stmt.cpp @@ -1777,7 +1777,7 @@ OMPSectionDirective *OMPSectionDirective::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPSectionsDirective), + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPSectionDirective), llvm::alignOf()); void *Mem = C.Allocate(Size + sizeof(Stmt *)); OMPSectionDirective *Dir = new (Mem) OMPSectionDirective(StartLoc, EndLoc); @@ -2041,6 +2041,27 @@ OMPTaskwaitDirective *OMPTaskwaitDirective::CreateEmpty(const ASTContext &C, return new (Mem) OMPTaskwaitDirective(); } +OMPTaskgroupDirective *OMPTaskgroupDirective::Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation EndLoc, + Stmt *AssociatedStmt) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTaskgroupDirective), + llvm::alignOf()); + void *Mem = C.Allocate(Size + sizeof(Stmt *)); + OMPTaskgroupDirective *Dir = + new (Mem) OMPTaskgroupDirective(StartLoc, EndLoc); + Dir->setAssociatedStmt(AssociatedStmt); + return Dir; +} + +OMPTaskgroupDirective *OMPTaskgroupDirective::CreateEmpty(const ASTContext &C, + EmptyShell) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTaskgroupDirective), + llvm::alignOf()); + void *Mem = C.Allocate(Size + sizeof(Stmt *)); + return new (Mem) OMPTaskgroupDirective(); +} + OMPFlushDirective *OMPFlushDirective::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index aabe974..658e3df 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -910,6 +910,11 @@ void StmtPrinter::VisitOMPTaskwaitDirective(OMPTaskwaitDirective *Node) { PrintOMPExecutableDirective(Node); } +void StmtPrinter::VisitOMPTaskgroupDirective(OMPTaskgroupDirective *Node) { + Indent() << "#pragma omp taskgroup"; + PrintOMPExecutableDirective(Node); +} + void StmtPrinter::VisitOMPFlushDirective(OMPFlushDirective *Node) { Indent() << "#pragma omp flush "; PrintOMPExecutableDirective(Node); diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index fb5350e..23f8d0c 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -510,6 +510,10 @@ void StmtProfiler::VisitOMPTaskwaitDirective(const OMPTaskwaitDirective *S) { VisitOMPExecutableDirective(S); } +void StmtProfiler::VisitOMPTaskgroupDirective(const OMPTaskgroupDirective *S) { + VisitOMPExecutableDirective(S); +} + void StmtProfiler::VisitOMPFlushDirective(const OMPFlushDirective *S) { VisitOMPExecutableDirective(S); } diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp index b83a069..b2798b7 100644 --- a/clang/lib/Basic/OpenMPKinds.cpp +++ b/clang/lib/Basic/OpenMPKinds.cpp @@ -332,6 +332,7 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind, case OMPD_taskyield: case OMPD_barrier: case OMPD_taskwait: + case OMPD_taskgroup: case OMPD_ordered: break; } diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index 269799d..b9ade9b 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -741,7 +741,7 @@ CGOpenMPRuntime::createRuntimeFunction(OpenMPRTLFunction Function) { break; } case OMPRTL__kmpc_end_ordered: { - // Build void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid); + // Build void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid); llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; llvm::FunctionType *FnTy = llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); @@ -756,6 +756,22 @@ CGOpenMPRuntime::createRuntimeFunction(OpenMPRTLFunction Function) { RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_omp_taskwait"); break; } + case OMPRTL__kmpc_taskgroup: { + // Build void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid); + llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; + llvm::FunctionType *FnTy = + llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); + RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_taskgroup"); + break; + } + case OMPRTL__kmpc_end_taskgroup: { + // Build void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid); + llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; + llvm::FunctionType *FnTy = + llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); + RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_taskgroup"); + break; + } } return RTLFn; } @@ -1240,6 +1256,25 @@ void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF, CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskyield), Args); } +void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF, + const RegionCodeGenTy &TaskgroupOpGen, + SourceLocation Loc) { + // __kmpc_taskgroup(ident_t *, gtid); + // TaskgroupOpGen(); + // __kmpc_end_taskgroup(ident_t *, gtid); + // Prepare arguments and build a call to __kmpc_taskgroup + { + CodeGenFunction::RunCleanupsScope Scope(CGF); + llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; + CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_taskgroup), Args); + // Build a call to __kmpc_end_taskgroup + CGF.EHStack.pushCleanup::value>>( + NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_taskgroup), + llvm::makeArrayRef(Args)); + emitInlinedDirective(CGF, TaskgroupOpGen); + } +} + static llvm::Value *emitCopyprivateCopyFunction( CodeGenModule &CGM, llvm::Type *ArgsType, ArrayRef CopyprivateVars, ArrayRef DestExprs, diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.h b/clang/lib/CodeGen/CGOpenMPRuntime.h index 4db3db4..95c578e 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.h +++ b/clang/lib/CodeGen/CGOpenMPRuntime.h @@ -131,6 +131,10 @@ private: // Call to kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 // global_tid); OMPRTL__kmpc_omp_taskwait, + // Call to void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid); + OMPRTL__kmpc_taskgroup, + // Call to void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid); + OMPRTL__kmpc_end_taskgroup, }; /// \brief Values for bit flags used in the ident_t to describe the fields. @@ -388,6 +392,13 @@ public: /// \brief Emits code for a taskyield directive. virtual void emitTaskyieldCall(CodeGenFunction &CGF, SourceLocation Loc); + /// \brief Emit a taskgroup region. + /// \param TaskgroupOpGen Generator for the statement associated with the + /// given taskgroup region. + virtual void emitTaskgroupRegion(CodeGenFunction &CGF, + const RegionCodeGenTy &TaskgroupOpGen, + SourceLocation Loc); + /// \brief Emits a single region. /// \param SingleOpGen Generator for the statement associated with the given /// single region. @@ -401,7 +412,7 @@ public: /// \brief Emit an ordered region. /// \param OrderedOpGen Generator for the statement associated with the given - /// critical region. + /// ordered region. virtual void emitOrderedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &OrderedOpGen, SourceLocation Loc); diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index a79b3e3..9286f03 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -222,6 +222,9 @@ void CodeGenFunction::EmitStmt(const Stmt *S) { case Stmt::OMPTaskwaitDirectiveClass: EmitOMPTaskwaitDirective(cast(*S)); break; + case Stmt::OMPTaskgroupDirectiveClass: + EmitOMPTaskgroupDirective(cast(*S)); + break; case Stmt::OMPFlushDirectiveClass: EmitOMPFlushDirective(cast(*S)); break; diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index 06860f8..2bad038 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -1612,6 +1612,16 @@ void CodeGenFunction::EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &S) { CGM.getOpenMPRuntime().emitTaskwaitCall(*this, S.getLocStart()); } +void CodeGenFunction::EmitOMPTaskgroupDirective( + const OMPTaskgroupDirective &S) { + LexicalScope Scope(*this, S.getSourceRange()); + auto &&CodeGen = [&S](CodeGenFunction &CGF) { + CGF.EmitStmt(cast(S.getAssociatedStmt())->getCapturedStmt()); + CGF.EnsureInsertPoint(); + }; + CGM.getOpenMPRuntime().emitTaskgroupRegion(*this, CodeGen, S.getLocStart()); +} + void CodeGenFunction::EmitOMPFlushDirective(const OMPFlushDirective &S) { CGM.getOpenMPRuntime().emitFlush(*this, [&]() -> ArrayRef { if (auto C = S.getSingleClause(/*K*/ OMPC_flush)) { diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 920a550..9377fe5 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -2169,6 +2169,7 @@ public: void EmitOMPTaskyieldDirective(const OMPTaskyieldDirective &S); void EmitOMPBarrierDirective(const OMPBarrierDirective &S); void EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &S); + void EmitOMPTaskgroupDirective(const OMPTaskgroupDirective &S); void EmitOMPFlushDirective(const OMPFlushDirective &S); void EmitOMPOrderedDirective(const OMPOrderedDirective &S); void EmitOMPAtomicDirective(const OMPAtomicDirective &S); diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index 187289e..a3c3c5d 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -94,6 +94,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() { case OMPD_taskyield: case OMPD_barrier: case OMPD_taskwait: + case OMPD_taskgroup: case OMPD_flush: case OMPD_for: case OMPD_for_simd: @@ -128,7 +129,8 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() { /// 'section' | 'single' | 'master' | 'critical' [ '(' ')' ] | /// 'parallel for' | 'parallel sections' | 'task' | 'taskyield' | /// 'barrier' | 'taskwait' | 'flush' | 'ordered' | 'atomic' | -/// 'for simd' | 'parallel for simd' | 'target' | 'teams' {clause} +/// 'for simd' | 'parallel for simd' | 'target' | 'teams' | 'taskgroup' +/// {clause} /// annot_pragma_openmp_end /// StmtResult @@ -198,7 +200,8 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) { case OMPD_ordered: case OMPD_atomic: case OMPD_target: - case OMPD_teams: { + case OMPD_teams: + case OMPD_taskgroup: { ConsumeToken(); // Parse directive name of the 'critical' directive if any. if (DKind == OMPD_critical) { diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index ea619ff..e609fcf 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -1270,6 +1270,14 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) { Params); break; } + case OMPD_taskgroup: { + Sema::CapturedParamNameType Params[] = { + std::make_pair(StringRef(), QualType()) // __context with shared vars + }; + ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP, + Params); + break; + } case OMPD_threadprivate: case OMPD_taskyield: case OMPD_barrier: @@ -1335,6 +1343,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | parallel | taskyield | * | // | parallel | barrier | * | // | parallel | taskwait | * | + // | parallel | taskgroup | * | // | parallel | flush | * | // | parallel | ordered | + | // | parallel | atomic | * | @@ -1357,6 +1366,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | for | taskyield | * | // | for | barrier | + | // | for | taskwait | * | + // | for | taskgroup | * | // | for | flush | * | // | for | ordered | * (if construct is ordered) | // | for | atomic | * | @@ -1379,6 +1389,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | master | taskyield | * | // | master | barrier | + | // | master | taskwait | * | + // | master | taskgroup | * | // | master | flush | * | // | master | ordered | + | // | master | atomic | * | @@ -1401,6 +1412,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | critical | taskyield | * | // | critical | barrier | + | // | critical | taskwait | * | + // | critical | taskgroup | * | // | critical | ordered | + | // | critical | atomic | * | // | critical | target | * | @@ -1422,6 +1434,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | simd | taskyield | | // | simd | barrier | | // | simd | taskwait | | + // | simd | taskgroup | | // | simd | flush | | // | simd | ordered | | // | simd | atomic | | @@ -1444,6 +1457,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | for simd | taskyield | | // | for simd | barrier | | // | for simd | taskwait | | + // | for simd | taskgroup | | // | for simd | flush | | // | for simd | ordered | | // | for simd | atomic | | @@ -1466,6 +1480,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | parallel for simd| taskyield | | // | parallel for simd| barrier | | // | parallel for simd| taskwait | | + // | parallel for simd| taskgroup | | // | parallel for simd| flush | | // | parallel for simd| ordered | | // | parallel for simd| atomic | | @@ -1488,6 +1503,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | sections | taskyield | * | // | sections | barrier | + | // | sections | taskwait | * | + // | sections | taskgroup | * | // | sections | flush | * | // | sections | ordered | + | // | sections | atomic | * | @@ -1510,6 +1526,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | section | taskyield | * | // | section | barrier | + | // | section | taskwait | * | + // | section | taskgroup | * | // | section | flush | * | // | section | ordered | + | // | section | atomic | * | @@ -1532,6 +1549,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | single | taskyield | * | // | single | barrier | + | // | single | taskwait | * | + // | single | taskgroup | * | // | single | flush | * | // | single | ordered | + | // | single | atomic | * | @@ -1554,6 +1572,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | parallel for | taskyield | * | // | parallel for | barrier | + | // | parallel for | taskwait | * | + // | parallel for | taskgroup | * | // | parallel for | flush | * | // | parallel for | ordered | * (if construct is ordered) | // | parallel for | atomic | * | @@ -1576,6 +1595,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | parallel sections| taskyield | * | // | parallel sections| barrier | + | // | parallel sections| taskwait | * | + // | parallel sections| taskgroup | * | // | parallel sections| flush | * | // | parallel sections| ordered | + | // | parallel sections| atomic | * | @@ -1598,6 +1618,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | task | taskyield | * | // | task | barrier | + | // | task | taskwait | * | + // | task | taskgroup | * | // | task | flush | * | // | task | ordered | + | // | task | atomic | * | @@ -1620,6 +1641,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | ordered | taskyield | * | // | ordered | barrier | + | // | ordered | taskwait | * | + // | ordered | taskgroup | * | // | ordered | flush | * | // | ordered | ordered | + | // | ordered | atomic | * | @@ -1642,6 +1664,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | atomic | taskyield | | // | atomic | barrier | | // | atomic | taskwait | | + // | atomic | taskgroup | | // | atomic | flush | | // | atomic | ordered | | // | atomic | atomic | | @@ -1664,6 +1687,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | target | taskyield | * | // | target | barrier | * | // | target | taskwait | * | + // | target | taskgroup | * | // | target | flush | * | // | target | ordered | * | // | target | atomic | * | @@ -1686,6 +1710,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | teams | taskyield | + | // | teams | barrier | + | // | teams | taskwait | + | + // | teams | taskgroup | + | // | teams | flush | + | // | teams | ordered | + | // | teams | atomic | + | @@ -1936,6 +1961,11 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind, "No associated statement allowed for 'omp taskwait' directive"); Res = ActOnOpenMPTaskwaitDirective(StartLoc, EndLoc); break; + case OMPD_taskgroup: + assert(ClausesWithImplicit.empty() && + "No clauses are allowed for 'omp taskgroup' directive"); + Res = ActOnOpenMPTaskgroupDirective(AStmt, StartLoc, EndLoc); + break; case OMPD_flush: assert(AStmt == nullptr && "No associated statement allowed for 'omp flush' directive"); @@ -3398,6 +3428,16 @@ StmtResult Sema::ActOnOpenMPTaskwaitDirective(SourceLocation StartLoc, return OMPTaskwaitDirective::Create(Context, StartLoc, EndLoc); } +StmtResult Sema::ActOnOpenMPTaskgroupDirective(Stmt *AStmt, + SourceLocation StartLoc, + SourceLocation EndLoc) { + assert(AStmt && isa(AStmt) && "Captured statement expected"); + + getCurFunction()->setHasBranchProtectedScope(); + + return OMPTaskgroupDirective::Create(Context, StartLoc, EndLoc, AStmt); +} + StmtResult Sema::ActOnOpenMPFlushDirective(ArrayRef Clauses, SourceLocation StartLoc, SourceLocation EndLoc) { diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index fde8946..878300e 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -6871,6 +6871,17 @@ TreeTransform::TransformOMPTaskwaitDirective(OMPTaskwaitDirective *D) { } template +StmtResult TreeTransform::TransformOMPTaskgroupDirective( + OMPTaskgroupDirective *D) { + DeclarationNameInfo DirName; + getDerived().getSema().StartOpenMPDSABlock(OMPD_taskgroup, DirName, nullptr, + D->getLocStart()); + StmtResult Res = getDerived().TransformOMPExecutableDirective(D); + getDerived().getSema().EndOpenMPDSABlock(Res.get()); + return Res; +} + +template StmtResult TreeTransform::TransformOMPFlushDirective(OMPFlushDirective *D) { DeclarationNameInfo DirName; diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index e0cd189..c15f6b0 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -2189,6 +2189,11 @@ void ASTStmtReader::VisitOMPTaskwaitDirective(OMPTaskwaitDirective *D) { VisitOMPExecutableDirective(D); } +void ASTStmtReader::VisitOMPTaskgroupDirective(OMPTaskgroupDirective *D) { + VisitStmt(D); + VisitOMPExecutableDirective(D); +} + void ASTStmtReader::VisitOMPFlushDirective(OMPFlushDirective *D) { VisitStmt(D); // The NumClauses field was read in ReadStmtFromStream. @@ -2803,6 +2808,10 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { S = OMPTaskwaitDirective::CreateEmpty(Context, Empty); break; + case STMT_OMP_TASKGROUP_DIRECTIVE: + S = OMPTaskgroupDirective::CreateEmpty(Context, Empty); + break; + case STMT_OMP_FLUSH_DIRECTIVE: S = OMPFlushDirective::CreateEmpty( Context, Record[ASTStmtReader::NumStmtFields], Empty); diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index 4c12d95..a461d3f 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -2071,6 +2071,12 @@ void ASTStmtWriter::VisitOMPTaskwaitDirective(OMPTaskwaitDirective *D) { Code = serialization::STMT_OMP_TASKWAIT_DIRECTIVE; } +void ASTStmtWriter::VisitOMPTaskgroupDirective(OMPTaskgroupDirective *D) { + VisitStmt(D); + VisitOMPExecutableDirective(D); + Code = serialization::STMT_OMP_TASKGROUP_DIRECTIVE; +} + void ASTStmtWriter::VisitOMPFlushDirective(OMPFlushDirective *D) { VisitStmt(D); Record.push_back(D->getNumClauses()); diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index c5f34da..ef515fb 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -816,6 +816,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, case Stmt::OMPTaskyieldDirectiveClass: case Stmt::OMPBarrierDirectiveClass: case Stmt::OMPTaskwaitDirectiveClass: + case Stmt::OMPTaskgroupDirectiveClass: case Stmt::OMPFlushDirectiveClass: case Stmt::OMPOrderedDirectiveClass: case Stmt::OMPAtomicDirectiveClass: diff --git a/clang/test/OpenMP/taskgroup_ast_print.cpp b/clang/test/OpenMP/taskgroup_ast_print.cpp new file mode 100644 index 0000000..683141e --- /dev/null +++ b/clang/test/OpenMP/taskgroup_ast_print.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s +// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s +// expected-no-diagnostics + +#ifndef HEADER +#define HEADER + +void foo() {} + +int main (int argc, char **argv) { + int b = argc, c, d, e, f, g; + static int a; +// CHECK: static int a; +#pragma omp taskgroup + a=2; +// CHECK-NEXT: #pragma omp taskgroup +// CHECK-NEXT: a = 2; +// CHECK-NEXT: ++a; + ++a; +#pragma omp taskgroup + foo(); +// CHECK-NEXT: #pragma omp taskgroup +// CHECK-NEXT: foo(); +// CHECK-NEXT: return 0; + return 0; +} + +#endif diff --git a/clang/test/OpenMP/taskgroup_codegen.cpp b/clang/test/OpenMP/taskgroup_codegen.cpp new file mode 100644 index 0000000..a6aec1f --- /dev/null +++ b/clang/test/OpenMP/taskgroup_codegen.cpp @@ -0,0 +1,56 @@ +// RUN: %clang_cc1 -verify -fopenmp -x c++ -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck %s +// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -fexceptions -fcxx-exceptions -gline-tables-only -x c++ -emit-llvm %s -o - | FileCheck %s --check-prefix=TERM_DEBUG +// expected-no-diagnostics + +#ifndef HEADER +#define HEADER + +// CHECK: [[IDENT_T_TY:%.+]] = type { i32, i32, i32, i32, i8* } + +// CHECK: define void [[FOO:@.+]]() + +void foo() {} + +// CHECK-LABEL: @main +// TERM_DEBUG-LABEL: @main +int main() { +// CHECK: [[A_ADDR:%.+]] = alloca i8 + char a; + +// CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num([[IDENT_T_TY]]* [[DEFAULT_LOC:@.+]]) +// CHECK: call void @__kmpc_taskgroup([[IDENT_T_TY]]* [[DEFAULT_LOC]], i32 [[GTID]]) +// CHECK-NEXT: store i8 2, i8* [[A_ADDR]] +// CHECK-NEXT: call void @__kmpc_end_taskgroup([[IDENT_T_TY]]* [[DEFAULT_LOC]], i32 [[GTID]]) +#pragma omp taskgroup + a = 2; +// CHECK: call void @__kmpc_taskgroup([[IDENT_T_TY]]* [[DEFAULT_LOC]], i32 [[GTID]]) +// CHECK-NEXT: invoke void [[FOO]]() +// CHECK: call void @__kmpc_end_taskgroup([[IDENT_T_TY]]* [[DEFAULT_LOC]], i32 [[GTID]]) +#pragma omp taskgroup + foo(); +// CHECK-NOT: call void @__kmpc_taskgroup +// CHECK-NOT: call void @__kmpc_end_taskgroup + return a; +} + +// CHECK-LABEL: parallel_taskgroup +// TERM_DEBUG-LABEL: parallel_taskgroup +void parallel_taskgroup() { +#pragma omp parallel +#pragma omp taskgroup + // TERM_DEBUG-NOT: __kmpc_global_thread_num + // TERM_DEBUG: call void @__kmpc_taskgroup({{.+}}), !dbg [[DBG_LOC_START:![0-9]+]] + // TERM_DEBUG: invoke void {{.*}}foo{{.*}}() + // TERM_DEBUG: unwind label %[[TERM_LPAD:.+]], + // TERM_DEBUG-NOT: __kmpc_global_thread_num + // TERM_DEBUG: call void @__kmpc_end_taskgroup({{.+}}), !dbg [[DBG_LOC_END:![0-9]+]] + // TERM_DEBUG: [[TERM_LPAD]] + // TERM_DEBUG: call void @__clang_call_terminate + // TERM_DEBUG: unreachable + foo(); +} +// TERM_DEBUG-DAG: [[DBG_LOC_START]] = !DILocation(line: [[@LINE-12]], +// TERM_DEBUG-DAG: [[DBG_LOC_END]] = !DILocation(line: [[@LINE-3]], +#endif diff --git a/clang/test/OpenMP/taskgroup_messages.cpp b/clang/test/OpenMP/taskgroup_messages.cpp new file mode 100644 index 0000000..e893da4 --- /dev/null +++ b/clang/test/OpenMP/taskgroup_messages.cpp @@ -0,0 +1,67 @@ +// RUN: %clang_cc1 -verify -fopenmp %s + +int foo(); + +int main() { + #pragma omp taskgroup + ; + #pragma omp taskgroup unknown // expected-warning {{extra tokens at the end of '#pragma omp taskgroup' are ignored}} + foo(); + { + #pragma omp taskgroup + } // expected-error {{expected statement}} + #pragma omp taskgroup + #pragma omp taskgroup + for (int i = 0; i < 10; ++i) { + foo(); + #pragma omp parallel + #pragma omp for + for (int j = 0; j < 10; j++) { + foo(); + #pragma omp taskgroup + foo(); + } + } + #pragma omp taskgroup + #pragma omp taskgroup + for (int i = 0; i < 10; ++i) { + foo(); + #pragma omp parallel + #pragma omp for + for (int j = 0; j < 10; j++) { + #pragma omp taskgroup + foo(); + } + } + #pragma omp taskgroup + #pragma omp taskgroup + for (int i = 0; i < 10; ++i) { + foo(); + #pragma omp parallel + #pragma omp for + for (int j = 0; j < 10; j++) { + #pragma omp taskgroup + foo(); + } + } + + return 0; +} + +int foo() { + L1: + foo(); + #pragma omp taskgroup + { + foo(); + goto L1; // expected-error {{use of undeclared label 'L1'}} + } + goto L2; // expected-error {{use of undeclared label 'L2'}} + #pragma omp taskgroup + { + L2: + foo(); + } + + return 0; +} diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index 05287bd..bdefa9b 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -1879,6 +1879,7 @@ public: void VisitOMPTaskyieldDirective(const OMPTaskyieldDirective *D); void VisitOMPBarrierDirective(const OMPBarrierDirective *D); void VisitOMPTaskwaitDirective(const OMPTaskwaitDirective *D); + void VisitOMPTaskgroupDirective(const OMPTaskgroupDirective *D); void VisitOMPFlushDirective(const OMPFlushDirective *D); void VisitOMPOrderedDirective(const OMPOrderedDirective *D); void VisitOMPAtomicDirective(const OMPAtomicDirective *D); @@ -2478,6 +2479,11 @@ void EnqueueVisitor::VisitOMPTaskwaitDirective(const OMPTaskwaitDirective *D) { VisitOMPExecutableDirective(D); } +void EnqueueVisitor::VisitOMPTaskgroupDirective( + const OMPTaskgroupDirective *D) { + VisitOMPExecutableDirective(D); +} + void EnqueueVisitor::VisitOMPFlushDirective(const OMPFlushDirective *D) { VisitOMPExecutableDirective(D); } @@ -4260,6 +4266,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) { return cxstring::createRef("OMPBarrierDirective"); case CXCursor_OMPTaskwaitDirective: return cxstring::createRef("OMPTaskwaitDirective"); + case CXCursor_OMPTaskgroupDirective: + return cxstring::createRef("OMPTaskgroupDirective"); case CXCursor_OMPFlushDirective: return cxstring::createRef("OMPFlushDirective"); case CXCursor_OMPOrderedDirective: diff --git a/clang/tools/libclang/CXCursor.cpp b/clang/tools/libclang/CXCursor.cpp index 68334d4..b8bb28e 100644 --- a/clang/tools/libclang/CXCursor.cpp +++ b/clang/tools/libclang/CXCursor.cpp @@ -570,6 +570,9 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent, case Stmt::OMPTaskwaitDirectiveClass: K = CXCursor_OMPTaskwaitDirective; break; + case Stmt::OMPTaskgroupDirectiveClass: + K = CXCursor_OMPTaskgroupDirective; + break; case Stmt::OMPFlushDirectiveClass: K = CXCursor_OMPFlushDirective; break; -- 2.7.4