SimplifyCFG: don't remove unreachable default switch destinations
[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-LABEL:      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) [[NUW:#[0-9]+]]
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-LABEL: 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-LABEL: 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-LABEL: 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-LABEL: 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* %p)
125   ret i8* %t
126 }
127
128 ; CHECK-LABEL: 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* %p
137 }
138
139 ; Don't apply the RV optimization to autorelease if there's no retain.
140
141 ; CHECK: define i8* @test9(i8* %p)
142 ; CHECK: call i8* @objc_autorelease(i8* %p)
143 define i8* @test9(i8* %p) {
144   call i8* @objc_autorelease(i8* %p)
145   ret i8* %p
146 }
147
148 ; Do not apply the RV optimization.
149
150 ; CHECK: define i8* @test10(i8* %p)
151 ; CHECK: tail call i8* @objc_retain(i8* %p) [[NUW]]
152 ; CHECK: call i8* @objc_autorelease(i8* %p) [[NUW]]
153 ; CHECK-NEXT: ret i8* %p
154 define i8* @test10(i8* %p) {
155   %1 = call i8* @objc_retain(i8* %p)
156   %2 = call i8* @objc_autorelease(i8* %p)
157   ret i8* %p
158 }
159
160 ; Don't do the autoreleaseRV optimization because @use_pointer
161 ; could undo the retain.
162
163 ; CHECK: define i8* @test11(i8* %p)
164 ; CHECK: tail call i8* @objc_retain(i8* %p)
165 ; CHECK-NEXT: call void @use_pointer(i8* %p)
166 ; CHECK: call i8* @objc_autorelease(i8* %p)
167 ; CHECK-NEXT: ret i8* %p
168 define i8* @test11(i8* %p) {
169   %1 = call i8* @objc_retain(i8* %p)
170   call void @use_pointer(i8* %p)
171   %2 = call i8* @objc_autorelease(i8* %p)
172   ret i8* %p
173 }
174
175 ; Don't spoil the RV optimization.
176
177 ; CHECK: define i8* @test12(i8* %p)
178 ; CHECK: tail call i8* @objc_retain(i8* %p)
179 ; CHECK: call void @use_pointer(i8* %p)
180 ; CHECK: tail call i8* @objc_autoreleaseReturnValue(i8* %p)
181 ; CHECK: ret i8* %p
182 define i8* @test12(i8* %p) {
183   %1 = call i8* @objc_retain(i8* %p)
184   call void @use_pointer(i8* %p)
185   %2 = call i8* @objc_autoreleaseReturnValue(i8* %p)
186   ret i8* %p
187 }
188
189 ; Don't zap the objc_retainAutoreleasedReturnValue.
190
191 ; CHECK-LABEL: define i8* @test13(
192 ; CHECK: tail call i8* @objc_retainAutoreleasedReturnValue(i8* %p)
193 ; CHECK: call i8* @objc_autorelease(i8* %p)
194 ; CHECK: ret i8* %p
195 define i8* @test13() {
196   %p = call i8* @returner()
197   %1 = call i8* @objc_retainAutoreleasedReturnValue(i8* %p)
198   call void @callee()
199   %2 = call i8* @objc_autorelease(i8* %p)
200   ret i8* %p
201 }
202
203 ; Convert objc_retainAutoreleasedReturnValue to objc_retain if its
204 ; argument is not a return value.
205
206 ; CHECK-LABEL: define void @test14(
207 ; CHECK-NEXT: tail call i8* @objc_retain(i8* %p) [[NUW]]
208 ; CHECK-NEXT: ret void
209 define void @test14(i8* %p) {
210   call i8* @objc_retainAutoreleasedReturnValue(i8* %p)
211   ret void
212 }
213
214 ; Don't convert objc_retainAutoreleasedReturnValue to objc_retain if its
215 ; argument is a return value.
216
217 ; CHECK-LABEL: define void @test15(
218 ; CHECK-NEXT: %y = call i8* @returner()
219 ; CHECK-NEXT: tail call i8* @objc_retainAutoreleasedReturnValue(i8* %y) [[NUW]]
220 ; CHECK-NEXT: ret void
221 define void @test15() {
222   %y = call i8* @returner()
223   call i8* @objc_retainAutoreleasedReturnValue(i8* %y)
224   ret void
225 }
226
227 ; Delete autoreleaseRV+retainRV pairs.
228
229 ; CHECK: define i8* @test19(i8* %p) {
230 ; CHECK-NEXT: ret i8* %p
231 define i8* @test19(i8* %p) {
232   call i8* @objc_autoreleaseReturnValue(i8* %p)
233   call i8* @objc_retainAutoreleasedReturnValue(i8* %p)
234   ret i8* %p
235 }
236
237 ; Like test19 but with plain autorelease.
238
239 ; CHECK: define i8* @test20(i8* %p) {
240 ; CHECK-NEXT: call i8* @objc_autorelease(i8* %p)
241 ; CHECK-NEXT: call i8* @objc_retain(i8* %p)
242 ; CHECK-NEXT: ret i8* %p
243 define i8* @test20(i8* %p) {
244   call i8* @objc_autorelease(i8* %p)
245   call i8* @objc_retainAutoreleasedReturnValue(i8* %p)
246   ret i8* %p
247 }
248
249 ; Like test19 but with plain retain.
250
251 ; CHECK: define i8* @test21(i8* %p) {
252 ; CHECK-NEXT: call i8* @objc_autoreleaseReturnValue(i8* %p)
253 ; CHECK-NEXT: call i8* @objc_retain(i8* %p)
254 ; CHECK-NEXT: ret i8* %p
255 define i8* @test21(i8* %p) {
256   call i8* @objc_autoreleaseReturnValue(i8* %p)
257   call i8* @objc_retain(i8* %p)
258   ret i8* %p
259 }
260
261 ; Like test19 but with plain retain and autorelease.
262
263 ; CHECK: define i8* @test22(i8* %p) {
264 ; CHECK-NEXT: call i8* @objc_autorelease(i8* %p)
265 ; CHECK-NEXT: call i8* @objc_retain(i8* %p)
266 ; CHECK-NEXT: ret i8* %p
267 define i8* @test22(i8* %p) {
268   call i8* @objc_autorelease(i8* %p)
269   call i8* @objc_retain(i8* %p)
270   ret i8* %p
271 }
272
273 ; Convert autoreleaseRV to autorelease.
274
275 ; CHECK-LABEL: define void @test23(
276 ; CHECK: call i8* @objc_autorelease(i8* %p) [[NUW]]
277 define void @test23(i8* %p) {
278   store i8 0, i8* %p
279   call i8* @objc_autoreleaseReturnValue(i8* %p)
280   ret void
281 }
282
283 ; Don't convert autoreleaseRV to autorelease if the result is returned,
284 ; even through a bitcast.
285
286 ; CHECK-LABEL: define {}* @test24(
287 ; CHECK: tail call i8* @objc_autoreleaseReturnValue(i8* %p)
288 define {}* @test24(i8* %p) {
289   %t = call i8* @objc_autoreleaseReturnValue(i8* %p)
290   %s = bitcast i8* %p to {}*
291   ret {}* %s
292 }
293
294 ; CHECK: attributes [[NUW]] = { nounwind }