1 ; RUN: opt -objc-arc -S < %s | FileCheck %s
3 target datalayout = "e-p:64:64:64"
5 declare i8* @llvm.objc.retain(i8*)
6 declare i8* @llvm.objc.retainAutoreleasedReturnValue(i8*)
7 declare void @llvm.objc.release(i8*)
8 declare i8* @llvm.objc.autorelease(i8*)
9 declare i8* @llvm.objc.autoreleaseReturnValue(i8*)
10 declare i8* @llvm.objc.retainAutoreleaseReturnValue(i8*)
11 declare void @llvm.objc.autoreleasePoolPop(i8*)
12 declare void @llvm.objc.autoreleasePoolPush()
13 declare i8* @llvm.objc.retainBlock(i8*)
15 declare i8* @objc_retainedObject(i8*)
16 declare i8* @objc_unretainedObject(i8*)
17 declare i8* @objc_unretainedPointer(i8*)
19 declare void @use_pointer(i8*)
20 declare void @callee()
21 declare void @callee_fnptr(void ()*)
22 declare void @invokee()
23 declare i8* @returner()
25 ; Test that retain+release elimination is suppressed when the
26 ; retain is an objc_retainAutoreleasedReturnValue, since it's
27 ; better to do the RV optimization.
29 ; CHECK-LABEL: define void @test0(
31 ; CHECK-NEXT: %x = call i8* @returner
32 ; CHECK-NEXT: %0 = tail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %x) [[NUW:#[0-9]+]]
34 ; CHECK-NOT: @llvm.objc.
36 ; CHECK-NEXT: call void @llvm.objc.release(i8* %x)
37 ; CHECK-NEXT: ret void
39 define void @test0(i1 %p) nounwind {
41 %x = call i8* @returner()
42 %0 = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %x)
43 br i1 %p, label %t, label %return
46 call void @use_pointer(i8* %x)
51 call void @llvm.objc.release(i8* %x) nounwind
57 ; CHECK-LABEL: define void @test2(
58 ; CHECK-NOT: @llvm.objc.
60 define void @test2() {
61 call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* null)
62 call i8* @llvm.objc.autoreleaseReturnValue(i8* null)
63 ; call i8* @llvm.objc.retainAutoreleaseReturnValue(i8* null) ; TODO
64 %bitcast = bitcast i32* null to i8*
65 %rb = call i8* @llvm.objc.retainBlock(i8* %bitcast)
66 call void @use_pointer(i8* %rb)
67 %rb2 = call i8* @llvm.objc.retainBlock(i8* undef)
68 call void @use_pointer(i8* %rb2)
72 ; Delete a redundant retainRV,autoreleaseRV when forwaring a call result
73 ; directly to a return value.
75 ; CHECK-LABEL: define i8* @test3(
76 ; CHECK: call i8* @returner()
77 ; CHECK-NEXT: ret i8* %call
80 %call = call i8* @returner()
81 %0 = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %call) nounwind
82 %1 = call i8* @llvm.objc.autoreleaseReturnValue(i8* %0) nounwind
86 ; Delete a redundant retain,autoreleaseRV when forwaring a call result
87 ; directly to a return value.
89 ; CHECK-LABEL: define i8* @test4(
90 ; CHECK: call i8* @returner()
91 ; CHECK-NEXT: ret i8* %call
94 %call = call i8* @returner()
95 %0 = call i8* @llvm.objc.retain(i8* %call) nounwind
96 %1 = call i8* @llvm.objc.autoreleaseReturnValue(i8* %0) nounwind
100 ; Delete a redundant fused retain+autoreleaseRV when forwaring a call result
101 ; directly to a return value.
104 ; HECK: define i8* @test5
105 ; HECK: call i8* @returner()
106 ; HECK-NEXT: ret i8* %call
107 ;define i8* @test5() {
109 ; %call = call i8* @returner()
110 ; %0 = call i8* @llvm.objc.retainAutoreleaseReturnValue(i8* %call) nounwind
114 ; Don't eliminate objc_retainAutoreleasedReturnValue by merging it into
115 ; an objc_autorelease.
116 ; TODO? Merge objc_retainAutoreleasedReturnValue and objc_autorelease into
117 ; objc_retainAutoreleasedReturnValueAutorelease and merge
118 ; objc_retainAutoreleasedReturnValue and objc_autoreleaseReturnValue
119 ; into objc_retainAutoreleasedReturnValueAutoreleaseReturnValue?
120 ; Those entrypoints don't exist yet though.
122 ; CHECK-LABEL: define i8* @test7(
123 ; CHECK: call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %p)
124 ; CHECK: %t = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %p)
125 define i8* @test7() {
126 %p = call i8* @returner()
127 call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %p)
128 %t = call i8* @llvm.objc.autoreleaseReturnValue(i8* %p)
129 call void @use_pointer(i8* %p)
133 ; CHECK-LABEL: define i8* @test7b(
134 ; CHECK: call i8* @llvm.objc.retain(i8* %p)
135 ; CHECK: %t = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %p)
136 define i8* @test7b() {
137 %p = call i8* @returner()
138 call void @use_pointer(i8* %p)
139 call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %p)
140 %t = call i8* @llvm.objc.autoreleaseReturnValue(i8* %p)
144 ; Don't apply the RV optimization to autorelease if there's no retain.
146 ; CHECK: define i8* @test9(i8* %p)
147 ; CHECK: call i8* @llvm.objc.autorelease(i8* %p)
148 define i8* @test9(i8* %p) {
149 call i8* @llvm.objc.autorelease(i8* %p)
153 ; Do not apply the RV optimization.
155 ; CHECK: define i8* @test10(i8* %p)
156 ; CHECK: tail call i8* @llvm.objc.retain(i8* %p) [[NUW]]
157 ; CHECK: call i8* @llvm.objc.autorelease(i8* %p) [[NUW]]
158 ; CHECK-NEXT: ret i8* %p
159 define i8* @test10(i8* %p) {
160 %1 = call i8* @llvm.objc.retain(i8* %p)
161 %2 = call i8* @llvm.objc.autorelease(i8* %p)
165 ; Don't do the autoreleaseRV optimization because @use_pointer
166 ; could undo the retain.
168 ; CHECK: define i8* @test11(i8* %p)
169 ; CHECK: tail call i8* @llvm.objc.retain(i8* %p)
170 ; CHECK-NEXT: call void @use_pointer(i8* %p)
171 ; CHECK: call i8* @llvm.objc.autorelease(i8* %p)
172 ; CHECK-NEXT: ret i8* %p
173 define i8* @test11(i8* %p) {
174 %1 = call i8* @llvm.objc.retain(i8* %p)
175 call void @use_pointer(i8* %p)
176 %2 = call i8* @llvm.objc.autorelease(i8* %p)
180 ; Don't spoil the RV optimization.
182 ; CHECK: define i8* @test12(i8* %p)
183 ; CHECK: tail call i8* @llvm.objc.retain(i8* %p)
184 ; CHECK: call void @use_pointer(i8* %p)
185 ; CHECK: tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %p)
187 define i8* @test12(i8* %p) {
188 %1 = call i8* @llvm.objc.retain(i8* %p)
189 call void @use_pointer(i8* %p)
190 %2 = call i8* @llvm.objc.autoreleaseReturnValue(i8* %p)
194 ; Don't zap the objc_retainAutoreleasedReturnValue.
196 ; CHECK-LABEL: define i8* @test13(
197 ; CHECK: tail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %p)
198 ; CHECK: call i8* @llvm.objc.autorelease(i8* %p)
200 define i8* @test13() {
201 %p = call i8* @returner()
202 %1 = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %p)
204 %2 = call i8* @llvm.objc.autorelease(i8* %p)
208 ; Convert objc_retainAutoreleasedReturnValue to objc_retain if its
209 ; argument is not a return value.
211 ; CHECK-LABEL: define void @test14(
212 ; CHECK-NEXT: tail call i8* @llvm.objc.retain(i8* %p) [[NUW]]
213 ; CHECK-NEXT: ret void
214 define void @test14(i8* %p) {
215 call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %p)
219 ; Don't convert objc_retainAutoreleasedReturnValue to objc_retain if its
220 ; argument is a return value.
222 ; CHECK-LABEL: define void @test15(
223 ; CHECK-NEXT: %y = call i8* @returner()
224 ; CHECK-NEXT: tail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %y) [[NUW]]
225 ; CHECK-NEXT: ret void
226 define void @test15() {
227 %y = call i8* @returner()
228 call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %y)
232 ; Delete autoreleaseRV+retainRV pairs.
234 ; CHECK: define i8* @test19(i8* %p) {
235 ; CHECK-NEXT: ret i8* %p
236 define i8* @test19(i8* %p) {
237 call i8* @llvm.objc.autoreleaseReturnValue(i8* %p)
238 call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %p)
242 ; Delete autoreleaseRV+retainRV pairs when they have equivalent PHIs as inputs
244 ; CHECK: define i8* @test19phi(i8* %p) {
246 ; CHECK-NEXT: br label %test19bb
248 ; CHECK-NEXT: ret i8* %p
249 define i8* @test19phi(i8* %p) {
253 %phi1 = phi i8* [ %p, %entry ]
254 %phi2 = phi i8* [ %p, %entry ]
255 call i8* @llvm.objc.autoreleaseReturnValue(i8* %phi1)
256 call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %phi2)
260 ; Like test19 but with plain autorelease.
262 ; CHECK: define i8* @test20(i8* %p) {
263 ; CHECK-NEXT: call i8* @llvm.objc.autorelease(i8* %p)
264 ; CHECK-NEXT: call i8* @llvm.objc.retain(i8* %p)
265 ; CHECK-NEXT: ret i8* %p
266 define i8* @test20(i8* %p) {
267 call i8* @llvm.objc.autorelease(i8* %p)
268 call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %p)
272 ; Like test19 but with plain retain.
274 ; CHECK: define i8* @test21(i8* %p) {
275 ; CHECK-NEXT: call i8* @llvm.objc.autoreleaseReturnValue(i8* %p)
276 ; CHECK-NEXT: call i8* @llvm.objc.retain(i8* %p)
277 ; CHECK-NEXT: ret i8* %p
278 define i8* @test21(i8* %p) {
279 call i8* @llvm.objc.autoreleaseReturnValue(i8* %p)
280 call i8* @llvm.objc.retain(i8* %p)
284 ; Like test19 but with plain retain and autorelease.
286 ; CHECK: define i8* @test22(i8* %p) {
287 ; CHECK-NEXT: call i8* @llvm.objc.autorelease(i8* %p)
288 ; CHECK-NEXT: call i8* @llvm.objc.retain(i8* %p)
289 ; CHECK-NEXT: ret i8* %p
290 define i8* @test22(i8* %p) {
291 call i8* @llvm.objc.autorelease(i8* %p)
292 call i8* @llvm.objc.retain(i8* %p)
296 ; Convert autoreleaseRV to autorelease.
298 ; CHECK-LABEL: define void @test23(
299 ; CHECK: call i8* @llvm.objc.autorelease(i8* %p) [[NUW]]
300 define void @test23(i8* %p) {
302 call i8* @llvm.objc.autoreleaseReturnValue(i8* %p)
306 ; Don't convert autoreleaseRV to autorelease if the result is returned,
307 ; even through a bitcast.
309 ; CHECK-LABEL: define {}* @test24(
310 ; CHECK: tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %p)
311 define {}* @test24(i8* %p) {
312 %t = call i8* @llvm.objc.autoreleaseReturnValue(i8* %p)
313 %s = bitcast i8* %p to {}*
317 declare i8* @first_test25();
318 declare i8* @second_test25(i8*);
319 declare void @somecall_test25();
321 ; ARC optimizer used to move the last release between the call to second_test25
322 ; and the call to objc_retainAutoreleasedReturnValue, causing %second to be
323 ; released prematurely when %first and %second were pointing to the same object.
325 ; CHECK-LABEL: define void @test25(
326 ; CHECK: %[[CALL1:.*]] = call i8* @second_test25(
327 ; CHECK-NEXT: tail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %[[CALL1]])
329 define void @test25() {
330 %first = call i8* @first_test25()
331 %v0 = call i8* @llvm.objc.retain(i8* %first)
332 call void @somecall_test25()
333 %second = call i8* @second_test25(i8* %first)
334 %call2 = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %second)
335 call void @llvm.objc.release(i8* %second), !clang.imprecise_release !0
336 call void @llvm.objc.release(i8* %first), !clang.imprecise_release !0
340 ; Check that ObjCARCOpt::OptimizeReturns removes the redundant calls even when
341 ; they are not in the same basic block. This code used to cause an assertion
344 ; CHECK-LABEL: define i8* @test26()
345 ; CHECK: call i8* @returner()
347 define i8* @test26() {
349 %v0 = call i8* @returner()
350 %v1 = tail call i8* @llvm.objc.retain(i8* %v0)
353 %v2 = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %v1)
359 declare i32* @func27(i32);
361 ; Check that ObjCARCOpt::OptimizeAutoreleaseRVCall doesn't turn a call to
362 ; @llvm.objc.autoreleaseReturnValue into a call to @llvm.objc.autorelease when a return
363 ; instruction uses a value equivalent to @llvm.objc.autoreleaseReturnValue's operand.
364 ; In the code below, %phival and %retval are considered equivalent.
366 ; CHECK-LABEL: define i32* @test27(
367 ; CHECK: %[[PHIVAL:.*]] = phi i8* [ %{{.*}}, %bb1 ], [ %{{.*}}, %bb2 ]
368 ; CHECK: %[[RETVAL:.*]] = phi i32* [ %{{.*}}, %bb1 ], [ %{{.*}}, %bb2 ]
369 ; CHECK: tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %[[PHIVAL]])
370 ; CHECK: ret i32* %[[RETVAL]]
372 define i32* @test27(i1 %cond) {
374 br i1 %cond, label %bb1, label %bb2
376 %v0 = call i32* @func27(i32 1)
377 %v1 = bitcast i32* %v0 to i8*
380 %v2 = call i32* @func27(i32 2)
381 %v3 = bitcast i32* %v2 to i8*
384 %phival = phi i8* [ %v1, %bb1 ], [ %v3, %bb2 ]
385 %retval = phi i32* [ %v0, %bb1 ], [ %v2, %bb2 ]
386 %v4 = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %phival)
392 ; CHECK: attributes [[NUW]] = { nounwind }