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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits