aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen
diff options
context:
space:
mode:
authorEli Friedman <eli.friedman@gmail.com>2012-03-01 04:01:32 +0000
committerEli Friedman <eli.friedman@gmail.com>2012-03-01 04:01:32 +0000
commit23f0267e2d56c0407f12e62df3561ecf75d74e6e (patch)
treef6e536907913aaa1fa958f250092fefd74cb7d4c /lib/CodeGen
parent5e4e58b805e0e03a669aa517d1d20d4735a3192e (diff)
Implement "optimization" for lambda-to-block conversion which inlines the generated block literal for lambdas which are immediately converted to block pointer type. This simplifies the AST, avoids an unnecessary copy of the lambda and makes it much easier to avoid copying the result onto the heap.
Note that this transformation has a substantial semantic effect outside of ARC: it gives the converted lambda lifetime semantics similar to a block literal. With ARC, the effect is much less obvious because the lifetime of blocks is already managed. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@151797 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen')
-rw-r--r--lib/CodeGen/CGBlocks.cpp24
-rw-r--r--lib/CodeGen/CGClass.cpp2
-rw-r--r--lib/CodeGen/CodeGenFunction.cpp3
-rw-r--r--lib/CodeGen/CodeGenFunction.h1
4 files changed, 19 insertions, 11 deletions
diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp
index f6aa9b4b48..1b35fa0ee4 100644
--- a/lib/CodeGen/CGBlocks.cpp
+++ b/lib/CodeGen/CGBlocks.cpp
@@ -622,10 +622,11 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const BlockExpr *blockExpr) {
llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
// Using the computed layout, generate the actual block function.
+ bool isLambdaConv = blockInfo.getBlockDecl()->isConversionFromLambda();
llvm::Constant *blockFn
= CodeGenFunction(CGM).GenerateBlockFunction(CurGD, blockInfo,
CurFuncDecl, LocalDeclMap,
- InLambdaConversionToBlock);
+ isLambdaConv);
blockFn = llvm::ConstantExpr::getBitCast(blockFn, VoidPtrTy);
// If there is nothing to capture, we can emit this as a global block.
@@ -700,11 +701,10 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
src = Builder.CreateStructGEP(LoadBlockStruct(),
enclosingCapture.getIndex(),
"block.capture.addr");
- } else if (InLambdaConversionToBlock) {
+ } else if (blockDecl->isConversionFromLambda()) {
// The lambda capture in a lambda's conversion-to-block-pointer is
- // special; we know its argument is an lvalue we can simply emit.
- CXXConstructExpr *CE = cast<CXXConstructExpr>(ci->getCopyExpr());
- src = EmitLValue(CE->getArg(0)).getAddress();
+ // special; we'll simply emit it directly.
+ src = 0;
} else {
// This is a [[type]]*.
src = LocalDeclMap[variable];
@@ -726,7 +726,19 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
// If we have a copy constructor, evaluate that into the block field.
} else if (const Expr *copyExpr = ci->getCopyExpr()) {
- EmitSynthesizedCXXCopyCtor(blockField, src, copyExpr);
+ if (blockDecl->isConversionFromLambda()) {
+ // If we have a lambda conversion, emit the expression
+ // directly into the block instead.
+ CharUnits Align = getContext().getTypeAlignInChars(type);
+ AggValueSlot Slot =
+ AggValueSlot::forAddr(blockField, Align, Qualifiers(),
+ AggValueSlot::IsDestructed,
+ AggValueSlot::DoesNotNeedGCBarriers,
+ AggValueSlot::IsNotAliased);
+ EmitAggExpr(copyExpr, Slot);
+ } else {
+ EmitSynthesizedCXXCopyCtor(blockField, src, copyExpr);
+ }
// If it's a reference variable, copy the reference into the block field.
} else if (type->isReferenceType()) {
diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp
index e3b5777387..6b5a149710 100644
--- a/lib/CodeGen/CGClass.cpp
+++ b/lib/CodeGen/CGClass.cpp
@@ -1795,9 +1795,7 @@ void CodeGenFunction::EmitLambdaToBlockPointerBody(FunctionArgList &Args) {
return;
}
- InLambdaConversionToBlock = true;
EmitFunctionBody(Args);
- InLambdaConversionToBlock = false;
}
void CodeGenFunction::EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD) {
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index 5d18169695..47176bd8ec 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -32,8 +32,7 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm)
Target(CGM.getContext().getTargetInfo()),
Builder(cgm.getModule().getContext()),
AutoreleaseResult(false), BlockInfo(0), BlockPointer(0),
- LambdaThisCaptureField(0), InLambdaConversionToBlock(false),
- NormalCleanupDest(0), NextCleanupDestIndex(1),
+ LambdaThisCaptureField(0), NormalCleanupDest(0), NextCleanupDestIndex(1),
FirstBlockInfo(0), EHResumeBlock(0), ExceptionSlot(0), EHSelectorSlot(0),
DebugInfo(0), DisableDebugInfo(false), DidCallStackSave(false),
IndirectBranch(0), SwitchInsn(0), CaseRangeBlock(0), UnreachableBlock(0),
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 42c9b7dc9b..7f39868dd9 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -601,7 +601,6 @@ public:
llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields;
FieldDecl *LambdaThisCaptureField;
- bool InLambdaConversionToBlock;
/// \brief A mapping from NRVO variables to the flags used to indicate
/// when the NRVO has been applied to this variable.