summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2011-10-04 06:23:45 +0000
committerJohn McCall <rjmccall@apple.com>2011-10-04 06:23:45 +0000
commitff61303bd04faa380d2058f2c5520fa125330192 (patch)
tree080b4d04d5e3bcdd5a9fffe5ba186df7d89d85f3 /clang/lib
parent05de0298d2c3da8d42c2de6a95a765523e3baed0 (diff)
downloadbcm5719-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.cpp6
-rw-r--r--clang/lib/CodeGen/CGObjC.cpp56
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h3
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);
OpenPOWER on IntegriCloud