summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r--clang/lib/CodeGen/CGBlocks.cpp28
-rw-r--r--clang/lib/CodeGen/CGOpenCLRuntime.cpp40
-rw-r--r--clang/lib/CodeGen/CGOpenCLRuntime.h15
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h12
4 files changed, 56 insertions, 39 deletions
diff --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp
index d60b5fbb70d..bbef9292d2c 100644
--- a/clang/lib/CodeGen/CGBlocks.cpp
+++ b/clang/lib/CodeGen/CGBlocks.cpp
@@ -740,27 +740,19 @@ void CodeGenFunction::destroyBlockInfos(CGBlockInfo *head) {
}
/// Emit a block literal expression in the current function.
-llvm::Value *CodeGenFunction::EmitBlockLiteral(const BlockExpr *blockExpr,
- llvm::Function **InvokeF) {
+llvm::Value *CodeGenFunction::EmitBlockLiteral(const BlockExpr *blockExpr) {
// If the block has no captures, we won't have a pre-computed
// layout for it.
if (!blockExpr->getBlockDecl()->hasCaptures()) {
// The block literal is emitted as a global variable, and the block invoke
// function has to be extracted from its initializer.
if (llvm::Constant *Block = CGM.getAddrOfGlobalBlockIfEmitted(blockExpr)) {
- if (InvokeF) {
- auto *GV = cast<llvm::GlobalVariable>(
- cast<llvm::Constant>(Block)->stripPointerCasts());
- auto *BlockInit = cast<llvm::ConstantStruct>(GV->getInitializer());
- *InvokeF = cast<llvm::Function>(
- BlockInit->getAggregateElement(2)->stripPointerCasts());
- }
return Block;
}
CGBlockInfo blockInfo(blockExpr->getBlockDecl(), CurFn->getName());
computeBlockInfo(CGM, this, blockInfo);
blockInfo.BlockExpression = blockExpr;
- return EmitBlockLiteral(blockInfo, InvokeF);
+ return EmitBlockLiteral(blockInfo);
}
// Find the block info for this block and take ownership of it.
@@ -769,11 +761,10 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const BlockExpr *blockExpr,
blockExpr->getBlockDecl()));
blockInfo->BlockExpression = blockExpr;
- return EmitBlockLiteral(*blockInfo, InvokeF);
+ return EmitBlockLiteral(*blockInfo);
}
-llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo,
- llvm::Function **InvokeF) {
+llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
bool IsOpenCL = CGM.getContext().getLangOpts().OpenCL;
auto GenVoidPtrTy =
IsOpenCL ? CGM.getOpenCLRuntime().getGenericVoidPointerType() : VoidPtrTy;
@@ -788,8 +779,6 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo,
BlockCGF.SanOpts = SanOpts;
auto *InvokeFn = BlockCGF.GenerateBlockFunction(
CurGD, blockInfo, LocalDeclMap, isLambdaConv, blockInfo.CanBeGlobal);
- if (InvokeF)
- *InvokeF = InvokeFn;
auto *blockFn = llvm::ConstantExpr::getPointerCast(InvokeFn, GenVoidPtrTy);
// If there is nothing to capture, we can emit this as a global block.
@@ -1024,6 +1013,11 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo,
llvm::Value *result = Builder.CreatePointerCast(
blockAddr.getPointer(), ConvertType(blockInfo.getBlockExpr()->getType()));
+ if (IsOpenCL) {
+ CGM.getOpenCLRuntime().recordBlockInfo(blockInfo.BlockExpression, InvokeFn,
+ result);
+ }
+
return result;
}
@@ -1287,6 +1281,10 @@ static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM,
llvm::Constant *Result =
llvm::ConstantExpr::getPointerCast(literal, RequiredType);
CGM.setAddrOfGlobalBlock(blockInfo.BlockExpression, Result);
+ if (CGM.getContext().getLangOpts().OpenCL)
+ CGM.getOpenCLRuntime().recordBlockInfo(
+ blockInfo.BlockExpression,
+ cast<llvm::Function>(blockFn->stripPointerCasts()), Result);
return Result;
}
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];
}
diff --git a/clang/lib/CodeGen/CGOpenCLRuntime.h b/clang/lib/CodeGen/CGOpenCLRuntime.h
index ead303d1d0d..c0088b5bcd8 100644
--- a/clang/lib/CodeGen/CGOpenCLRuntime.h
+++ b/clang/lib/CodeGen/CGOpenCLRuntime.h
@@ -23,6 +23,7 @@
namespace clang {
+class BlockExpr;
class Expr;
class VarDecl;
@@ -39,8 +40,9 @@ protected:
/// Structure for enqueued block information.
struct EnqueuedBlockInfo {
- llvm::Function *Kernel; /// Enqueued block kernel.
- llvm::Value *BlockArg; /// The first argument to enqueued block kernel.
+ llvm::Function *InvokeFunc; /// Block invoke function.
+ llvm::Function *Kernel; /// Enqueued block kernel.
+ llvm::Value *BlockArg; /// The first argument to enqueued block kernel.
};
/// Maps block expression to block information.
llvm::DenseMap<const Expr *, EnqueuedBlockInfo> EnqueuedBlockMap;
@@ -76,6 +78,15 @@ public:
/// \return enqueued block information for enqueued block.
EnqueuedBlockInfo emitOpenCLEnqueuedBlock(CodeGenFunction &CGF,
const Expr *E);
+
+ /// \brief Record invoke function and block literal emitted during normal
+ /// codegen for a block expression. The information is used by
+ /// emitOpenCLEnqueuedBlock to emit wrapper kernel.
+ ///
+ /// \param InvokeF invoke function emitted for the block expression.
+ /// \param Block block literal emitted for the block expression.
+ void recordBlockInfo(const BlockExpr *E, llvm::Function *InvokeF,
+ llvm::Value *Block);
};
}
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 78335018936..c530e37bd66 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -1583,10 +1583,7 @@ public:
/// \return an LLVM value which is a pointer to a struct which contains
/// information about the block, including the block invoke function, the
/// captured variables, etc.
- /// \param InvokeF will contain the block invoke function if it is not
- /// nullptr.
- llvm::Value *EmitBlockLiteral(const BlockExpr *,
- llvm::Function **InvokeF = nullptr);
+ llvm::Value *EmitBlockLiteral(const BlockExpr *);
static void destroyBlockInfos(CGBlockInfo *info);
llvm::Function *GenerateBlockFunction(GlobalDecl GD,
@@ -3010,11 +3007,8 @@ public:
LValue EmitOMPSharedLValue(const Expr *E);
private:
- /// Helpers for blocks. Returns invoke function by \p InvokeF if it is not
- /// nullptr. It should be called without \p InvokeF if the caller does not
- /// need invoke function to be returned.
- llvm::Value *EmitBlockLiteral(const CGBlockInfo &Info,
- llvm::Function **InvokeF = nullptr);
+ /// Helpers for blocks.
+ llvm::Value *EmitBlockLiteral(const CGBlockInfo &Info);
/// struct with the values to be passed to the OpenMP loop-related functions
struct OMPLoopArguments {
OpenPOWER on IntegriCloud