638b89ccc724aa0ef41ca71ef95b8520190b1f4b
[oota-llvm.git] / test / Transforms / ObjCARC / rv.ll
1 ; RUN: opt -objc-arc -S < %s | FileCheck %s
2
3 target datalayout = "e-p:64:64:64"
4
5 declare i8* @objc_retain(i8*)
6 declare i8* @objc_retainAutoreleasedReturnValue(i8*)
7 declare void @objc_release(i8*)
8 declare i8* @objc_autorelease(i8*)
9 declare i8* @objc_autoreleaseReturnValue(i8*)
10 declare i8* @objc_retainAutoreleaseReturnValue(i8*)
11 declare void @objc_autoreleasePoolPop(i8*)
12 declare void @objc_autoreleasePoolPush()
13 declare i8* @objc_retainBlock(i8*)
14
15 declare i8* @objc_retainedObject(i8*)
16 declare i8* @objc_unretainedObject(i8*)
17 declare i8* @objc_unretainedPointer(i8*)
18
19 declare void @use_pointer(i8*)
20 declare void @callee()
21 declare void @callee_fnptr(void ()*)
22 declare void @invokee()
23 declare i8* @returner()
24
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.
28
29 ; CHECK:      define void @test0(
30 ; CHECK-NEXT: entry:
31 ; CHECK-NEXT:   %x = call i8* @returner
32 ; CHECK-NEXT:   %0 = tail call i8* @objc_retainAutoreleasedReturnValue(i8* %x) nounwind
33 ; CHECK: t:
34 ; CHECK-NOT: @objc_
35 ; CHECK: return:
36 ; CHECK-NEXT: call void @objc_release(i8* %x)
37 ; CHECK-NEXT: ret void
38 ; CHECK-NEXT: }
39 define void @test0(i1 %p) nounwind {
40 entry:
41   %x = call i8* @returner()
42   %0 = call i8* @objc_retainAutoreleasedReturnValue(i8* %x)
43   br i1 %p, label %t, label %return
44
45 t:
46   call void @use_pointer(i8* %x)
47   store i8 0, i8* %x
48   br label %return
49
50 return:
51   call void @objc_release(i8* %x) nounwind
52   ret void
53 }
54
55 ; Delete no-ops.
56
57 ; CHECK: define void @test2
58 ; CHECK-NOT: @objc_
59 ; CHECK: }
60 define void @test2() {
61   call i8* @objc_retainAutoreleasedReturnValue(i8* null)
62   call i8* @objc_autoreleaseReturnValue(i8* null)
63   ; call i8* @objc_retainAutoreleaseReturnValue(i8* null) ; TODO
64   ret void
65 }
66
67 ; Delete a redundant retainRV,autoreleaseRV when forwaring a call result
68 ; directly to a return value.
69
70 ; CHECK: define i8* @test3
71 ; CHECK: call i8* @returner()
72 ; CHECK-NEXT: ret i8* %call
73 define i8* @test3() {
74 entry:
75   %call = call i8* @returner()
76   %0 = call i8* @objc_retainAutoreleasedReturnValue(i8* %call) nounwind
77   %1 = call i8* @objc_autoreleaseReturnValue(i8* %0) nounwind
78   ret i8* %1
79 }
80
81 ; Delete a redundant retain,autoreleaseRV when forwaring a call result
82 ; directly to a return value.
83
84 ; CHECK: define i8* @test4
85 ; CHECK: call i8* @returner()
86 ; CHECK-NEXT: ret i8* %call
87 define i8* @test4() {
88 entry:
89   %call = call i8* @returner()
90   %0 = call i8* @objc_retain(i8* %call) nounwind
91   %1 = call i8* @objc_autoreleaseReturnValue(i8* %0) nounwind
92   ret i8* %1
93 }
94
95 ; Delete a redundant fused retain+autoreleaseRV when forwaring a call result
96 ; directly to a return value.
97
98 ; TODO
99 ; HECK: define i8* @test5
100 ; HECK: call i8* @returner()
101 ; HECK-NEXT: ret i8* %call
102 ;define i8* @test5() {
103 ;entry:
104 ;  %call = call i8* @returner()
105 ;  %0 = call i8* @objc_retainAutoreleaseReturnValue(i8* %call) nounwind
106 ;  ret i8* %0
107 ;}
108
109 ; Don't eliminate objc_retainAutoreleasedReturnValue by merging it into
110 ; an objc_autorelease.
111 ; TODO? Merge objc_retainAutoreleasedReturnValue and objc_autorelease into
112 ; objc_retainAutoreleasedReturnValueAutorelease and merge
113 ; objc_retainAutoreleasedReturnValue and objc_autoreleaseReturnValue
114 ; into objc_retainAutoreleasedReturnValueAutoreleaseReturnValue?
115 ; Those entrypoints don't exist yet though.
116
117 ; CHECK: define i8* @test7(
118 ; CHECK: call i8* @objc_retainAutoreleasedReturnValue(i8* %p)
119 ; CHECK: %t = tail call i8* @objc_autoreleaseReturnValue(i8* %p)
120 define i8* @test7() {
121   %p = call i8* @returner()
122   call i8* @objc_retainAutoreleasedReturnValue(i8* %p)
123   %t = call i8* @objc_autoreleaseReturnValue(i8* %p)
124   call void @use_pointer(i8* %t)
125   ret i8* %t
126 }
127
128 ; CHECK: define i8* @test7b(
129 ; CHECK: call i8* @objc_retain(i8* %p)
130 ; CHECK: %t = tail call i8* @objc_autoreleaseReturnValue(i8* %p)
131 define i8* @test7b() {
132   %p = call i8* @returner()
133   call void @use_pointer(i8* %p)
134   call i8* @objc_retainAutoreleasedReturnValue(i8* %p)
135   %t = call i8* @objc_autoreleaseReturnValue(i8* %p)
136   ret i8* %t
137 }
138
139 ; Turn objc_retain into objc_retainAutoreleasedReturnValue if its operand
140 ; is a return value.
141
142 ; CHECK: define void @test8()
143 ; CHECK: tail call i8* @objc_retainAutoreleasedReturnValue(i8* %p)
144 define void @test8() {
145   %p = call i8* @returner()
146   call i8* @objc_retain(i8* %p)
147   ret void
148 }
149
150 ; Don't apply the RV optimization to autorelease if there's no retain.
151
152 ; CHECK: define i8* @test9(i8* %p)
153 ; CHECK: call i8* @objc_autorelease(i8* %p)
154 define i8* @test9(i8* %p) {
155   call i8* @objc_autorelease(i8* %p)
156   ret i8* %p
157 }
158
159 ; Apply the RV optimization.
160
161 ; CHECK: define i8* @test10(i8* %p)
162 ; CHECK: tail call i8* @objc_retain(i8* %p) nounwind
163 ; CHECK: tail call i8* @objc_autoreleaseReturnValue(i8* %p) nounwind
164 ; CHECK-NEXT: ret i8* %p
165 define i8* @test10(i8* %p) {
166   %1 = call i8* @objc_retain(i8* %p)
167   %2 = call i8* @objc_autorelease(i8* %p)
168   ret i8* %p
169 }
170
171 ; Don't do the autoreleaseRV optimization because @use_pointer
172 ; could undo the retain.
173
174 ; CHECK: define i8* @test11(i8* %p)
175 ; CHECK: tail call i8* @objc_retain(i8* %p)
176 ; CHECK-NEXT: call void @use_pointer(i8* %p)
177 ; CHECK: call i8* @objc_autorelease(i8* %p)
178 ; CHECK-NEXT: ret i8* %p
179 define i8* @test11(i8* %p) {
180   %1 = call i8* @objc_retain(i8* %p)
181   call void @use_pointer(i8* %p)
182   %2 = call i8* @objc_autorelease(i8* %p)
183   ret i8* %p
184 }
185
186 ; Don't spoil the RV optimization.
187
188 ; CHECK: define i8* @test12(i8* %p)
189 ; CHECK: tail call i8* @objc_retain(i8* %p)
190 ; CHECK: call void @use_pointer(i8* %p)
191 ; CHECK: tail call i8* @objc_autoreleaseReturnValue(i8* %p)
192 ; CHECK: ret i8* %p
193 define i8* @test12(i8* %p) {
194   %1 = call i8* @objc_retain(i8* %p)
195   call void @use_pointer(i8* %p)
196   %2 = call i8* @objc_autoreleaseReturnValue(i8* %p)
197   ret i8* %p
198 }
199
200 ; Don't zap the objc_retainAutoreleasedReturnValue.
201
202 ; CHECK: define i8* @test13(
203 ; CHECK: tail call i8* @objc_retainAutoreleasedReturnValue(i8* %p)
204 ; CHECK: call i8* @objc_autorelease(i8* %p)
205 ; CHECK: ret i8* %p
206 define i8* @test13() {
207   %p = call i8* @returner()
208   %1 = call i8* @objc_retainAutoreleasedReturnValue(i8* %p)
209   call void @callee()
210   %2 = call i8* @objc_autorelease(i8* %p)
211   ret i8* %p
212 }
213
214 ; Convert objc_retainAutoreleasedReturnValue to objc_retain if its
215 ; argument is not a return value.
216
217 ; CHECK: define void @test14(
218 ; CHECK-NEXT: tail call i8* @objc_retain(i8* %p) nounwind
219 ; CHECK-NEXT: ret void
220 define void @test14(i8* %p) {
221   call i8* @objc_retainAutoreleasedReturnValue(i8* %p)
222   ret void
223 }
224
225 ; Don't convert objc_retainAutoreleasedReturnValue to objc_retain if its
226 ; argument is a return value.
227
228 ; CHECK: define void @test15(
229 ; CHECK-NEXT: %y = call i8* @returner()
230 ; CHECK-NEXT: tail call i8* @objc_retainAutoreleasedReturnValue(i8* %y) nounwind
231 ; CHECK-NEXT: ret void
232 define void @test15() {
233   %y = call i8* @returner()
234   call i8* @objc_retainAutoreleasedReturnValue(i8* %y)
235   ret void
236 }
237
238 ; Convert objc_retain to objc_retainAutoreleasedReturnValue if its
239 ; argument is a return value.
240
241 ; CHECK: define void @test16(
242 ; CHECK-NEXT: %y = call i8* @returner()
243 ; CHECK-NEXT: tail call i8* @objc_retainAutoreleasedReturnValue(i8* %y) nounwind
244 ; CHECK-NEXT: ret void
245 define void @test16() {
246   %y = call i8* @returner()
247   call i8* @objc_retain(i8* %y)
248   ret void
249 }
250
251 ; Don't convert objc_retain to objc_retainAutoreleasedReturnValue if its
252 ; argument is not a return value.
253
254 ; CHECK: define void @test17(
255 ; CHECK-NEXT: tail call i8* @objc_retain(i8* %y) nounwind
256 ; CHECK-NEXT: ret void
257 define void @test17(i8* %y) {
258   call i8* @objc_retain(i8* %y)
259   ret void
260 }
261
262 ; Don't Convert objc_retain to objc_retainAutoreleasedReturnValue if it
263 ; isn't next to the call providing its return value.
264
265 ; CHECK: define void @test18(
266 ; CHECK-NEXT: %y = call i8* @returner()
267 ; CHECK-NEXT: call void @callee()
268 ; CHECK-NEXT: tail call i8* @objc_retain(i8* %y) nounwind
269 ; CHECK-NEXT: ret void
270 define void @test18() {
271   %y = call i8* @returner()
272   call void @callee()
273   call i8* @objc_retain(i8* %y)
274   ret void
275 }
276
277 ; Delete autoreleaseRV+retainRV pairs.
278
279 ; CHECK: define i8* @test19(i8* %p) {
280 ; CHECK-NEXT: ret i8* %p
281 define i8* @test19(i8* %p) {
282   call i8* @objc_autoreleaseReturnValue(i8* %p)
283   call i8* @objc_retainAutoreleasedReturnValue(i8* %p)
284   ret i8* %p
285 }
286
287 ; Like test19 but with plain autorelease.
288
289 ; CHECK: define i8* @test20(i8* %p) {
290 ; CHECK-NEXT: call i8* @objc_autorelease(i8* %p)
291 ; CHECK-NEXT: call i8* @objc_retain(i8* %p)
292 ; CHECK-NEXT: ret i8* %p
293 define i8* @test20(i8* %p) {
294   call i8* @objc_autorelease(i8* %p)
295   call i8* @objc_retainAutoreleasedReturnValue(i8* %p)
296   ret i8* %p
297 }
298
299 ; Like test19 but with plain retain.
300
301 ; CHECK: define i8* @test21(i8* %p) {
302 ; CHECK-NEXT: call i8* @objc_autoreleaseReturnValue(i8* %p)
303 ; CHECK-NEXT: call i8* @objc_retain(i8* %p)
304 ; CHECK-NEXT: ret i8* %p
305 define i8* @test21(i8* %p) {
306   call i8* @objc_autoreleaseReturnValue(i8* %p)
307   call i8* @objc_retain(i8* %p)
308   ret i8* %p
309 }
310
311 ; Like test19 but with plain retain and autorelease.
312
313 ; CHECK: define i8* @test22(i8* %p) {
314 ; CHECK-NEXT: call i8* @objc_autorelease(i8* %p)
315 ; CHECK-NEXT: call i8* @objc_retain(i8* %p)
316 ; CHECK-NEXT: ret i8* %p
317 define i8* @test22(i8* %p) {
318   call i8* @objc_autorelease(i8* %p)
319   call i8* @objc_retain(i8* %p)
320   ret i8* %p
321 }
322
323 ; Convert autoreleaseRV to autorelease.
324
325 ; CHECK: define void @test23(
326 ; CHECK: call i8* @objc_autorelease(i8* %p) nounwind
327 define void @test23(i8* %p) {
328   store i8 0, i8* %p
329   call i8* @objc_autoreleaseReturnValue(i8* %p)
330   ret void
331 }
332
333 ; Don't convert autoreleaseRV to autorelease if the result is returned,
334 ; even through a bitcast.
335
336 ; CHECK: define {}* @test24(
337 ; CHECK: tail call i8* @objc_autoreleaseReturnValue(i8* %p)
338 define {}* @test24(i8* %p) {
339   %t = call i8* @objc_autoreleaseReturnValue(i8* %p)
340   %s = bitcast i8* %p to {}*
341   ret {}* %s
342 }