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 @@ -412,7 +412,8 @@ // 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], @@ -433,13 +434,17 @@ llvm_ptrptr_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<[], @@ -462,7 +467,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/lib/CodeGen/PreISelIntrinsicLowering.cpp b/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp --- a/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp +++ b/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp @@ -86,6 +86,13 @@ // performance. Fn->addFnAttr(Attribute::NonLazyBind); } + + // Transfer the 'returned' attribute from the intrinsic to the callee. + unsigned Index; + if (F.getAttributes().hasAttrSomewhere(Attribute::Returned, &Index) && + Index) + Fn->addParamAttr(Index - AttributeList::FirstArgIndex, + Attribute::Returned); } CallInst::TailCallKind OverridingTCK = getOverridingTailCallKind(F); diff --git a/llvm/test/Transforms/PreISelIntrinsicLowering/objc-arc.ll b/llvm/test/Transforms/PreISelIntrinsicLowering/objc-arc.ll --- a/llvm/test/Transforms/PreISelIntrinsicLowering/objc-arc.ll +++ b/llvm/test/Transforms/PreISelIntrinsicLowering/objc-arc.ll @@ -253,7 +253,7 @@ ret i32 %0 } -declare i8* @llvm.objc.autorelease(i8*) +declare i8* @llvm.objc.autorelease(i8* returned) declare void @llvm.objc.autoreleasePoolPop(i8*) declare i8* @llvm.objc.autoreleasePoolPush() declare i8* @llvm.objc.autoreleaseReturnValue(i8*) @@ -264,10 +264,10 @@ declare i8* @llvm.objc.loadWeakRetained(i8**) declare void @llvm.objc.moveWeak(i8**, i8**) declare void @llvm.objc.release(i8*) -declare i8* @llvm.objc.retain(i8*) -declare i8* @llvm.objc.retainAutorelease(i8*) -declare i8* @llvm.objc.retainAutoreleaseReturnValue(i8*) -declare i8* @llvm.objc.retainAutoreleasedReturnValue(i8*) +declare i8* @llvm.objc.retain(i8* returned) +declare i8* @llvm.objc.retainAutorelease(i8* returned) +declare i8* @llvm.objc.retainAutoreleaseReturnValue(i8* returned) +declare i8* @llvm.objc.retainAutoreleasedReturnValue(i8* returned) declare i8* @llvm.objc.retainBlock(i8*) declare void @llvm.objc.storeStrong(i8**, i8*) declare i8* @llvm.objc.storeWeak(i8**, i8*) @@ -275,13 +275,13 @@ declare i8* @llvm.objc.retainedObject(i8*) declare i8* @llvm.objc.unretainedObject(i8*) declare i8* @llvm.objc.unretainedPointer(i8*) -declare i8* @llvm.objc.retain.autorelease(i8*) +declare i8* @llvm.objc.retain.autorelease(i8* returned) declare i32 @llvm.objc.sync.enter(i8*) declare i32 @llvm.objc.sync.exit(i8*) attributes #0 = { nounwind } -; CHECK: declare i8* @objc_autorelease(i8*) +; CHECK: declare i8* @objc_autorelease(i8* returned) ; CHECK: declare void @objc_autoreleasePoolPop(i8*) ; CHECK: declare i8* @objc_autoreleasePoolPush() ; CHECK: declare i8* @objc_autoreleaseReturnValue(i8*) @@ -292,10 +292,10 @@ ; CHECK: declare i8* @objc_loadWeakRetained(i8**) ; CHECK: declare void @objc_moveWeak(i8**, i8**) ; CHECK: declare void @objc_release(i8*) [[NLB:#[0-9]+]] -; CHECK: declare i8* @objc_retain(i8*) [[NLB]] -; CHECK: declare i8* @objc_retainAutorelease(i8*) -; CHECK: declare i8* @objc_retainAutoreleaseReturnValue(i8*) -; CHECK: declare i8* @objc_retainAutoreleasedReturnValue(i8*) +; CHECK: declare i8* @objc_retain(i8* returned) [[NLB]] +; CHECK: declare i8* @objc_retainAutorelease(i8* returned) +; CHECK: declare i8* @objc_retainAutoreleaseReturnValue(i8* returned) +; CHECK: declare i8* @objc_retainAutoreleasedReturnValue(i8* returned) ; CHECK: declare i8* @objc_retainBlock(i8*) ; CHECK: declare void @objc_storeStrong(i8**, i8*) ; CHECK: declare i8* @objc_storeWeak(i8**, i8*) @@ -303,7 +303,7 @@ ; CHECK: declare i8* @objc_retainedObject(i8*) ; CHECK: declare i8* @objc_unretainedObject(i8*) ; CHECK: declare i8* @objc_unretainedPointer(i8*) -; CHECK: declare i8* @objc_retain_autorelease(i8*) +; CHECK: declare i8* @objc_retain_autorelease(i8* returned) ; CHECK: declare i32 @objc_sync_enter(i8*) ; CHECK: declare i32 @objc_sync_exit(i8*)