1 ; RUN: opt < %s -passes=inline -S | FileCheck %s
3 @g0 = global ptr null, align 8
6 define ptr @callee0_autoreleaseRV() {
7 %call = call ptr @foo0() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
8 %1 = tail call ptr @llvm.objc.autoreleaseReturnValue(ptr %call)
12 ; CHECK-LABEL: define void @test0_autoreleaseRV(
13 ; CHECK: call ptr @foo0() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
15 define void @test0_autoreleaseRV() {
16 %call = call ptr @callee0_autoreleaseRV() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
20 ; CHECK-LABEL: define void @test0_claimRV_autoreleaseRV(
21 ; CHECK: %[[CALL:.*]] = call ptr @foo0() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
22 ; CHECK: call void @llvm.objc.release(ptr %[[CALL]])
23 ; CHECK-NEXT: ret void
25 define void @test0_claimRV_autoreleaseRV() {
26 %call = call ptr @callee0_autoreleaseRV() [ "clang.arc.attachedcall"(ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
30 ; CHECK-LABEL: define void @test1_autoreleaseRV(
31 ; CHECK: invoke ptr @foo0() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
33 define void @test1_autoreleaseRV() personality ptr @__gxx_personality_v0 {
35 %call = invoke ptr @callee0_autoreleaseRV() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
36 to label %invoke.cont unwind label %lpad
42 %0 = landingpad { ptr, i32 }
44 resume { ptr, i32 } undef
47 ; CHECK-LABEL: define void @test1_claimRV_autoreleaseRV(
48 ; CHECK: %[[INVOKE:.*]] = invoke ptr @foo0() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
49 ; CHECK: call void @llvm.objc.release(ptr %[[INVOKE]])
52 define void @test1_claimRV_autoreleaseRV() personality ptr @__gxx_personality_v0 {
54 %call = invoke ptr @callee0_autoreleaseRV() [ "clang.arc.attachedcall"(ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
55 to label %invoke.cont unwind label %lpad
61 %0 = landingpad { ptr, i32 }
63 resume { ptr, i32 } undef
66 define ptr @callee1_no_autoreleaseRV() {
67 %call = call ptr @foo0()
71 ; CHECK-LABEL: define void @test2_no_autoreleaseRV(
72 ; CHECK: call ptr @foo0() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
73 ; CHECK-NEXT: ret void
75 define void @test2_no_autoreleaseRV() {
76 %call = call ptr @callee1_no_autoreleaseRV() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
80 ; CHECK-LABEL: define void @test2_claimRV_no_autoreleaseRV(
81 ; CHECK: call ptr @foo0() [ "clang.arc.attachedcall"(ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
82 ; CHECK-NEXT: ret void
84 define void @test2_claimRV_no_autoreleaseRV() {
85 %call = call ptr @callee1_no_autoreleaseRV() [ "clang.arc.attachedcall"(ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
89 ; CHECK-LABEL: define void @test3_no_autoreleaseRV(
90 ; CHECK: invoke ptr @foo0() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
92 define void @test3_no_autoreleaseRV() personality ptr @__gxx_personality_v0 {
94 %call = invoke ptr @callee1_no_autoreleaseRV() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
95 to label %invoke.cont unwind label %lpad
101 %0 = landingpad { ptr, i32 }
103 resume { ptr, i32 } undef
106 define ptr @callee2_nocall() {
107 %1 = load ptr, ptr @g0, align 8
111 ; Check that a call to @llvm.objc.retain is inserted if there is no matching
112 ; autoreleaseRV call or a call.
114 ; CHECK-LABEL: define void @test4_nocall(
115 ; CHECK: %[[V0:.*]] = load ptr, ptr @g0,
116 ; CHECK-NEXT: call ptr @llvm.objc.retain(ptr %[[V0]])
117 ; CHECK-NEXT: ret void
119 define void @test4_nocall() {
120 %call = call ptr @callee2_nocall() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
124 ; CHECK-LABEL: define void @test4_claimRV_nocall(
125 ; CHECK: %[[V0:.*]] = load ptr, ptr @g0,
126 ; CHECK-NEXT: ret void
128 define void @test4_claimRV_nocall() {
129 %call = call ptr @callee2_nocall() [ "clang.arc.attachedcall"(ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
133 ; Check that a call to @llvm.objc.retain is inserted if call to @foo already has
134 ; the attribute. I'm not sure this will happen in practice.
136 define ptr @callee3_marker() {
137 %1 = call ptr @foo0() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
141 ; CHECK-LABEL: define void @test5(
142 ; CHECK: %[[V0:.*]] = call ptr @foo0() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
143 ; CHECK-NEXT: call ptr @llvm.objc.retain(ptr %[[V0]])
144 ; CHECK-NEXT: ret void
146 define void @test5() {
147 %call = call ptr @callee3_marker() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
151 ; Don't pair up an autoreleaseRV in the callee and an retainRV in the caller
152 ; if there is an instruction between the ret instruction and the call to
153 ; autoreleaseRV that isn't a cast instruction.
155 define ptr @callee0_autoreleaseRV2() {
156 %call = call ptr @foo0() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
157 %1 = tail call ptr @llvm.objc.autoreleaseReturnValue(ptr %call)
158 store ptr null, ptr @g0
162 ; CHECK-LABEL: define void @test6(
163 ; CHECK: %[[V0:.*]] = call ptr @foo0() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
164 ; CHECK: call ptr @llvm.objc.autoreleaseReturnValue(ptr %[[V0]])
165 ; CHECK: store ptr null, ptr @g0, align 8
166 ; CHECK: call ptr @llvm.objc.retain(ptr %[[V0]])
167 ; CHECK-NEXT: ret void
169 define void @test6() {
170 %call = call ptr @callee0_autoreleaseRV2() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
174 declare ptr @llvm.objc.retainAutoreleasedReturnValue(ptr)
175 declare ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue(ptr)
176 declare ptr @llvm.objc.autoreleaseReturnValue(ptr)
177 declare i32 @__gxx_personality_v0(...)