diff --git a/clang/test/CodeGenObjC/arc.m b/clang/test/CodeGenObjC/arc.m --- a/clang/test/CodeGenObjC/arc.m +++ b/clang/test/CodeGenObjC/arc.m @@ -7,30 +7,30 @@ // RUN: %clang_cc1 -fobjc-runtime=macosx-10.7.0 -triple x86_64-apple-darwin11 -Wno-objc-root-class -Wno-incompatible-pointer-types -Wno-arc-unsafe-retained-assign -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=ARC-NATIVE %s // ARC-ALIEN: declare extern_weak void @llvm.objc.storeStrong(ptr, ptr) -// ARC-ALIEN: declare extern_weak ptr @llvm.objc.retain(ptr) -// ARC-ALIEN: declare extern_weak ptr @llvm.objc.autoreleaseReturnValue(ptr) +// ARC-ALIEN: declare extern_weak ptr @llvm.objc.retain(ptr returned) +// ARC-ALIEN: declare extern_weak ptr @llvm.objc.autoreleaseReturnValue(ptr returned) // ARC-ALIEN: declare ptr @objc_msgSend(ptr, ptr, ...) [[NLB:#[0-9]+]] // ARC-ALIEN: declare extern_weak void @llvm.objc.release(ptr) -// ARC-ALIEN: declare extern_weak ptr @llvm.objc.retainAutoreleasedReturnValue(ptr) +// ARC-ALIEN: declare extern_weak ptr @llvm.objc.retainAutoreleasedReturnValue(ptr returned) // ARC-ALIEN: declare extern_weak ptr @llvm.objc.initWeak(ptr, ptr) // ARC-ALIEN: declare extern_weak ptr @llvm.objc.storeWeak(ptr, ptr) // ARC-ALIEN: declare extern_weak ptr @llvm.objc.loadWeakRetained(ptr) // ARC-ALIEN: declare extern_weak void @llvm.objc.destroyWeak(ptr) -// ARC-ALIEN: declare extern_weak ptr @llvm.objc.autorelease(ptr) -// ARC-ALIEN: declare extern_weak ptr @llvm.objc.retainAutorelease(ptr) +// ARC-ALIEN: declare extern_weak ptr @llvm.objc.autorelease(ptr returned) +// ARC-ALIEN: declare extern_weak ptr @llvm.objc.retainAutorelease(ptr returned) // ARC-NATIVE: declare void @llvm.objc.storeStrong(ptr, ptr) -// ARC-NATIVE: declare ptr @llvm.objc.retain(ptr) -// ARC-NATIVE: declare ptr @llvm.objc.autoreleaseReturnValue(ptr) +// ARC-NATIVE: declare ptr @llvm.objc.retain(ptr returned) +// ARC-NATIVE: declare ptr @llvm.objc.autoreleaseReturnValue(ptr returned) // ARC-NATIVE: declare ptr @objc_msgSend(ptr, ptr, ...) [[NLB:#[0-9]+]] // ARC-NATIVE: declare void @llvm.objc.release(ptr) -// ARC-NATIVE: declare ptr @llvm.objc.retainAutoreleasedReturnValue(ptr) +// ARC-NATIVE: declare ptr @llvm.objc.retainAutoreleasedReturnValue(ptr returned) // ARC-NATIVE: declare ptr @llvm.objc.initWeak(ptr, ptr) // ARC-NATIVE: declare ptr @llvm.objc.storeWeak(ptr, ptr) // ARC-NATIVE: declare ptr @llvm.objc.loadWeakRetained(ptr) // ARC-NATIVE: declare void @llvm.objc.destroyWeak(ptr) -// ARC-NATIVE: declare ptr @llvm.objc.autorelease(ptr) -// ARC-NATIVE: declare ptr @llvm.objc.retainAutorelease(ptr) +// ARC-NATIVE: declare ptr @llvm.objc.autorelease(ptr returned) +// ARC-NATIVE: declare ptr @llvm.objc.retainAutorelease(ptr returned) // CHECK-LABEL: define{{.*}} void @test0 void test0(id x) { diff --git a/clang/test/CodeGenObjC/convert-messages-to-runtime-calls.m b/clang/test/CodeGenObjC/convert-messages-to-runtime-calls.m --- a/clang/test/CodeGenObjC/convert-messages-to-runtime-calls.m +++ b/clang/test/CodeGenObjC/convert-messages-to-runtime-calls.m @@ -28,6 +28,11 @@ // MSGS: {{call.*@objc_msgSend}} // CALLS: {{call.*@objc_alloc}} // CALLS: {{call.*@objc_allocWithZone}} + + // Note that calls to the intrinsics are not allowed for + // retain/release/autorelease they're marked `thisreturn`, which isn't + // guaranteed to be true for classes that define their own `-retain`, for + // example. Be sure to keep these as normal function calls: // CALLS: {{call.*@objc_retain}} // CALLS: {{call.*@objc_release}} // CALLS: {{tail call.*@objc_autorelease}} diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td --- a/llvm/include/llvm/IR/Intrinsics.td +++ b/llvm/include/llvm/IR/Intrinsics.td @@ -720,11 +720,13 @@ // eliminate retain and releases where possible. def int_objc_autorelease : Intrinsic<[llvm_ptr_ty], - [llvm_ptr_ty]>; + [llvm_ptr_ty], + [Returned>]>; def int_objc_autoreleasePoolPop : Intrinsic<[], [llvm_ptr_ty]>; def int_objc_autoreleasePoolPush : Intrinsic<[llvm_ptr_ty], []>; def int_objc_autoreleaseReturnValue : Intrinsic<[llvm_ptr_ty], - [llvm_ptr_ty]>; + [llvm_ptr_ty], + [Returned>]>; def int_objc_copyWeak : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty]>; @@ -741,13 +743,17 @@ llvm_ptr_ty]>; def int_objc_release : Intrinsic<[], [llvm_ptr_ty]>; def int_objc_retain : Intrinsic<[llvm_ptr_ty], - [llvm_ptr_ty]>; + [llvm_ptr_ty], + [Returned>]>; def int_objc_retainAutorelease : Intrinsic<[llvm_ptr_ty], - [llvm_ptr_ty]>; + [llvm_ptr_ty], + [Returned>]>; def int_objc_retainAutoreleaseReturnValue : Intrinsic<[llvm_ptr_ty], - [llvm_ptr_ty]>; + [llvm_ptr_ty], + [Returned>]>; def int_objc_retainAutoreleasedReturnValue : Intrinsic<[llvm_ptr_ty], - [llvm_ptr_ty]>; + [llvm_ptr_ty], + [Returned>]>; def int_objc_retainBlock : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty]>; def int_objc_storeStrong : Intrinsic<[], @@ -762,7 +768,8 @@ [llvm_vararg_ty], [IntrInaccessibleMemOnly]>; def int_objc_unsafeClaimAutoreleasedReturnValue : Intrinsic<[llvm_ptr_ty], - [llvm_ptr_ty]>; + [llvm_ptr_ty], + [Returned>]>; def int_objc_retainedObject : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty]>; def int_objc_unretainedObject : Intrinsic<[llvm_ptr_ty], @@ -770,7 +777,8 @@ def int_objc_unretainedPointer : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty]>; def int_objc_retain_autorelease : Intrinsic<[llvm_ptr_ty], - [llvm_ptr_ty]>; + [llvm_ptr_ty], + [Returned>]>; def int_objc_sync_enter : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty]>; def int_objc_sync_exit : Intrinsic<[llvm_i32_ty], diff --git a/llvm/include/llvm/IR/Value.h b/llvm/include/llvm/IR/Value.h --- a/llvm/include/llvm/IR/Value.h +++ b/llvm/include/llvm/IR/Value.h @@ -656,7 +656,7 @@ } /// Strip off pointer casts, all-zero GEPs, single-argument phi nodes and - /// invariant group info. + /// invariant group info. Looks through returned arg functions. /// /// Returns the original uncasted value. If this is called on a non-pointer /// value, it returns 'this'. This function should be used only in diff --git a/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp b/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp --- a/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp +++ b/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp @@ -162,6 +162,16 @@ CallInst::TailCallKind TCK = CI->getTailCallKind(); NewCI->setTailCallKind(std::max(TCK, OverridingTCK)); + // Transfer the 'returned' attribute from the intrinsic to the call site. + // By applying this only to intrinsic call sites, we avoid applying it to + // non-ARC explicit calls to things like objc_retain which have not been + // auto-upgraded to use the intrinsics. + unsigned Index; + if (F.getAttributes().hasAttrSomewhere(Attribute::Returned, &Index) && + Index) + NewCI->addParamAttr(Index - AttributeList::FirstArgIndex, + Attribute::Returned); + if (!CI->use_empty()) CI->replaceAllUsesWith(NewCI); CI->eraseFromParent(); diff --git a/llvm/lib/IR/Value.cpp b/llvm/lib/IR/Value.cpp --- a/llvm/lib/IR/Value.cpp +++ b/llvm/lib/IR/Value.cpp @@ -662,7 +662,8 @@ V = cast(V)->getIncomingValue(0); } else { if (const auto *Call = dyn_cast(V)) { - if (const Value *RV = Call->getReturnedArgOperand()) { + if (const Value *RV = Call->getReturnedArgOperand(); + RV && StripKind == PSK_ForAliasAnalysis) { V = RV; continue; }