diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/Stmt.cpp | 34 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGOpenMPRuntime.cpp | 126 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGOpenMPRuntime.h | 14 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGStmtOpenMP.cpp | 60 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOpenMP.cpp | 50 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReaderStmt.cpp | 7 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriterStmt.cpp | 7 |
7 files changed, 192 insertions, 106 deletions
diff --git a/clang/lib/AST/Stmt.cpp b/clang/lib/AST/Stmt.cpp index 2169da32453..265b7290406 100644 --- a/clang/lib/AST/Stmt.cpp +++ b/clang/lib/AST/Stmt.cpp @@ -1622,11 +1622,8 @@ OMPDependClause *OMPDependClause::CreateEmpty(const ASTContext &C, unsigned N) { } OMPParallelDirective *OMPParallelDirective::Create( - const ASTContext &C, - SourceLocation StartLoc, - SourceLocation EndLoc, - ArrayRef<OMPClause *> Clauses, - Stmt *AssociatedStmt) { + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel) { unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPParallelDirective), llvm::alignOf<OMPClause *>()); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + @@ -1635,6 +1632,7 @@ OMPParallelDirective *OMPParallelDirective::Create( Clauses.size()); Dir->setClauses(Clauses); Dir->setAssociatedStmt(AssociatedStmt); + Dir->setHasCancel(HasCancel); return Dir; } @@ -1693,7 +1691,7 @@ OMPForDirective * OMPForDirective::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, - const HelperExprs &Exprs) { + const HelperExprs &Exprs, bool HasCancel) { unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPForDirective), llvm::alignOf<OMPClause *>()); void *Mem = @@ -1722,6 +1720,7 @@ OMPForDirective::Create(const ASTContext &C, SourceLocation StartLoc, Dir->setInits(Exprs.Inits); Dir->setUpdates(Exprs.Updates); Dir->setFinals(Exprs.Finals); + Dir->setHasCancel(HasCancel); return Dir; } @@ -1787,7 +1786,7 @@ OMPForSimdDirective *OMPForSimdDirective::CreateEmpty(const ASTContext &C, OMPSectionsDirective *OMPSectionsDirective::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, - ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) { + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel) { unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPSectionsDirective), llvm::alignOf<OMPClause *>()); void *Mem = @@ -1796,6 +1795,7 @@ OMPSectionsDirective *OMPSectionsDirective::Create( new (Mem) OMPSectionsDirective(StartLoc, EndLoc, Clauses.size()); Dir->setClauses(Clauses); Dir->setAssociatedStmt(AssociatedStmt); + Dir->setHasCancel(HasCancel); return Dir; } @@ -1812,12 +1812,14 @@ OMPSectionsDirective *OMPSectionsDirective::CreateEmpty(const ASTContext &C, OMPSectionDirective *OMPSectionDirective::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, - Stmt *AssociatedStmt) { + Stmt *AssociatedStmt, + bool HasCancel) { unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPSectionDirective), llvm::alignOf<Stmt *>()); void *Mem = C.Allocate(Size + sizeof(Stmt *)); OMPSectionDirective *Dir = new (Mem) OMPSectionDirective(StartLoc, EndLoc); Dir->setAssociatedStmt(AssociatedStmt); + Dir->setHasCancel(HasCancel); return Dir; } @@ -1898,7 +1900,7 @@ OMPCriticalDirective *OMPCriticalDirective::CreateEmpty(const ASTContext &C, OMPParallelForDirective *OMPParallelForDirective::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, - const HelperExprs &Exprs) { + const HelperExprs &Exprs, bool HasCancel) { unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPParallelForDirective), llvm::alignOf<OMPClause *>()); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + @@ -1927,6 +1929,7 @@ OMPParallelForDirective *OMPParallelForDirective::Create( Dir->setInits(Exprs.Inits); Dir->setUpdates(Exprs.Updates); Dir->setFinals(Exprs.Finals); + Dir->setHasCancel(HasCancel); return Dir; } @@ -1990,7 +1993,7 @@ OMPParallelForSimdDirective::CreateEmpty(const ASTContext &C, OMPParallelSectionsDirective *OMPParallelSectionsDirective::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, - ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) { + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel) { unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPParallelSectionsDirective), llvm::alignOf<OMPClause *>()); void *Mem = @@ -1999,6 +2002,7 @@ OMPParallelSectionsDirective *OMPParallelSectionsDirective::Create( new (Mem) OMPParallelSectionsDirective(StartLoc, EndLoc, Clauses.size()); Dir->setClauses(Clauses); Dir->setAssociatedStmt(AssociatedStmt); + Dir->setHasCancel(HasCancel); return Dir; } @@ -2012,11 +2016,10 @@ OMPParallelSectionsDirective::CreateEmpty(const ASTContext &C, return new (Mem) OMPParallelSectionsDirective(NumClauses); } -OMPTaskDirective *OMPTaskDirective::Create(const ASTContext &C, - SourceLocation StartLoc, - SourceLocation EndLoc, - ArrayRef<OMPClause *> Clauses, - Stmt *AssociatedStmt) { +OMPTaskDirective * +OMPTaskDirective::Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses, + Stmt *AssociatedStmt, bool HasCancel) { unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTaskDirective), llvm::alignOf<OMPClause *>()); void *Mem = @@ -2025,6 +2028,7 @@ OMPTaskDirective *OMPTaskDirective::Create(const ASTContext &C, new (Mem) OMPTaskDirective(StartLoc, EndLoc, Clauses.size()); Dir->setClauses(Clauses); Dir->setAssociatedStmt(AssociatedStmt); + Dir->setHasCancel(HasCancel); return Dir; } diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index a9e7a9c5552..f7e1d03e7e9 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -45,14 +45,16 @@ public: CGOpenMPRegionInfo(const CapturedStmt &CS, const CGOpenMPRegionKind RegionKind, - const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind) + const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind, + bool HasCancel) : CGCapturedStmtInfo(CS, CR_OpenMP), RegionKind(RegionKind), - CodeGen(CodeGen), Kind(Kind) {} + CodeGen(CodeGen), Kind(Kind), HasCancel(HasCancel) {} CGOpenMPRegionInfo(const CGOpenMPRegionKind RegionKind, - const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind) + const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind, + bool HasCancel) : CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen), - Kind(Kind) {} + Kind(Kind), HasCancel(HasCancel) {} /// \brief Get a variable or parameter for storing global thread id /// inside OpenMP construct. @@ -69,6 +71,8 @@ public: OpenMPDirectiveKind getDirectiveKind() const { return Kind; } + bool hasCancel() const { return HasCancel; } + static bool classof(const CGCapturedStmtInfo *Info) { return Info->getKind() == CR_OpenMP; } @@ -77,6 +81,7 @@ protected: CGOpenMPRegionKind RegionKind; const RegionCodeGenTy &CodeGen; OpenMPDirectiveKind Kind; + bool HasCancel; }; /// \brief API for captured statement code generation in OpenMP constructs. @@ -84,8 +89,9 @@ class CGOpenMPOutlinedRegionInfo : public CGOpenMPRegionInfo { public: CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar, const RegionCodeGenTy &CodeGen, - OpenMPDirectiveKind Kind) - : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen, Kind), + OpenMPDirectiveKind Kind, bool HasCancel) + : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen, Kind, + HasCancel), ThreadIDVar(ThreadIDVar) { assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); } @@ -114,8 +120,8 @@ public: CGOpenMPTaskOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar, const RegionCodeGenTy &CodeGen, - OpenMPDirectiveKind Kind) - : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen, Kind), + OpenMPDirectiveKind Kind, bool HasCancel) + : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen, Kind, HasCancel), ThreadIDVar(ThreadIDVar) { assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); } @@ -147,8 +153,9 @@ class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo { public: CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI, const RegionCodeGenTy &CodeGen, - OpenMPDirectiveKind Kind) - : CGOpenMPRegionInfo(InlinedRegion, CodeGen, Kind), OldCSI(OldCSI), + OpenMPDirectiveKind Kind, bool HasCancel) + : CGOpenMPRegionInfo(InlinedRegion, CodeGen, Kind, HasCancel), + OldCSI(OldCSI), OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {} // \brief Retrieve the value of the context parameter. llvm::Value *getContextValue() const override { @@ -214,11 +221,11 @@ public: /// a list of functions used for code generation of implicitly inlined /// regions. InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen, - OpenMPDirectiveKind Kind) + OpenMPDirectiveKind Kind, bool HasCancel) : CGF(CGF) { // Start emission for the construct. - CGF.CapturedStmtInfo = - new CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, CodeGen, Kind); + CGF.CapturedStmtInfo = new CGOpenMPInlinedRegionInfo( + CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel); } ~InlinedOpenMPRegionRAII() { // Restore original CapturedStmtInfo only if we're done with code emission. @@ -309,7 +316,15 @@ llvm::Value *CGOpenMPRuntime::emitParallelOutlinedFunction( "thread id variable must be of type kmp_int32 *"); const CapturedStmt *CS = cast<CapturedStmt>(D.getAssociatedStmt()); CodeGenFunction CGF(CGM, true); - CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind); + bool HasCancel = false; + if (auto *OPD = dyn_cast<OMPParallelDirective>(&D)) + HasCancel = OPD->hasCancel(); + else if (auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D)) + HasCancel = OPSD->hasCancel(); + else if (auto *OPFD = dyn_cast<OMPParallelForDirective>(&D)) + HasCancel = OPFD->hasCancel(); + CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind, + HasCancel); CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); return CGF.GenerateOpenMPCapturedStmtFunction(*CS); } @@ -322,7 +337,8 @@ llvm::Value *CGOpenMPRuntime::emitTaskOutlinedFunction( auto *CS = cast<CapturedStmt>(D.getAssociatedStmt()); CodeGenFunction CGF(CGM, true); CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, - InnermostKind); + InnermostKind, + cast<OMPTaskDirective>(D).hasCancel()); CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); return CGF.GenerateCapturedStmtFunction(*CS); } @@ -1550,8 +1566,8 @@ void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF, } void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, - OpenMPDirectiveKind Kind, - bool CheckForCancel) { + OpenMPDirectiveKind Kind, bool EmitChecks, + bool ForceSimpleCall) { // Build call __kmpc_cancel_barrier(loc, thread_id); // Build call __kmpc_barrier(loc, thread_id); OpenMPLocationFlags Flags = OMP_IDENT_KMPC; @@ -1571,16 +1587,19 @@ void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, } // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc, // thread_id); + auto *OMPRegionInfo = + dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo); + // Do not emit barrier call in the single directive emitted in some rare cases + // for sections directives. + if (OMPRegionInfo && OMPRegionInfo->getDirectiveKind() == OMPD_single) + return; llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags), getThreadID(CGF, Loc)}; - if (auto *OMPRegionInfo = - dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { - auto CancelDestination = - CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); - if (CancelDestination.isValid()) { + if (OMPRegionInfo) { + if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) { auto *Result = CGF.EmitRuntimeCall( createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args); - if (CheckForCancel) { + if (EmitChecks) { // if (__kmpc_cancel_barrier()) { // exit from construct; // } @@ -1590,6 +1609,8 @@ void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); CGF.EmitBlock(ExitBB); // exit from construct; + auto CancelDestination = + CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); CGF.EmitBranchThroughCleanup(CancelDestination); CGF.EmitBlock(ContBB, /*IsFinished=*/true); } @@ -2825,8 +2846,9 @@ void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF, void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF, OpenMPDirectiveKind InnerKind, - const RegionCodeGenTy &CodeGen) { - InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind); + const RegionCodeGenTy &CodeGen, + bool HasCancel) { + InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel); CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr); } @@ -2862,9 +2884,9 @@ void CGOpenMPRuntime::emitCancellationPointCall( // global_tid, kmp_int32 cncl_kind); if (auto *OMPRegionInfo = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { - auto CancelDest = - CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); - if (CancelDest.isValid()) { + if (OMPRegionInfo->getDirectiveKind() == OMPD_single) + return; + if (OMPRegionInfo->hasCancel()) { llvm::Value *Args[] = { emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; @@ -2881,8 +2903,10 @@ void CGOpenMPRuntime::emitCancellationPointCall( CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); CGF.EmitBlock(ExitBB); // __kmpc_cancel_barrier(); - emitBarrierCall(CGF, Loc, OMPD_unknown, /*CheckForCancel=*/false); + emitBarrierCall(CGF, Loc, OMPD_unknown, /*EmitChecks=*/false); // exit from construct; + auto CancelDest = + CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); CGF.EmitBranchThroughCleanup(CancelDest); CGF.EmitBlock(ContBB, /*IsFinished=*/true); } @@ -2895,29 +2919,29 @@ void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, // kmp_int32 cncl_kind); if (auto *OMPRegionInfo = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { + if (OMPRegionInfo->getDirectiveKind() == OMPD_single) + return; + llvm::Value *Args[] = { + emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), + CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; + // Ignore return result until untied tasks are supported. + auto *Result = + CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_cancel), Args); + // if (__kmpc_cancel()) { + // __kmpc_cancel_barrier(); + // exit from construct; + // } + auto *ExitBB = CGF.createBasicBlock(".cancel.exit"); + auto *ContBB = CGF.createBasicBlock(".cancel.continue"); + auto *Cmp = CGF.Builder.CreateIsNotNull(Result); + CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); + CGF.EmitBlock(ExitBB); + // __kmpc_cancel_barrier(); + emitBarrierCall(CGF, Loc, OMPD_unknown, /*EmitChecks=*/false); + // exit from construct; auto CancelDest = CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); - if (CancelDest.isValid()) { - llvm::Value *Args[] = { - emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), - CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; - // Ignore return result until untied tasks are supported. - auto *Result = - CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_cancel), Args); - // if (__kmpc_cancel()) { - // __kmpc_cancel_barrier(); - // exit from construct; - // } - auto *ExitBB = CGF.createBasicBlock(".cancel.exit"); - auto *ContBB = CGF.createBasicBlock(".cancel.continue"); - auto *Cmp = CGF.Builder.CreateIsNotNull(Result); - CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); - CGF.EmitBlock(ExitBB); - // __kmpc_cancel_barrier(); - emitBarrierCall(CGF, Loc, OMPD_unknown, /*CheckForCancel=*/false); - // exit from construct; - CGF.EmitBranchThroughCleanup(CancelDest); - CGF.EmitBlock(ContBB, /*IsFinished=*/true); - } + CGF.EmitBranchThroughCleanup(CancelDest); + CGF.EmitBlock(ContBB, /*IsFinished=*/true); } } diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.h b/clang/lib/CodeGen/CGOpenMPRuntime.h index 2cd4917ae9d..b9ad6432e9a 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.h +++ b/clang/lib/CodeGen/CGOpenMPRuntime.h @@ -454,12 +454,15 @@ public: /// \brief Emit an implicit/explicit barrier for OpenMP threads. /// \param Kind Directive for which this implicit barrier call must be /// generated. Must be OMPD_barrier for explicit barrier generation. - /// \param CheckForCancel true if check for possible cancellation must be - /// performed, false otherwise. + /// \param EmitChecks true if need to emit checks for cancellation barriers. + /// \param ForceSimpleCall true simple barrier call must be emitted, false if + /// runtime class decides which one to emit (simple or with cancellation + /// checks). /// virtual void emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind Kind, - bool CheckForCancel = true); + bool EmitChecks = true, + bool ForceSimpleCall = false); /// \brief Check if the specified \a ScheduleKind is static non-chunked. /// This kind of worksharing directive is emitted without outer loop. @@ -654,9 +657,12 @@ public: /// \param InnermostKind Kind of innermost directive (for simple directives it /// is a directive itself, for combined - its innermost directive). /// \param CodeGen Code generation sequence for the \a D directive. + /// \param HasCancel true if region has inner cancel directive, false + /// otherwise. virtual void emitInlinedDirective(CodeGenFunction &CGF, OpenMPDirectiveKind InnermostKind, - const RegionCodeGenTy &CodeGen); + const RegionCodeGenTy &CodeGen, + bool HasCancel = false); /// \brief Emit a code for reduction clause. Next code should be emitted for /// reduction: /// \code diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index 03f473631e0..70f86385d57 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -624,8 +624,9 @@ void CodeGenFunction::EmitOMPParallelDirective(const OMPParallelDirective &S) { // initialization of firstprivate variables or propagation master's thread // values of threadprivate variables to local instances of that variables // of all other implicit threads. - CGF.CGM.getOpenMPRuntime().emitBarrierCall(CGF, S.getLocStart(), - OMPD_unknown); + CGF.CGM.getOpenMPRuntime().emitBarrierCall( + CGF, S.getLocStart(), OMPD_unknown, /*EmitChecks=*/false, + /*ForceSimpleCall=*/true); } CGF.EmitOMPPrivateClause(S, PrivateScope); CGF.EmitOMPReductionClauseInit(S, PrivateScope); @@ -633,8 +634,9 @@ void CodeGenFunction::EmitOMPParallelDirective(const OMPParallelDirective &S) { CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt()); CGF.EmitOMPReductionClauseFinal(S); // Emit implicit barrier at the end of the 'parallel' directive. - CGF.CGM.getOpenMPRuntime().emitBarrierCall(CGF, S.getLocStart(), - OMPD_unknown); + CGF.CGM.getOpenMPRuntime().emitBarrierCall( + CGF, S.getLocStart(), OMPD_unknown, /*EmitChecks=*/false, + /*ForceSimpleCall=*/true); }; emitCommonOMPParallelDirective(*this, S, OMPD_parallel, CodeGen); } @@ -1238,8 +1240,9 @@ bool CodeGenFunction::EmitOMPWorksharingLoop(const OMPLoopDirective &S) { if (EmitOMPFirstprivateClause(S, LoopScope)) { // Emit implicit barrier to synchronize threads and avoid data races on // initialization of firstprivate variables. - CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(), - OMPD_unknown); + CGM.getOpenMPRuntime().emitBarrierCall( + *this, S.getLocStart(), OMPD_unknown, /*EmitChecks=*/false, + /*ForceSimpleCall=*/true); } EmitOMPPrivateClause(S, LoopScope); HasLastprivateClause = EmitOMPLastprivateClauseInit(S, LoopScope); @@ -1321,7 +1324,8 @@ void CodeGenFunction::EmitOMPForDirective(const OMPForDirective &S) { auto &&CodeGen = [&S, &HasLastprivates](CodeGenFunction &CGF) { HasLastprivates = CGF.EmitOMPWorksharingLoop(S); }; - CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_for, CodeGen); + CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_for, CodeGen, + S.hasCancel()); // Emit an implicit barrier at the end. if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates) { @@ -1416,8 +1420,9 @@ CodeGenFunction::EmitSections(const OMPExecutableDirective &S) { if (CGF.EmitOMPFirstprivateClause(S, LoopScope)) { // Emit implicit barrier to synchronize threads and avoid data races on // initialization of firstprivate variables. - CGF.CGM.getOpenMPRuntime().emitBarrierCall(CGF, S.getLocStart(), - OMPD_unknown); + CGF.CGM.getOpenMPRuntime().emitBarrierCall( + CGF, S.getLocStart(), OMPD_unknown, /*EmitChecks=*/false, + /*ForceSimpleCall=*/true); } CGF.EmitOMPPrivateClause(S, LoopScope); HasLastprivates = CGF.EmitOMPLastprivateClauseInit(S, LoopScope); @@ -1450,7 +1455,13 @@ CodeGenFunction::EmitSections(const OMPExecutableDirective &S) { CGF.EmitLoadOfScalar(IL, S.getLocStart()))); }; - CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_sections, CodeGen); + bool HasCancel = false; + if (auto *OSD = dyn_cast<OMPSectionsDirective>(&S)) + HasCancel = OSD->hasCancel(); + else if (auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&S)) + HasCancel = OPSD->hasCancel(); + CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_sections, CodeGen, + HasCancel); // Emit barrier for lastprivates only if 'sections' directive has 'nowait' // clause. Otherwise the barrier will be generated by the codegen for the // directive. @@ -1490,7 +1501,9 @@ CodeGenFunction::EmitSections(const OMPExecutableDirective &S) { S.getSingleClause<OMPNowaitClause>()) { // Emit implicit barrier to synchronize threads and avoid data races on // initialization of firstprivate variables. - CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(), OMPD_unknown); + CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(), OMPD_unknown, + /*EmitChecks=*/false, + /*ForceSimpleCall=*/true); } return OMPD_single; } @@ -1510,7 +1523,8 @@ void CodeGenFunction::EmitOMPSectionDirective(const OMPSectionDirective &S) { CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt()); CGF.EnsureInsertPoint(); }; - CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_section, CodeGen); + CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_section, CodeGen, + S.hasCancel()); } void CodeGenFunction::EmitOMPSingleDirective(const OMPSingleDirective &S) { @@ -1586,8 +1600,9 @@ void CodeGenFunction::EmitOMPParallelForDirective( // Emit implicit barrier at the end of parallel region, but this barrier // is at the end of 'for' directive, so emit it as the implicit barrier for // this 'for' directive. - CGF.CGM.getOpenMPRuntime().emitBarrierCall(CGF, S.getLocStart(), - OMPD_parallel); + CGF.CGM.getOpenMPRuntime().emitBarrierCall( + CGF, S.getLocStart(), OMPD_parallel, /*EmitChecks=*/false, + /*ForceSimpleCall=*/true); }; emitCommonOMPParallelDirective(*this, S, OMPD_for, CodeGen); } @@ -1603,8 +1618,9 @@ void CodeGenFunction::EmitOMPParallelForSimdDirective( // Emit implicit barrier at the end of parallel region, but this barrier // is at the end of 'for' directive, so emit it as the implicit barrier for // this 'for' directive. - CGF.CGM.getOpenMPRuntime().emitBarrierCall(CGF, S.getLocStart(), - OMPD_parallel); + CGF.CGM.getOpenMPRuntime().emitBarrierCall( + CGF, S.getLocStart(), OMPD_parallel, /*EmitChecks=*/false, + /*ForceSimpleCall=*/true); }; emitCommonOMPParallelDirective(*this, S, OMPD_simd, CodeGen); } @@ -1617,8 +1633,9 @@ void CodeGenFunction::EmitOMPParallelSectionsDirective( auto &&CodeGen = [&S](CodeGenFunction &CGF) { (void)CGF.EmitSections(S); // Emit implicit barrier at the end of parallel region. - CGF.CGM.getOpenMPRuntime().emitBarrierCall(CGF, S.getLocStart(), - OMPD_parallel); + CGF.CGM.getOpenMPRuntime().emitBarrierCall( + CGF, S.getLocStart(), OMPD_parallel, /*EmitChecks=*/false, + /*ForceSimpleCall=*/true); }; emitCommonOMPParallelDirective(*this, S, OMPD_sections, CodeGen); } @@ -2253,10 +2270,9 @@ CodeGenFunction::JumpDest CodeGenFunction::getOMPCancelDestination(OpenMPDirectiveKind Kind) { if (Kind == OMPD_parallel || Kind == OMPD_task) return ReturnBlock; - else if (Kind == OMPD_for || Kind == OMPD_section || Kind == OMPD_sections) - return BreakContinueStack.empty() ? JumpDest() - : BreakContinueStack.back().BreakBlock; - return JumpDest(); + assert(Kind == OMPD_for || Kind == OMPD_section || Kind == OMPD_sections || + Kind == OMPD_parallel_sections || Kind == OMPD_parallel_for); + return BreakContinueStack.back().BreakBlock; } // Generate the instructions for '#pragma omp target data' directive. diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index bc5fadcc5d9..cf7ce23866d 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -98,6 +98,7 @@ private: SourceLocation ConstructLoc; bool OrderedRegion; bool NowaitRegion; + bool CancelRegion; unsigned CollapseNumber; SourceLocation InnerTeamsRegionLoc; SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name, @@ -105,12 +106,12 @@ private: : SharingMap(), AlignedMap(), LCVSet(), DefaultAttr(DSA_unspecified), Directive(DKind), DirectiveName(std::move(Name)), CurScope(CurScope), ConstructLoc(Loc), OrderedRegion(false), NowaitRegion(false), - CollapseNumber(1), InnerTeamsRegionLoc() {} + CancelRegion(false), CollapseNumber(1), InnerTeamsRegionLoc() {} SharingMapTy() : SharingMap(), AlignedMap(), LCVSet(), DefaultAttr(DSA_unspecified), Directive(OMPD_unknown), DirectiveName(), CurScope(nullptr), ConstructLoc(), OrderedRegion(false), NowaitRegion(false), - CollapseNumber(1), InnerTeamsRegionLoc() {} + CancelRegion(false), CollapseNumber(1), InnerTeamsRegionLoc() {} }; typedef SmallVector<SharingMapTy, 64> StackTy; @@ -251,6 +252,16 @@ public: return Stack[Stack.size() - 2].NowaitRegion; return false; } + /// \brief Marks parent region as cancel region. + void setParentCancelRegion(bool Cancel = true) { + if (Stack.size() > 2) + Stack[Stack.size() - 2].CancelRegion = + Stack[Stack.size() - 2].CancelRegion || Cancel; + } + /// \brief Return true if current region has inner cancel construct. + bool isCancelRegion() const { + return Stack.back().CancelRegion; + } /// \brief Set collapse value for the region. void setCollapseNumber(unsigned Val) { Stack.back().CollapseNumber = Val; } @@ -1901,10 +1912,12 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // construct-type-clause. NestingProhibited = !((CancelRegion == OMPD_parallel && ParentRegion == OMPD_parallel) || - (CancelRegion == OMPD_for && ParentRegion == OMPD_for) || + (CancelRegion == OMPD_for && + (ParentRegion == OMPD_for || ParentRegion == OMPD_parallel_for)) || (CancelRegion == OMPD_taskgroup && ParentRegion == OMPD_task) || (CancelRegion == OMPD_sections && - (ParentRegion == OMPD_section || ParentRegion == OMPD_sections))); + (ParentRegion == OMPD_section || ParentRegion == OMPD_sections || + ParentRegion == OMPD_parallel_sections))); } else if (CurrentRegion == OMPD_master) { // OpenMP [2.16, Nesting of Regions] // A master region may not be closely nested inside a worksharing, @@ -2275,8 +2288,8 @@ StmtResult Sema::ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses, getCurFunction()->setHasBranchProtectedScope(); - return OMPParallelDirective::Create(Context, StartLoc, EndLoc, Clauses, - AStmt); + return OMPParallelDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt, + DSAStack->isCancelRegion()); } namespace { @@ -3741,7 +3754,7 @@ StmtResult Sema::ActOnOpenMPForDirective( getCurFunction()->setHasBranchProtectedScope(); return OMPForDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount, - Clauses, AStmt, B); + Clauses, AStmt, B, DSAStack->isCancelRegion()); } StmtResult Sema::ActOnOpenMPForSimdDirective( @@ -3822,6 +3835,8 @@ StmtResult Sema::ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses, diag::err_omp_sections_substmt_not_section); return StmtError(); } + cast<OMPSectionDirective>(SectionStmt) + ->setHasCancel(DSAStack->isCancelRegion()); } } else { Diag(AStmt->getLocStart(), diag::err_omp_sections_not_compound_stmt); @@ -3830,8 +3845,8 @@ StmtResult Sema::ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses, getCurFunction()->setHasBranchProtectedScope(); - return OMPSectionsDirective::Create(Context, StartLoc, EndLoc, Clauses, - AStmt); + return OMPSectionsDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt, + DSAStack->isCancelRegion()); } StmtResult Sema::ActOnOpenMPSectionDirective(Stmt *AStmt, @@ -3843,8 +3858,10 @@ StmtResult Sema::ActOnOpenMPSectionDirective(Stmt *AStmt, assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); getCurFunction()->setHasBranchProtectedScope(); + DSAStack->setParentCancelRegion(DSAStack->isCancelRegion()); - return OMPSectionDirective::Create(Context, StartLoc, EndLoc, AStmt); + return OMPSectionDirective::Create(Context, StartLoc, EndLoc, AStmt, + DSAStack->isCancelRegion()); } StmtResult Sema::ActOnOpenMPSingleDirective(ArrayRef<OMPClause *> Clauses, @@ -3946,7 +3963,8 @@ StmtResult Sema::ActOnOpenMPParallelForDirective( getCurFunction()->setHasBranchProtectedScope(); return OMPParallelForDirective::Create(Context, StartLoc, EndLoc, - NestedLoopCount, Clauses, AStmt, B); + NestedLoopCount, Clauses, AStmt, B, + DSAStack->isCancelRegion()); } StmtResult Sema::ActOnOpenMPParallelForSimdDirective( @@ -4031,6 +4049,8 @@ Sema::ActOnOpenMPParallelSectionsDirective(ArrayRef<OMPClause *> Clauses, diag::err_omp_parallel_sections_substmt_not_section); return StmtError(); } + cast<OMPSectionDirective>(SectionStmt) + ->setHasCancel(DSAStack->isCancelRegion()); } } else { Diag(AStmt->getLocStart(), @@ -4040,8 +4060,8 @@ Sema::ActOnOpenMPParallelSectionsDirective(ArrayRef<OMPClause *> Clauses, getCurFunction()->setHasBranchProtectedScope(); - return OMPParallelSectionsDirective::Create(Context, StartLoc, EndLoc, - Clauses, AStmt); + return OMPParallelSectionsDirective::Create( + Context, StartLoc, EndLoc, Clauses, AStmt, DSAStack->isCancelRegion()); } StmtResult Sema::ActOnOpenMPTaskDirective(ArrayRef<OMPClause *> Clauses, @@ -4060,7 +4080,8 @@ StmtResult Sema::ActOnOpenMPTaskDirective(ArrayRef<OMPClause *> Clauses, getCurFunction()->setHasBranchProtectedScope(); - return OMPTaskDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt); + return OMPTaskDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt, + DSAStack->isCancelRegion()); } StmtResult Sema::ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc, @@ -4899,6 +4920,7 @@ StmtResult Sema::ActOnOpenMPCancelDirective(SourceLocation StartLoc, Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1; return StmtError(); } + DSAStack->setParentCancelRegion(/*Cancel=*/true); return OMPCancelDirective::Create(Context, StartLoc, EndLoc, CancelRegion); } diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index 9446db842f3..4501dd82b17 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -2167,6 +2167,7 @@ void ASTStmtReader::VisitOMPParallelDirective(OMPParallelDirective *D) { // The NumClauses field was read in ReadStmtFromStream. ++Idx; VisitOMPExecutableDirective(D); + D->setHasCancel(Record[Idx++]); } void ASTStmtReader::VisitOMPSimdDirective(OMPSimdDirective *D) { @@ -2175,6 +2176,7 @@ void ASTStmtReader::VisitOMPSimdDirective(OMPSimdDirective *D) { void ASTStmtReader::VisitOMPForDirective(OMPForDirective *D) { VisitOMPLoopDirective(D); + D->setHasCancel(Record[Idx++]); } void ASTStmtReader::VisitOMPForSimdDirective(OMPForSimdDirective *D) { @@ -2186,11 +2188,13 @@ void ASTStmtReader::VisitOMPSectionsDirective(OMPSectionsDirective *D) { // The NumClauses field was read in ReadStmtFromStream. ++Idx; VisitOMPExecutableDirective(D); + D->setHasCancel(Record[Idx++]); } void ASTStmtReader::VisitOMPSectionDirective(OMPSectionDirective *D) { VisitStmt(D); VisitOMPExecutableDirective(D); + D->setHasCancel(Record[Idx++]); } void ASTStmtReader::VisitOMPSingleDirective(OMPSingleDirective *D) { @@ -2213,6 +2217,7 @@ void ASTStmtReader::VisitOMPCriticalDirective(OMPCriticalDirective *D) { void ASTStmtReader::VisitOMPParallelForDirective(OMPParallelForDirective *D) { VisitOMPLoopDirective(D); + D->setHasCancel(Record[Idx++]); } void ASTStmtReader::VisitOMPParallelForSimdDirective( @@ -2226,6 +2231,7 @@ void ASTStmtReader::VisitOMPParallelSectionsDirective( // The NumClauses field was read in ReadStmtFromStream. ++Idx; VisitOMPExecutableDirective(D); + D->setHasCancel(Record[Idx++]); } void ASTStmtReader::VisitOMPTaskDirective(OMPTaskDirective *D) { @@ -2233,6 +2239,7 @@ void ASTStmtReader::VisitOMPTaskDirective(OMPTaskDirective *D) { // The NumClauses field was read in ReadStmtFromStream. ++Idx; VisitOMPExecutableDirective(D); + D->setHasCancel(Record[Idx++]); } void ASTStmtReader::VisitOMPTaskyieldDirective(OMPTaskyieldDirective *D) { diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index 7db73f5a53b..be1c69bf08b 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -2003,6 +2003,7 @@ void ASTStmtWriter::VisitOMPParallelDirective(OMPParallelDirective *D) { VisitStmt(D); Record.push_back(D->getNumClauses()); VisitOMPExecutableDirective(D); + Record.push_back(D->hasCancel() ? 1 : 0); Code = serialization::STMT_OMP_PARALLEL_DIRECTIVE; } @@ -2013,6 +2014,7 @@ void ASTStmtWriter::VisitOMPSimdDirective(OMPSimdDirective *D) { void ASTStmtWriter::VisitOMPForDirective(OMPForDirective *D) { VisitOMPLoopDirective(D); + Record.push_back(D->hasCancel() ? 1 : 0); Code = serialization::STMT_OMP_FOR_DIRECTIVE; } @@ -2025,12 +2027,14 @@ void ASTStmtWriter::VisitOMPSectionsDirective(OMPSectionsDirective *D) { VisitStmt(D); Record.push_back(D->getNumClauses()); VisitOMPExecutableDirective(D); + Record.push_back(D->hasCancel() ? 1 : 0); Code = serialization::STMT_OMP_SECTIONS_DIRECTIVE; } void ASTStmtWriter::VisitOMPSectionDirective(OMPSectionDirective *D) { VisitStmt(D); VisitOMPExecutableDirective(D); + Record.push_back(D->hasCancel() ? 1 : 0); Code = serialization::STMT_OMP_SECTION_DIRECTIVE; } @@ -2056,6 +2060,7 @@ void ASTStmtWriter::VisitOMPCriticalDirective(OMPCriticalDirective *D) { void ASTStmtWriter::VisitOMPParallelForDirective(OMPParallelForDirective *D) { VisitOMPLoopDirective(D); + Record.push_back(D->hasCancel() ? 1 : 0); Code = serialization::STMT_OMP_PARALLEL_FOR_DIRECTIVE; } @@ -2070,6 +2075,7 @@ void ASTStmtWriter::VisitOMPParallelSectionsDirective( VisitStmt(D); Record.push_back(D->getNumClauses()); VisitOMPExecutableDirective(D); + Record.push_back(D->hasCancel() ? 1 : 0); Code = serialization::STMT_OMP_PARALLEL_SECTIONS_DIRECTIVE; } @@ -2077,6 +2083,7 @@ void ASTStmtWriter::VisitOMPTaskDirective(OMPTaskDirective *D) { VisitStmt(D); Record.push_back(D->getNumClauses()); VisitOMPExecutableDirective(D); + Record.push_back(D->hasCancel() ? 1 : 0); Code = serialization::STMT_OMP_TASK_DIRECTIVE; } |