[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / ObjCARC / rv.ll
blob29017222ebb1145fcac7528c454060228a117cbd
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(
33 ; CHECK-NEXT: entry:
34 ; CHECK-NEXT:   %x = call i8* @returner
35 ; CHECK-NEXT:   %0 = tail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %x) [[NUW:#[0-9]+]]
36 ; CHECK: t:
37 ; CHECK-NOT: @llvm.objc.
38 ; CHECK: return:
39 ; CHECK-NEXT: call void @llvm.objc.release(i8* %x)
40 ; CHECK-NEXT: ret void
41 ; CHECK-NEXT: }
42 define void @test0(i1 %p) nounwind {
43 entry:
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)
50   store i8 0, i8* %x
51   br label %return
53 return:
54   call void @llvm.objc.release(i8* %x) nounwind
55   ret void
58 ; Delete no-ops.
60 ; CHECK-LABEL: define void @test2(
61 ; CHECK-NOT: @llvm.objc.
62 ; CHECK: }
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)
72   ret void
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
81 define i8* @test3() {
82 entry:
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
86   ret i8* %1
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
95 define i8* @test4() {
96 entry:
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
100   ret i8* %1
103 ; Delete a redundant fused retain+autoreleaseRV when forwaring a call result
104 ; directly to a return value.
106 ; TODO
107 ; HECK: define i8* @test5
108 ; HECK: call i8* @returner()
109 ; HECK-NEXT: ret i8* %call
110 ;define i8* @test5() {
111 ;entry:
112 ;  %call = call i8* @returner()
113 ;  %0 = call i8* @llvm.objc.retainAutoreleaseReturnValue(i8* %call) nounwind
114 ;  ret i8* %0
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)
133   ret i8* %t
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)
144   ret 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)
153   ret 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)
165   ret 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)
180   ret 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)
189 ; CHECK: ret 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)
194   ret 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)
202 ; CHECK: ret i8* %p
203 define i8* @test13() {
204   %p = call i8* @returner()
205   %1 = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %p)
206   call void @callee()
207   %2 = call i8* @llvm.objc.autorelease(i8* %p)
208   ret 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)
219   ret void
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)
232   ret void
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)
242   ret i8* %p
245 ; Delete autoreleaseRV+retainRV pairs when they have equivalent PHIs as inputs
247 ; CHECK: define i8* @test19phi(i8* %p) {
248 ; CHECK-NEXT: entry:
249 ; CHECK-NEXT: br label %test19bb
250 ; CHECK: test19bb:
251 ; CHECK-NEXT: ret i8* %p
252 define i8* @test19phi(i8* %p) {
253 entry:
254   br label %test19bb
255 test19bb:
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)
260   ret i8* %p
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)
272   ret 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)
284   ret 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)
296   ret 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) {
304   store i8 0, i8* %p
305   call i8* @llvm.objc.autoreleaseReturnValue(i8* %p)
306   ret void
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 {}*
317   ret {}* %s
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
340   ret void
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
345 ; failure.
347 ; CHECK-LABEL: define i8* @test26()
348 ; CHECK: call i8* @returner()
349 ; CHECK-NOT:  call
350 define i8* @test26() {
351 bb0:
352   %v0 = call i8* @returner()
353   %v1 = tail call i8* @llvm.objc.retain(i8* %v0)
354   br label %bb1
355 bb1:
356   %v2 = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %v1)
357   br label %bb2
358 bb2:
359   ret i8* %v2
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) {
376 entry:
377   br i1 %cond, label %bb1, label %bb2
378 bb1:
379   %v0 = call i32* @func27(i32 1)
380   %v1 = bitcast i32* %v0 to i8*
381   br label %bb3
382 bb2:
383   %v2 = call i32* @func27(i32 2)
384   %v3 = bitcast i32* %v2 to i8*
385   br label %bb3
386 bb3:
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)
390   ret i32* %retval
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() {
400 entry:
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
404   ret i8* %1
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*) {
412 entry:
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
417 invoke.cont:
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)
422   ret i8* %call
424 lpad:
425   %4 = landingpad { i8*, i32 }
426           cleanup
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
444 bb0:
445   %v0 = call i8* @returner()
446   %v1 = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %v0)
447   %v2 = call i8* @llvm.objc.autoreleaseReturnValue(i8* %v0)
448   ret i8* %v0
449 bb1:
450   %v3 = tail call i8* @returner()
451   %v4 = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %v3)
452   %v5 = call i8* @llvm.objc.autoreleaseReturnValue(i8* %v3)
453   ret i8* %v3
456 ; Remove operand bundle "clang.arc.attachedcall" and the autoreleaseRV call if the call
457 ; is a tail 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)
467   ret i8* %1
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)
479   ret i8* %1
482 !0 = !{}
484 ; CHECK: attributes [[NUW]] = { nounwind }