jroelofs updated this revision to Diff 364215. jroelofs added a comment. Herald added a project: clang. Herald added a subscriber: cfe-commits.
Add a note/check to the `[x retain] => objc_retain(x)` test explaining why it shouldn't be lowered as an intrinsic call in the future. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D105671/new/ https://reviews.llvm.org/D105671 Files: clang/test/CodeGenObjC/convert-messages-to-runtime-calls.m llvm/include/llvm/IR/Intrinsics.td llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp llvm/test/Transforms/PreISelIntrinsicLowering/objc-arc.ll
Index: llvm/test/Transforms/PreISelIntrinsicLowering/objc-arc.ll =================================================================== --- llvm/test/Transforms/PreISelIntrinsicLowering/objc-arc.ll +++ llvm/test/Transforms/PreISelIntrinsicLowering/objc-arc.ll @@ -6,7 +6,7 @@ define i8* @test_objc_autorelease(i8* %arg0) { ; CHECK-LABEL: test_objc_autorelease ; CHECK-NEXT: entry -; CHECK-NEXT: %0 = notail call i8* @objc_autorelease(i8* %arg0) +; CHECK-NEXT: %0 = notail call i8* @objc_autorelease(i8* returned %arg0) ; CHECK-NEXT: ret i8* %0 entry: %0 = call i8* @llvm.objc.autorelease(i8* %arg0) @@ -113,20 +113,31 @@ ret void } +define i8* @test_objc_retain_intrinsic(i8* %arg0) { +; CHECK-LABEL: test_objc_retain_intrinsic +; CHECK-NEXT: entry +; CHECK-NEXT: %0 = tail call i8* @objc_retain(i8* returned %arg0) +; CHECK-NEXT: ret i8* %0 +entry: + %0 = call i8* @llvm.objc.retain(i8* %arg0) + ret i8* %0 +} + +; Explicit objc_retain calls should not be upgraded to be "thisreturn". define i8* @test_objc_retain(i8* %arg0) { ; CHECK-LABEL: test_objc_retain ; CHECK-NEXT: entry -; CHECK-NEXT: %0 = tail call i8* @objc_retain(i8* %arg0) +; CHECK-NEXT: %0 = call i8* @objc_retain(i8* %arg0) ; CHECK-NEXT: ret i8* %0 entry: - %0 = call i8* @llvm.objc.retain(i8* %arg0) + %0 = call i8* @objc_retain(i8* %arg0) ret i8* %0 } define i8* @test_objc_retainAutorelease(i8* %arg0) { ; CHECK-LABEL: test_objc_retainAutorelease ; CHECK-NEXT: entry -; CHECK-NEXT: %0 = call i8* @objc_retainAutorelease(i8* %arg0) +; CHECK-NEXT: %0 = call i8* @objc_retainAutorelease(i8* returned %arg0) ; CHECK-NEXT: ret i8* %0 entry: %0 = call i8* @llvm.objc.retainAutorelease(i8* %arg0) @@ -136,7 +147,7 @@ define i8* @test_objc_retainAutoreleaseReturnValue(i8* %arg0) { ; CHECK-LABEL: test_objc_retainAutoreleaseReturnValue ; CHECK-NEXT: entry -; CHECK-NEXT: %0 = tail call i8* @objc_retainAutoreleaseReturnValue(i8* %arg0) +; CHECK-NEXT: %0 = tail call i8* @objc_retainAutoreleaseReturnValue(i8* returned %arg0) ; CHECK-NEXT: ret i8* %0 entry: %0 = tail call i8* @llvm.objc.retainAutoreleaseReturnValue(i8* %arg0) @@ -146,7 +157,7 @@ define i8* @test_objc_retainAutoreleasedReturnValue(i8* %arg0) { ; CHECK-LABEL: test_objc_retainAutoreleasedReturnValue ; CHECK-NEXT: entry -; CHECK-NEXT: %0 = tail call i8* @objc_retainAutoreleasedReturnValue(i8* %arg0) +; CHECK-NEXT: %0 = tail call i8* @objc_retainAutoreleasedReturnValue(i8* returned %arg0) ; CHECK-NEXT: ret i8* %0 entry: %0 = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %arg0) @@ -226,7 +237,7 @@ define i8* @test_objc_retain_autorelease(i8* %arg0) { ; CHECK-LABEL: test_objc_retain_autorelease ; CHECK-NEXT: entry -; CHECK-NEXT: %0 = call i8* @objc_retain_autorelease(i8* %arg0) +; CHECK-NEXT: %0 = call i8* @objc_retain_autorelease(i8* returned %arg0) ; CHECK-NEXT: ret i8* %0 entry: %0 = call i8* @llvm.objc.retain.autorelease(i8* %arg0) @@ -265,6 +276,7 @@ declare void @llvm.objc.moveWeak(i8**, i8**) declare void @llvm.objc.release(i8*) declare i8* @llvm.objc.retain(i8*) +declare i8* @objc_retain(i8*) declare i8* @llvm.objc.retainAutorelease(i8*) declare i8* @llvm.objc.retainAutoreleaseReturnValue(i8*) declare i8* @llvm.objc.retainAutoreleasedReturnValue(i8*) @@ -281,6 +293,7 @@ attributes #0 = { nounwind } +; CHECK: declare i8* @objc_retain(i8*) [[NLB:#[0-9]+]] ; CHECK: declare i8* @objc_autorelease(i8*) ; CHECK: declare void @objc_autoreleasePoolPop(i8*) ; CHECK: declare i8* @objc_autoreleasePoolPush() @@ -291,8 +304,7 @@ ; CHECK: declare i8* @objc_loadWeak(i8**) ; 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 void @objc_release(i8*) [[NLB]] ; CHECK: declare i8* @objc_retainAutorelease(i8*) ; CHECK: declare i8* @objc_retainAutoreleaseReturnValue(i8*) ; CHECK: declare i8* @objc_retainAutoreleasedReturnValue(i8*) Index: llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp =================================================================== --- llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp +++ llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp @@ -110,6 +110,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(); Index: llvm/include/llvm/IR/Intrinsics.td =================================================================== --- llvm/include/llvm/IR/Intrinsics.td +++ 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<ArgIndex<0>>]>; 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<ArgIndex<0>>]>; def int_objc_retainAutorelease : Intrinsic<[llvm_ptr_ty], - [llvm_ptr_ty]>; + [llvm_ptr_ty], + [Returned<ArgIndex<0>>]>; def int_objc_retainAutoreleaseReturnValue : Intrinsic<[llvm_ptr_ty], - [llvm_ptr_ty]>; + [llvm_ptr_ty], + [Returned<ArgIndex<0>>]>; def int_objc_retainAutoreleasedReturnValue : Intrinsic<[llvm_ptr_ty], - [llvm_ptr_ty]>; + [llvm_ptr_ty], + [Returned<ArgIndex<0>>]>; 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<ArgIndex<0>>]>; def int_objc_sync_enter : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty]>; def int_objc_sync_exit : Intrinsic<[llvm_i32_ty], Index: clang/test/CodeGenObjC/convert-messages-to-runtime-calls.m =================================================================== --- clang/test/CodeGenObjC/convert-messages-to-runtime-calls.m +++ clang/test/CodeGenObjC/convert-messages-to-runtime-calls.m @@ -26,6 +26,12 @@ // MSGS: {{call.*@objc_msgSend}} // MSGS: {{call.*@objc_msgSend}} // MSGS: {{call.*@objc_msgSend}} + // We can't emit calls to the intrinsics are not allowed as they're marked + // `thisreturn`, which isn't guaranteed to be true for classes that define + // their own `-retain`, for example. + // CALLS-NOT: {{call.*@llvm.objc.retain}} + // CALLS-NOT: {{call.*@llvm.objc.release}} + // CALLS-NOT: {{tail call.*@llvm.objc.autorelease}} // CALLS: {{call.*@objc_alloc}} // CALLS: {{call.*@objc_allocWithZone}} // CALLS: {{call.*@objc_retain}}
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits