summaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGOpenCLRuntime.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2018-07-28 11:06:01 +0000
committerDimitry Andric <dim@FreeBSD.org>2018-07-28 11:06:01 +0000
commit486754660bb926339aefcf012a3f848592babb8b (patch)
treeecdbc446c9876f4f120f701c243373cd3cb43db3 /lib/CodeGen/CGOpenCLRuntime.cpp
parent55e6d896ad333f07bb3b1ba487df214fc268a4ab (diff)
Notes
Diffstat (limited to 'lib/CodeGen/CGOpenCLRuntime.cpp')
-rw-r--r--lib/CodeGen/CGOpenCLRuntime.cpp81
1 files changed, 57 insertions, 24 deletions
diff --git a/lib/CodeGen/CGOpenCLRuntime.cpp b/lib/CodeGen/CGOpenCLRuntime.cpp
index d140e7f09e9a..1da19a90c387 100644
--- a/lib/CodeGen/CGOpenCLRuntime.cpp
+++ b/lib/CodeGen/CGOpenCLRuntime.cpp
@@ -66,13 +66,19 @@ llvm::Type *CGOpenCLRuntime::convertOpenCLSpecificType(const Type *T) {
}
llvm::Type *CGOpenCLRuntime::getPipeType(const PipeType *T) {
- if (!PipeTy){
- uint32_t PipeAddrSpc = CGM.getContext().getTargetAddressSpace(
- CGM.getContext().getOpenCLTypeAddrSpace(T));
- PipeTy = llvm::PointerType::get(llvm::StructType::create(
- CGM.getLLVMContext(), "opencl.pipe_t"), PipeAddrSpc);
- }
+ if (T->isReadOnly())
+ return getPipeType(T, "opencl.pipe_ro_t", PipeROTy);
+ else
+ return getPipeType(T, "opencl.pipe_wo_t", PipeWOTy);
+}
+llvm::Type *CGOpenCLRuntime::getPipeType(const PipeType *T, StringRef Name,
+ llvm::Type *&PipeTy) {
+ if (!PipeTy)
+ PipeTy = llvm::PointerType::get(llvm::StructType::create(
+ CGM.getLLVMContext(), Name),
+ CGM.getContext().getTargetAddressSpace(
+ CGM.getContext().getOpenCLTypeAddrSpace(T)));
return PipeTy;
}
@@ -112,37 +118,64 @@ llvm::PointerType *CGOpenCLRuntime::getGenericVoidPointerType() {
CGM.getContext().getTargetAddressSpace(LangAS::opencl_generic));
}
-CGOpenCLRuntime::EnqueuedBlockInfo
-CGOpenCLRuntime::emitOpenCLEnqueuedBlock(CodeGenFunction &CGF, const Expr *E) {
- // The block literal may be assigned to a const variable. Chasing down
- // to get the block literal.
+// Get the block literal from an expression derived from the block expression.
+// OpenCL v2.0 s6.12.5:
+// Block variable declarations are implicitly qualified with const. Therefore
+// all block variables must be initialized at declaration time and may not be
+// reassigned.
+static const BlockExpr *getBlockExpr(const Expr *E) {
+ if (auto Cast = dyn_cast<CastExpr>(E)) {
+ E = Cast->getSubExpr();
+ }
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);
+ return cast<BlockExpr>(E);
+}
+
+/// 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;
+}
+
+llvm::Function *CGOpenCLRuntime::getInvokeFunction(const Expr *E) {
+ return EnqueuedBlockMap[getBlockExpr(E)].InvokeFunc;
+}
+
+CGOpenCLRuntime::EnqueuedBlockInfo
+CGOpenCLRuntime::emitOpenCLEnqueuedBlock(CodeGenFunction &CGF, const Expr *E) {
+ CGF.EmitScalarExpr(E);
+
+ const BlockExpr *Block = getBlockExpr(E);
+ assert(EnqueuedBlockMap.find(Block) != EnqueuedBlockMap.end() &&
+ "Block expression not emitted");
- // 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;
+ // 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];
}