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*)
14 declare void @llvm.objc.clang.arc.noop.use(...)
16 declare i8* @objc_retainedObject(i8*)
17 declare i8* @objc_unretainedObject(i8*)
18 declare i8* @objc_unretainedPointer(i8*)
20 declare void @use_pointer(i8*)
21 declare void @callee()
22 declare void @callee_fnptr(void ()*)
23 declare void @invokee()
24 declare i8* @returner()
25 declare i8* @returner1(i8*)
26 declare i32 @__gxx_personality_v0(...)
28 ; Test that retain+release elimination is suppressed when the
29 ; retain is an objc_retainAutoreleasedReturnValue, since it's
30 ; better to do the RV optimization.
32 ; CHECK-LABEL: define void @test0(
34 ; CHECK-NEXT: %x = call i8* @returner
35 ; CHECK-NEXT: %0 = tail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %x) [[NUW:#[0-9]+]]
37 ; CHECK-NOT: @llvm.objc.
39 ; CHECK-NEXT: call void @llvm.objc.release(i8* %x)
40 ; CHECK-NEXT: ret void
42 define void @test0(i1 %p) nounwind {
44 %x = call i8* @returner()
45 %0 = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %x)
46 br i1 %p, label %t, label %return
49 call void @use_pointer(i8* %x)
54 call void @llvm.objc.release(i8* %x) nounwind
60 ; CHECK-LABEL: define void @test2(
61 ; CHECK-NOT: @llvm.objc.
63 define void @test2() {
64 call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* null)
65 call i8* @llvm.objc.autoreleaseReturnValue(i8* null)
66 ; call i8* @llvm.objc.retainAutoreleaseReturnValue(i8* null) ; TODO
67 %bitcast = bitcast i32* null to i8*
68 %rb = call i8* @llvm.objc.retainBlock(i8* %bitcast)
69 call void @use_pointer(i8* %rb)
70 %rb2 = call i8* @llvm.objc.retainBlock(i8* undef)
71 call void @use_pointer(i8* %rb2)
75 ; Delete a redundant retainRV,autoreleaseRV when forwaring a call result
76 ; directly to a return value.
78 ; CHECK-LABEL: define i8* @test3(
79 ; CHECK: call i8* @returner()
80 ; CHECK-NEXT: ret i8* %call
83 %call = tail call i8* @returner()
84 %0 = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %call) nounwind
85 %1 = call i8* @llvm.objc.autoreleaseReturnValue(i8* %0) nounwind
89 ; Delete a redundant retain,autoreleaseRV when forwaring a call result
90 ; directly to a return value.
92 ; CHECK-LABEL: define i8* @test4(
93 ; CHECK: call i8* @returner()
94 ; CHECK-NEXT: ret i8* %call
97 %call = call i8* @returner()
98 %0 = call i8* @llvm.objc.retain(i8* %call) nounwind
99 %1 = call i8* @llvm.objc.autoreleaseReturnValue(i8* %0) nounwind
103 ; Delete a redundant fused retain+autoreleaseRV when forwaring a call result
104 ; directly to a return value.
107 ; HECK: define i8* @test5
108 ; HECK: call i8* @returner()
109 ; HECK-NEXT: ret i8* %call
110 ;define i8* @test5() {
112 ; %call = call i8* @returner()
113 ; %0 = call i8* @llvm.objc.retainAutoreleaseReturnValue(i8* %call) nounwind
117 ; Don't eliminate objc_retainAutoreleasedReturnValue by merging it into
118 ; an objc_autorelease.
119 ; TODO? Merge objc_retainAutoreleasedReturnValue and objc_autorelease into
120 ; objc_retainAutoreleasedReturnValueAutorelease and merge
121 ; objc_retainAutoreleasedReturnValue and objc_autoreleaseReturnValue
122 ; into objc_retainAutoreleasedReturnValueAutoreleaseReturnValue?
123 ; Those entrypoints don't exist yet though.
125 ; CHECK-LABEL: define i8* @test7(
126 ; CHECK: call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %p)
127 ; CHECK: %t = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %p)
128 define i8* @test7() {
129 %p = call i8* @returner()
130 call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %p)
131 %t = call i8* @llvm.objc.autoreleaseReturnValue(i8* %p)
132 call void @use_pointer(i8* %p)
136 ; CHECK-LABEL: define i8* @test7b(
137 ; CHECK: call i8* @llvm.objc.retain(i8* %p)
138 ; CHECK: %t = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %p)
139 define i8* @test7b() {
140 %p = call i8* @returner()
141 call void @use_pointer(i8* %p)
142 call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %p)
143 %t = call i8* @llvm.objc.autoreleaseReturnValue(i8* %p)
147 ; Don't apply the RV optimization to autorelease if there's no retain.
149 ; CHECK: define i8* @test9(i8* %p)
150 ; CHECK: call i8* @llvm.objc.autorelease(i8* %p)
151 define i8* @test9(i8* %p) {
152 call i8* @llvm.objc.autorelease(i8* %p)
156 ; Do not apply the RV optimization.
158 ; CHECK: define i8* @test10(i8* %p)
159 ; CHECK: tail call i8* @llvm.objc.retain(i8* %p) [[NUW]]
160 ; CHECK: call i8* @llvm.objc.autorelease(i8* %p) [[NUW]]
161 ; CHECK-NEXT: ret i8* %p
162 define i8* @test10(i8* %p) {
163 %1 = call i8* @llvm.objc.retain(i8* %p)
164 %2 = call i8* @llvm.objc.autorelease(i8* %p)
168 ; Don't do the autoreleaseRV optimization because @use_pointer
169 ; could undo the retain.
171 ; CHECK: define i8* @test11(i8* %p)
172 ; CHECK: tail call i8* @llvm.objc.retain(i8* %p)
173 ; CHECK-NEXT: call void @use_pointer(i8* %p)
174 ; CHECK: call i8* @llvm.objc.autorelease(i8* %p)
175 ; CHECK-NEXT: ret i8* %p
176 define i8* @test11(i8* %p) {
177 %1 = call i8* @llvm.objc.retain(i8* %p)
178 call void @use_pointer(i8* %p)
179 %2 = call i8* @llvm.objc.autorelease(i8* %p)
183 ; Don't spoil the RV optimization.
185 ; CHECK: define i8* @test12(i8* %p)
186 ; CHECK: tail call i8* @llvm.objc.retain(i8* %p)
187 ; CHECK: call void @use_pointer(i8* %p)
188 ; CHECK: tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %p)
190 define i8* @test12(i8* %p) {
191 %1 = call i8* @llvm.objc.retain(i8* %p)
192 call void @use_pointer(i8* %p)
193 %2 = call i8* @llvm.objc.autoreleaseReturnValue(i8* %p)
197 ; Don't zap the objc_retainAutoreleasedReturnValue.
199 ; CHECK-LABEL: define i8* @test13(
200 ; CHECK: tail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %p)
201 ; CHECK: call i8* @llvm.objc.autorelease(i8* %p)
203 define i8* @test13() {
204 %p = call i8* @returner()
205 %1 = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %p)
207 %2 = call i8* @llvm.objc.autorelease(i8* %p)
211 ; Convert objc_retainAutoreleasedReturnValue to objc_retain if its
212 ; argument is not a return value.
214 ; CHECK-LABEL: define void @test14(
215 ; CHECK-NEXT: tail call i8* @llvm.objc.retain(i8* %p) [[NUW]]
216 ; CHECK-NEXT: ret void
217 define void @test14(i8* %p) {
218 call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %p)
222 ; Don't convert objc_retainAutoreleasedReturnValue to objc_retain if its
223 ; argument is a return value.
225 ; CHECK-LABEL: define void @test15(
226 ; CHECK-NEXT: %y = call i8* @returner()
227 ; CHECK-NEXT: tail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %y) [[NUW]]
228 ; CHECK-NEXT: ret void
229 define void @test15() {
230 %y = call i8* @returner()
231 call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %y)
235 ; Delete autoreleaseRV+retainRV pairs.
237 ; CHECK: define i8* @test19(i8* %p) {
238 ; CHECK-NEXT: ret i8* %p
239 define i8* @test19(i8* %p) {
240 call i8* @llvm.objc.autoreleaseReturnValue(i8* %p)
241 call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %p)
245 ; Delete autoreleaseRV+retainRV pairs when they have equivalent PHIs as inputs
247 ; CHECK: define i8* @test19phi(i8* %p) {
249 ; CHECK-NEXT: br label %test19bb
251 ; CHECK-NEXT: ret i8* %p
252 define i8* @test19phi(i8* %p) {
256 %phi1 = phi i8* [ %p, %entry ]
257 %phi2 = phi i8* [ %p, %entry ]
258 call i8* @llvm.objc.autoreleaseReturnValue(i8* %phi1)
259 call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %phi2)
263 ; Like test19 but with plain autorelease.
265 ; CHECK: define i8* @test20(i8* %p) {
266 ; CHECK-NEXT: call i8* @llvm.objc.autorelease(i8* %p)
267 ; CHECK-NEXT: call i8* @llvm.objc.retain(i8* %p)
268 ; CHECK-NEXT: ret i8* %p
269 define i8* @test20(i8* %p) {
270 call i8* @llvm.objc.autorelease(i8* %p)
271 call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %p)
275 ; Like test19 but with plain retain.
277 ; CHECK: define i8* @test21(i8* %p) {
278 ; CHECK-NEXT: call i8* @llvm.objc.autoreleaseReturnValue(i8* %p)
279 ; CHECK-NEXT: call i8* @llvm.objc.retain(i8* %p)
280 ; CHECK-NEXT: ret i8* %p
281 define i8* @test21(i8* %p) {
282 call i8* @llvm.objc.autoreleaseReturnValue(i8* %p)
283 call i8* @llvm.objc.retain(i8* %p)
287 ; Like test19 but with plain retain and autorelease.
289 ; CHECK: define i8* @test22(i8* %p) {
290 ; CHECK-NEXT: call i8* @llvm.objc.autorelease(i8* %p)
291 ; CHECK-NEXT: call i8* @llvm.objc.retain(i8* %p)
292 ; CHECK-NEXT: ret i8* %p
293 define i8* @test22(i8* %p) {
294 call i8* @llvm.objc.autorelease(i8* %p)
295 call i8* @llvm.objc.retain(i8* %p)
299 ; Convert autoreleaseRV to autorelease.
301 ; CHECK-LABEL: define void @test23(
302 ; CHECK: call i8* @llvm.objc.autorelease(i8* %p) [[NUW]]
303 define void @test23(i8* %p) {
305 call i8* @llvm.objc.autoreleaseReturnValue(i8* %p)
309 ; Don't convert autoreleaseRV to autorelease if the result is returned,
310 ; even through a bitcast.
312 ; CHECK-LABEL: define {}* @test24(
313 ; CHECK: tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %p)
314 define {}* @test24(i8* %p) {
315 %t = call i8* @llvm.objc.autoreleaseReturnValue(i8* %p)
316 %s = bitcast i8* %p to {}*
320 declare i8* @first_test25();
321 declare i8* @second_test25(i8*);
322 declare void @somecall_test25();
324 ; ARC optimizer used to move the last release between the call to second_test25
325 ; and the call to objc_retainAutoreleasedReturnValue, causing %second to be
326 ; released prematurely when %first and %second were pointing to the same object.
328 ; CHECK-LABEL: define void @test25(
329 ; CHECK: %[[CALL1:.*]] = call i8* @second_test25(
330 ; CHECK-NEXT: tail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %[[CALL1]])
332 define void @test25() {
333 %first = call i8* @first_test25()
334 %v0 = call i8* @llvm.objc.retain(i8* %first)
335 call void @somecall_test25()
336 %second = call i8* @second_test25(i8* %first)
337 %call2 = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %second)
338 call void @llvm.objc.release(i8* %second), !clang.imprecise_release !0
339 call void @llvm.objc.release(i8* %first), !clang.imprecise_release !0
343 ; Check that ObjCARCOpt::OptimizeReturns removes the redundant calls even when
344 ; they are not in the same basic block. This code used to cause an assertion
347 ; CHECK-LABEL: define i8* @test26()
348 ; CHECK: call i8* @returner()
350 define i8* @test26() {
352 %v0 = call i8* @returner()
353 %v1 = tail call i8* @llvm.objc.retain(i8* %v0)
356 %v2 = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %v1)
362 declare i32* @func27(i32);
364 ; Check that ObjCARCOpt::OptimizeAutoreleaseRVCall doesn't turn a call to
365 ; @llvm.objc.autoreleaseReturnValue into a call to @llvm.objc.autorelease when a return
366 ; instruction uses a value equivalent to @llvm.objc.autoreleaseReturnValue's operand.
367 ; In the code below, %phival and %retval are considered equivalent.
369 ; CHECK-LABEL: define i32* @test27(
370 ; CHECK: %[[PHIVAL:.*]] = phi i8* [ %{{.*}}, %bb1 ], [ %{{.*}}, %bb2 ]
371 ; CHECK: %[[RETVAL:.*]] = phi i32* [ %{{.*}}, %bb1 ], [ %{{.*}}, %bb2 ]
372 ; CHECK: tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %[[PHIVAL]])
373 ; CHECK: ret i32* %[[RETVAL]]
375 define i32* @test27(i1 %cond) {
377 br i1 %cond, label %bb1, label %bb2
379 %v0 = call i32* @func27(i32 1)
380 %v1 = bitcast i32* %v0 to i8*
383 %v2 = call i32* @func27(i32 2)
384 %v3 = bitcast i32* %v2 to i8*
387 %phival = phi i8* [ %v1, %bb1 ], [ %v3, %bb2 ]
388 %retval = phi i32* [ %v0, %bb1 ], [ %v2, %bb2 ]
389 %v4 = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %phival)
393 ; Don't eliminate the retainRV/autoreleaseRV pair if the call isn't a tail call.
395 ; CHECK-LABEL: define i8* @test28(
396 ; CHECK: call i8* @returner()
397 ; CHECK: call i8* @llvm.objc.retainAutoreleasedReturnValue(
398 ; CHECK: call i8* @llvm.objc.autoreleaseReturnValue(
399 define i8* @test28() {
401 %call = call i8* @returner()
402 %0 = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %call) nounwind
403 %1 = call i8* @llvm.objc.autoreleaseReturnValue(i8* %0) nounwind
407 ; CHECK-LABEL: define i8* @test29(
408 ; CHECK: call i8* @llvm.objc.retainAutoreleasedReturnValue(
409 ; CHECK: call i8* @llvm.objc.autoreleaseReturnValue(
411 define i8* @test29(i8* %k) local_unnamed_addr personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
413 %0 = tail call i8* @llvm.objc.retain(i8* %k)
414 %call = invoke i8* @returner1(i8* %k)
415 to label %invoke.cont unwind label %lpad
418 %1 = bitcast i8* %call to i8*
419 %2 = notail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %1)
420 tail call void @llvm.objc.release(i8* %k), !clang.imprecise_release !0
421 %3 = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %1)
425 %4 = landingpad { i8*, i32 }
427 tail call void @llvm.objc.release(i8* %k) #1, !clang.imprecise_release !0
428 resume { i8*, i32 } %4
431 ; The second retainRV/autoreleaseRV pair can be removed since the call to
432 ; @returner is a tail call.
434 ; CHECK-LABEL: define i8* @test30(
435 ; CHECK: %[[V0:.*]] = call i8* @returner()
436 ; CHECK-NEXT: call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %[[V0]])
437 ; CHECK-NEXT: call i8* @llvm.objc.autoreleaseReturnValue(i8* %[[V0]])
438 ; CHECK-NEXT: ret i8* %[[V0]]
439 ; CHECK: %[[V3:.*]] = tail call i8* @returner()
440 ; CHECK-NEXT: ret i8* %[[V3]]
442 define i8* @test30(i1 %cond) {
443 br i1 %cond, label %bb0, label %bb1
445 %v0 = call i8* @returner()
446 %v1 = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %v0)
447 %v2 = call i8* @llvm.objc.autoreleaseReturnValue(i8* %v0)
450 %v3 = tail call i8* @returner()
451 %v4 = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %v3)
452 %v5 = call i8* @llvm.objc.autoreleaseReturnValue(i8* %v3)
456 ; Remove operand bundle "clang.arc.attachedcall" and the autoreleaseRV call if the call
459 ; CHECK-LABEL: define i8* @test31(
460 ; CHECK-NEXT: %[[CALL:.*]] = tail call i8* @returner()
461 ; CHECK-NEXT: ret i8* %[[CALL]]
463 define i8* @test31() {
464 %call = tail call i8* @returner() [ "clang.arc.attachedcall"(i64 0) ]
465 call void (...) @llvm.objc.clang.arc.noop.use(i8* %call)
466 %1 = call i8* @llvm.objc.autoreleaseReturnValue(i8* %call)
470 ; CHECK-LABEL: define i8* @test32(
471 ; CHECK: %[[CALL:.*]] = call i8* @returner() [ "clang.arc.attachedcall"(i64 0) ]
472 ; CHECK: call void (...) @llvm.objc.clang.arc.noop.use(i8* %[[CALL]])
473 ; CHECK: call i8* @llvm.objc.autoreleaseReturnValue(i8* %[[CALL]])
475 define i8* @test32() {
476 %call = call i8* @returner() [ "clang.arc.attachedcall"(i64 0) ]
477 call void (...) @llvm.objc.clang.arc.noop.use(i8* %call)
478 %1 = call i8* @llvm.objc.autoreleaseReturnValue(i8* %call)
484 ; CHECK: attributes [[NUW]] = { nounwind }