diff options
author | Alexey Bataev <a.bataev@hotmail.com> | 2015-07-03 09:56:58 +0000 |
---|---|---|
committer | Alexey Bataev <a.bataev@hotmail.com> | 2015-07-03 09:56:58 +0000 |
commit | 81c7ea0ec35494940dfeaabef8f6e3e75f3bd807 (patch) | |
tree | 9c895063ec5c75fd52040e3892ab41dca3ff1981 /clang/lib/CodeGen/CGOpenMPRuntime.cpp | |
parent | 40178c352e5b8841df4862490d112c2a1db0b058 (diff) | |
download | bcm5719-llvm-81c7ea0ec35494940dfeaabef8f6e3e75f3bd807.tar.gz bcm5719-llvm-81c7ea0ec35494940dfeaabef8f6e3e75f3bd807.zip |
[OPENMP 4.0] Fixed codegen for 'cancellation point' construct.
Generate the next code for 'cancellation point':
if (__kmpc_cancellationpoint()) {
__kmpc_cancel_barrier();
<exit construct>;
}
llvm-svn: 241336
Diffstat (limited to 'clang/lib/CodeGen/CGOpenMPRuntime.cpp')
-rw-r--r-- | clang/lib/CodeGen/CGOpenMPRuntime.cpp | 158 |
1 files changed, 101 insertions, 57 deletions
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index 5fe81c2443c..534d148209b 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -45,14 +45,14 @@ public: CGOpenMPRegionInfo(const CapturedStmt &CS, const CGOpenMPRegionKind RegionKind, - const RegionCodeGenTy &CodeGen) + const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind) : CGCapturedStmtInfo(CS, CR_OpenMP), RegionKind(RegionKind), - CodeGen(CodeGen) {} + CodeGen(CodeGen), Kind(Kind) {} CGOpenMPRegionInfo(const CGOpenMPRegionKind RegionKind, - const RegionCodeGenTy &CodeGen) - : CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind), - CodeGen(CodeGen) {} + const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind) + : CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen), + Kind(Kind) {} /// \brief Get a variable or parameter for storing global thread id /// inside OpenMP construct. @@ -67,6 +67,8 @@ public: CGOpenMPRegionKind getRegionKind() const { return RegionKind; } + OpenMPDirectiveKind getDirectiveKind() const { return Kind; } + static bool classof(const CGCapturedStmtInfo *Info) { return Info->getKind() == CR_OpenMP; } @@ -74,14 +76,16 @@ public: protected: CGOpenMPRegionKind RegionKind; const RegionCodeGenTy &CodeGen; + OpenMPDirectiveKind Kind; }; /// \brief API for captured statement code generation in OpenMP constructs. class CGOpenMPOutlinedRegionInfo : public CGOpenMPRegionInfo { public: CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar, - const RegionCodeGenTy &CodeGen) - : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen), + const RegionCodeGenTy &CodeGen, + OpenMPDirectiveKind Kind) + : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen, Kind), ThreadIDVar(ThreadIDVar) { assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); } @@ -109,8 +113,9 @@ class CGOpenMPTaskOutlinedRegionInfo : public CGOpenMPRegionInfo { public: CGOpenMPTaskOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar, - const RegionCodeGenTy &CodeGen) - : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen), + const RegionCodeGenTy &CodeGen, + OpenMPDirectiveKind Kind) + : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen, Kind), ThreadIDVar(ThreadIDVar) { assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); } @@ -141,8 +146,9 @@ private: class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo { public: CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI, - const RegionCodeGenTy &CodeGen) - : CGOpenMPRegionInfo(InlinedRegion, CodeGen), OldCSI(OldCSI), + const RegionCodeGenTy &CodeGen, + OpenMPDirectiveKind Kind) + : CGOpenMPRegionInfo(InlinedRegion, CodeGen, Kind), OldCSI(OldCSI), OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {} // \brief Retrieve the value of the context parameter. llvm::Value *getContextValue() const override { @@ -207,11 +213,12 @@ public: /// \param CodeGen Code generation sequence for combined directives. Includes /// a list of functions used for code generation of implicitly inlined /// regions. - InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen) + InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen, + OpenMPDirectiveKind Kind) : CGF(CGF) { // Start emission for the construct. CGF.CapturedStmtInfo = - new CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, CodeGen); + new CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, CodeGen, Kind); } ~InlinedOpenMPRegionRAII() { // Restore original CapturedStmtInfo only if we're done with code emission. @@ -273,28 +280,27 @@ void CGOpenMPRuntime::clear() { InternalVars.clear(); } -llvm::Value * -CGOpenMPRuntime::emitParallelOutlinedFunction(const OMPExecutableDirective &D, - const VarDecl *ThreadIDVar, - const RegionCodeGenTy &CodeGen) { +llvm::Value *CGOpenMPRuntime::emitParallelOutlinedFunction( + const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, + OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { assert(ThreadIDVar->getType()->isPointerType() && "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); + CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind); CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); return CGF.GenerateCapturedStmtFunction(*CS); } -llvm::Value * -CGOpenMPRuntime::emitTaskOutlinedFunction(const OMPExecutableDirective &D, - const VarDecl *ThreadIDVar, - const RegionCodeGenTy &CodeGen) { +llvm::Value *CGOpenMPRuntime::emitTaskOutlinedFunction( + const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, + OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { assert(!ThreadIDVar->getType()->isPointerType() && "thread id variable must be of type kmp_int32 for tasks"); auto *CS = cast<CapturedStmt>(D.getAssociatedStmt()); CodeGenFunction CGF(CGM, true); - CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen); + CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, + InnermostKind); CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); return CGF.GenerateCapturedStmtFunction(*CS); } @@ -530,6 +536,14 @@ CGOpenMPRuntime::createRuntimeFunction(OpenMPRTLFunction Function) { RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier"); break; } + case OMPRTL__kmpc_barrier: { + // Build void __kmpc_cancel_barrier(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, /*Name*/ "__kmpc_barrier"); + break; + } case OMPRTL__kmpc_for_static_fini: { // Build void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid); llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; @@ -1246,11 +1260,12 @@ void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF, CGF.EHStack.pushCleanup<CallEndCleanup<std::extent<decltype(Args)>::value>>( NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_critical), llvm::makeArrayRef(Args)); - emitInlinedDirective(CGF, CriticalOpGen); + emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen); } } static void emitIfStmt(CodeGenFunction &CGF, llvm::Value *IfCond, + OpenMPDirectiveKind Kind, const RegionCodeGenTy &BodyOpGen) { llvm::Value *CallBool = CGF.EmitScalarConversion( IfCond, @@ -1262,7 +1277,7 @@ static void emitIfStmt(CodeGenFunction &CGF, llvm::Value *IfCond, // Generate the branch (If-stmt) CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock); CGF.EmitBlock(ThenBlock); - CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, BodyOpGen); + CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, Kind, BodyOpGen); // Emit the rest of bblocks/branches CGF.EmitBranch(ContBlock); CGF.EmitBlock(ContBlock, true); @@ -1281,7 +1296,7 @@ void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF, CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_master), Args); typedef CallEndCleanup<std::extent<decltype(Args)>::value> MasterCallEndCleanup; - emitIfStmt(CGF, IsMaster, [&](CodeGenFunction &CGF) -> void { + emitIfStmt(CGF, IsMaster, OMPD_master, [&](CodeGenFunction &CGF) -> void { CodeGenFunction::RunCleanupsScope Scope(CGF); CGF.EHStack.pushCleanup<MasterCallEndCleanup>( NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_master), @@ -1314,7 +1329,7 @@ void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF, CGF.EHStack.pushCleanup<CallEndCleanup<std::extent<decltype(Args)>::value>>( NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_taskgroup), llvm::makeArrayRef(Args)); - emitInlinedDirective(CGF, TaskgroupOpGen); + emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen); } } @@ -1410,7 +1425,7 @@ void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF, CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_single), Args); typedef CallEndCleanup<std::extent<decltype(Args)>::value> SingleCallEndCleanup; - emitIfStmt(CGF, IsSingle, [&](CodeGenFunction &CGF) -> void { + emitIfStmt(CGF, IsSingle, OMPD_single, [&](CodeGenFunction &CGF) -> void { CodeGenFunction::RunCleanupsScope Scope(CGF); CGF.EHStack.pushCleanup<SingleCallEndCleanup>( NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_single), @@ -1478,13 +1493,15 @@ void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF, CGF.EHStack.pushCleanup<CallEndCleanup<std::extent<decltype(Args)>::value>>( NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_ordered), llvm::makeArrayRef(Args)); - emitInlinedDirective(CGF, OrderedOpGen); + emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); } } void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, - OpenMPDirectiveKind Kind) { + OpenMPDirectiveKind Kind, + bool CheckForCancel) { // Build call __kmpc_cancel_barrier(loc, thread_id); + // Build call __kmpc_barrier(loc, thread_id); OpenMPLocationFlags Flags = OMP_IDENT_KMPC; if (Kind == OMPD_for) { Flags = @@ -1500,15 +1517,34 @@ void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, } else { Flags = static_cast<OpenMPLocationFlags>(Flags | OMP_IDENT_BARRIER_IMPL); } - // Build call __kmpc_cancel_barrier(loc, thread_id); - // Replace __kmpc_barrier() function by __kmpc_cancel_barrier() because this - // one provides the same functionality and adds initial support for - // cancellation constructs introduced in OpenMP 4.0. __kmpc_cancel_barrier() - // is provided default by the runtime library so it safe to make such - // replacement. + // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc, + // thread_id); llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags), getThreadID(CGF, Loc)}; - CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args); + if (auto *OMPRegionInfo = + dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { + auto CancelDestination = + CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); + if (CancelDestination.isValid()) { + auto *Result = CGF.EmitRuntimeCall( + createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args); + if (CheckForCancel) { + // if (__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); + // exit from construct; + CGF.EmitBranchThroughCleanup(CancelDestination); + CGF.EmitBlock(ContBB, /*IsFinished=*/true); + } + return; + } + } + CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_barrier), Args); } /// \brief Schedule types for 'omp for' loops (these enumerators are taken from @@ -2681,8 +2717,9 @@ void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF, } void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF, + OpenMPDirectiveKind InnerKind, const RegionCodeGenTy &CodeGen) { - InlinedOpenMPRegionRAII Region(CGF, CodeGen); + InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind); CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr); } @@ -2708,25 +2745,32 @@ void CGOpenMPRuntime::emitCancellationPointCall( assert(CancelRegion == OMPD_taskgroup); CancelKind = CancelTaskgroup; } - llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), - CGF.Builder.getInt32(CancelKind)}; - // Ignore return result until untied tasks are supported. - auto *Result = CGF.EmitRuntimeCall( - createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args); - // if (__kmpc_cancellationpoint()) - // 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); - if (CancelRegion == OMPD_parallel || CancelRegion == OMPD_taskgroup) { - CGF.EmitBranchThroughCleanup(CGF.ReturnBlock); - } else { - assert(CancelRegion == OMPD_for || CancelRegion == OMPD_sections); - BreakStmt PseudoBrStmt(Loc); - CGF.EmitBreakStmt(PseudoBrStmt); + if (auto *OMPRegionInfo = + dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { + auto CancelDest = + CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); + if (CancelDest.isValid()) { + llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), + getThreadID(CGF, Loc), + CGF.Builder.getInt32(CancelKind)}; + // Ignore return result until untied tasks are supported. + auto *Result = CGF.EmitRuntimeCall( + createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args); + // if (__kmpc_cancellationpoint()) { + // __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.EmitBlock(ContBB, /*IsFinished=*/true); } |