diff options
author | John McCall <rjmccall@apple.com> | 2011-10-04 06:23:45 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2011-10-04 06:23:45 +0000 |
commit | ff61303bd04faa380d2058f2c5520fa125330192 (patch) | |
tree | 080b4d04d5e3bcdd5a9fffe5ba186df7d89d85f3 /clang/lib | |
parent | 05de0298d2c3da8d42c2de6a95a765523e3baed0 (diff) | |
download | bcm5719-llvm-ff61303bd04faa380d2058f2c5520fa125330192.tar.gz bcm5719-llvm-ff61303bd04faa380d2058f2c5520fa125330192.zip |
Mark calls to objc_retainBlock that don't result from casts
to id so that we can still optimize them appropriately.
llvm-svn: 141064
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/CodeGen/CGExprScalar.cpp | 6 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGObjC.cpp | 56 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 3 |
3 files changed, 52 insertions, 13 deletions
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 0954e20050d..9d956201484 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -1128,10 +1128,8 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { value = CGF.EmitARCRetainAutoreleasedReturnValue(value); return CGF.EmitObjCConsumeObject(E->getType(), value); } - case CK_ARCExtendBlockObject: { - llvm::Value *value = CGF.EmitARCRetainScalarExpr(E); - return CGF.EmitObjCConsumeObject(E->getType(), value); - } + case CK_ARCExtendBlockObject: + return CGF.EmitARCExtendBlockObject(E); case CK_FloatingRealToComplex: case CK_FloatingComplexCast: diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp index 72e0c305240..344c1ee1804 100644 --- a/clang/lib/CodeGen/CGObjC.cpp +++ b/clang/lib/CodeGen/CGObjC.cpp @@ -1658,7 +1658,7 @@ static void emitARCCopyOperation(CodeGenFunction &CGF, /// call i8* @objc_retainBlock(i8* %value) llvm::Value *CodeGenFunction::EmitARCRetain(QualType type, llvm::Value *value) { if (type->isBlockPointerType()) - return EmitARCRetainBlock(value); + return EmitARCRetainBlock(value, /*mandatory*/ false); else return EmitARCRetainNonBlock(value); } @@ -1673,10 +1673,32 @@ llvm::Value *CodeGenFunction::EmitARCRetainNonBlock(llvm::Value *value) { /// Retain the given block, with _Block_copy semantics. /// call i8* @objc_retainBlock(i8* %value) -llvm::Value *CodeGenFunction::EmitARCRetainBlock(llvm::Value *value) { - return emitARCValueOperation(*this, value, - CGM.getARCEntrypoints().objc_retainBlock, - "objc_retainBlock"); +/// +/// \param mandatory - If false, emit the call with metadata +/// indicating that it's okay for the optimizer to eliminate this call +/// if it can prove that the block never escapes except down the stack. +llvm::Value *CodeGenFunction::EmitARCRetainBlock(llvm::Value *value, + bool mandatory) { + llvm::Value *result + = emitARCValueOperation(*this, value, + CGM.getARCEntrypoints().objc_retainBlock, + "objc_retainBlock"); + + // If the copy isn't mandatory, add !clang.arc.copy_on_escape to + // tell the optimizer that it doesn't need to do this copy if the + // block doesn't escape, where being passed as an argument doesn't + // count as escaping. + if (!mandatory && isa<llvm::Instruction>(result)) { + llvm::CallInst *call + = cast<llvm::CallInst>(result->stripPointerCasts()); + assert(call->getCalledValue() == CGM.getARCEntrypoints().objc_retainBlock); + + SmallVector<llvm::Value*,1> args; + call->setMetadata("clang.arc.copy_on_escape", + llvm::MDNode::get(Builder.getContext(), args)); + } + + return result; } /// Retain the given object which is the result of a function call. @@ -1857,7 +1879,7 @@ llvm::Value *CodeGenFunction::EmitARCRetainAutorelease(QualType type, llvm::Type *origType = value->getType(); value = Builder.CreateBitCast(value, Int8PtrTy); - value = EmitARCRetainBlock(value); + value = EmitARCRetainBlock(value, /*mandatory*/ true); value = EmitARCAutorelease(value); return Builder.CreateBitCast(value, origType); } @@ -2300,7 +2322,7 @@ tryEmitARCRetainScalarExpr(CodeGenFunction &CGF, const Expr *e) { } // Retain the object as a block, then cast down. - result = CGF.EmitARCRetainBlock(result); + result = CGF.EmitARCRetainBlock(result, /*mandatory*/ true); if (resultType) result = CGF.Builder.CreateBitCast(result, resultType); return TryEmitResult(result, true); } @@ -2386,6 +2408,24 @@ CodeGenFunction::EmitARCRetainAutoreleaseScalarExpr(const Expr *e) { return value; } +llvm::Value *CodeGenFunction::EmitARCExtendBlockObject(const Expr *e) { + llvm::Value *result; + bool doRetain; + + if (shouldEmitSeparateBlockRetain(e)) { + result = EmitScalarExpr(e); + doRetain = true; + } else { + TryEmitResult subresult = tryEmitARCRetainScalarExpr(*this, e); + result = subresult.getPointer(); + doRetain = !subresult.getInt(); + } + + if (doRetain) + result = EmitARCRetainBlock(result, /*mandatory*/ true); + return EmitObjCConsumeObject(e->getType(), result); +} + llvm::Value *CodeGenFunction::EmitObjCThrowOperand(const Expr *expr) { // In ARC, retain and autorelease the expression. if (getLangOptions().ObjCAutoRefCount) { @@ -2423,7 +2463,7 @@ CodeGenFunction::EmitARCStoreStrong(const BinaryOperator *e, // type, then we need to emit the block-retain immediately in case // it invalidates the l-value. if (!hasImmediateRetain && e->getType()->isBlockPointerType()) { - value = EmitARCRetainBlock(value); + value = EmitARCRetainBlock(value, /*mandatory*/ false); hasImmediateRetain = true; } diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 0f120923d61..9a18d3367b6 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -2129,7 +2129,7 @@ public: bool ignored); llvm::Value *EmitARCRetain(QualType type, llvm::Value *value); llvm::Value *EmitARCRetainNonBlock(llvm::Value *value); - llvm::Value *EmitARCRetainBlock(llvm::Value *value); + llvm::Value *EmitARCRetainBlock(llvm::Value *value, bool mandatory); void EmitARCRelease(llvm::Value *value, bool precise); llvm::Value *EmitARCAutorelease(llvm::Value *value); llvm::Value *EmitARCAutoreleaseReturnValue(llvm::Value *value); @@ -2147,6 +2147,7 @@ public: llvm::Value *EmitObjCConsumeObject(QualType T, llvm::Value *Ptr); llvm::Value *EmitObjCExtendObjectLifetime(QualType T, llvm::Value *Ptr); + llvm::Value *EmitARCExtendBlockObject(const Expr *expr); llvm::Value *EmitARCRetainScalarExpr(const Expr *expr); llvm::Value *EmitARCRetainAutoreleaseScalarExpr(const Expr *expr); |