diff options
Diffstat (limited to 'clang/lib/CodeGen/CGOpenCLRuntime.cpp')
-rw-r--r-- | clang/lib/CodeGen/CGOpenCLRuntime.cpp | 40 |
1 files changed, 27 insertions, 13 deletions
diff --git a/clang/lib/CodeGen/CGOpenCLRuntime.cpp b/clang/lib/CodeGen/CGOpenCLRuntime.cpp index d140e7f09e9..6d0089da83f 100644 --- a/clang/lib/CodeGen/CGOpenCLRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenCLRuntime.cpp @@ -112,37 +112,51 @@ llvm::PointerType *CGOpenCLRuntime::getGenericVoidPointerType() { CGM.getContext().getTargetAddressSpace(LangAS::opencl_generic)); } +/// Record emitted llvm invoke function and llvm block literal for the +/// corresponding block expression. +void CGOpenCLRuntime::recordBlockInfo(const BlockExpr *E, + llvm::Function *InvokeF, + llvm::Value *Block) { + assert(EnqueuedBlockMap.find(E) == EnqueuedBlockMap.end() && + "Block expression emitted twice"); + assert(isa<llvm::Function>(InvokeF) && "Invalid invoke function"); + assert(Block->getType()->isPointerTy() && "Invalid block literal type"); + EnqueuedBlockMap[E].InvokeFunc = InvokeF; + EnqueuedBlockMap[E].BlockArg = Block; + EnqueuedBlockMap[E].Kernel = nullptr; +} + CGOpenCLRuntime::EnqueuedBlockInfo CGOpenCLRuntime::emitOpenCLEnqueuedBlock(CodeGenFunction &CGF, const Expr *E) { + CGF.EmitScalarExpr(E); + // The block literal may be assigned to a const variable. Chasing down // to get the block literal. if (auto DR = dyn_cast<DeclRefExpr>(E)) { E = cast<VarDecl>(DR->getDecl())->getInit(); } + E = E->IgnoreImplicit(); if (auto Cast = dyn_cast<CastExpr>(E)) { E = Cast->getSubExpr(); } auto *Block = cast<BlockExpr>(E); - // The same block literal may be enqueued multiple times. Cache it if - // possible. - auto Loc = EnqueuedBlockMap.find(Block); - if (Loc != EnqueuedBlockMap.end()) { - return Loc->second; + assert(EnqueuedBlockMap.find(Block) != EnqueuedBlockMap.end() && + "Block expression not emitted"); + + // Do not emit the block wrapper again if it has been emitted. + if (EnqueuedBlockMap[Block].Kernel) { + return EnqueuedBlockMap[Block]; } - // Emit block literal as a common block expression and get the block invoke - // function. - llvm::Function *Invoke; - auto *V = CGF.EmitBlockLiteral(cast<BlockExpr>(Block), &Invoke); auto *F = CGF.getTargetHooks().createEnqueuedBlockKernel( - CGF, Invoke, V->stripPointerCasts()); + CGF, EnqueuedBlockMap[Block].InvokeFunc, + EnqueuedBlockMap[Block].BlockArg->stripPointerCasts()); // The common part of the post-processing of the kernel goes here. F->addFnAttr(llvm::Attribute::NoUnwind); F->setCallingConv( CGF.getTypes().ClangCallConvToLLVMCallConv(CallingConv::CC_OpenCLKernel)); - EnqueuedBlockInfo Info{F, V}; - EnqueuedBlockMap[Block] = Info; - return Info; + EnqueuedBlockMap[Block].Kernel = F; + return EnqueuedBlockMap[Block]; } |