SimplifyCFG: don't remove unreachable default switch destinations
[oota-llvm.git] / test / Transforms / ObjCARC / allocas.ll
1 ; RUN: opt -objc-arc -S < %s | FileCheck %s
2
3 declare i8* @objc_retain(i8*)
4 declare i8* @objc_retainAutoreleasedReturnValue(i8*)
5 declare void @objc_release(i8*)
6 declare i8* @objc_autorelease(i8*)
7 declare i8* @objc_autoreleaseReturnValue(i8*)
8 declare void @objc_autoreleasePoolPop(i8*)
9 declare i8* @objc_autoreleasePoolPush()
10 declare i8* @objc_retainBlock(i8*)
11
12 declare i8* @objc_retainedObject(i8*)
13 declare i8* @objc_unretainedObject(i8*)
14 declare i8* @objc_unretainedPointer(i8*)
15
16 declare void @use_pointer(i8*)
17 declare void @callee()
18 declare void @callee_fnptr(void ()*)
19 declare void @invokee()
20 declare i8* @returner()
21 declare i8* @returner1()
22 declare i8* @returner2()
23 declare void @bar(i32 ()*)
24 declare void @use_alloca(i8**)
25
26 declare void @llvm.dbg.value(metadata, i64, metadata, metadata)
27
28 declare i8* @objc_msgSend(i8*, i8*, ...)
29
30
31 ; In the presence of allocas, unconditionally remove retain/release pairs only
32 ; if they are known safe in both directions. This prevents matching up an inner
33 ; retain with the boundary guarding release in the following situation:
34
35 ; %A = alloca
36 ; retain(%x)
37 ; retain(%x) <--- Inner Retain
38 ; store %x, %A
39 ; %y = load %A
40 ; ... DO STUFF ...
41 ; release(%y)
42 ; release(%x) <--- Guarding Release
43 ;
44 ; rdar://13750319
45
46 ; CHECK: define void @test1a(i8* %x)
47 ; CHECK: @objc_retain(i8* %x)
48 ; CHECK: @objc_retain(i8* %x)
49 ; CHECK: @objc_release(i8* %y)
50 ; CHECK: @objc_release(i8* %x)
51 ; CHECK: ret void
52 ; CHECK: }
53 define void @test1a(i8* %x) {
54 entry:
55   %A = alloca i8*
56   tail call i8* @objc_retain(i8* %x)
57   tail call i8* @objc_retain(i8* %x)
58   store i8* %x, i8** %A, align 8
59   %y = load i8** %A
60   call void @use_alloca(i8** %A)
61   call void @objc_release(i8* %y), !clang.imprecise_release !0
62   call void @use_pointer(i8* %x)
63   call void @objc_release(i8* %x), !clang.imprecise_release !0
64   ret void
65 }
66
67 ; CHECK: define void @test1b(i8* %x)
68 ; CHECK: @objc_retain(i8* %x)
69 ; CHECK: @objc_retain(i8* %x)
70 ; CHECK: @objc_release(i8* %y)
71 ; CHECK: @objc_release(i8* %x)
72 ; CHECK: ret void
73 ; CHECK: }
74 define void @test1b(i8* %x) {
75 entry:
76   %A = alloca i8*
77   %gep = getelementptr i8** %A, i32 0
78   tail call i8* @objc_retain(i8* %x)
79   tail call i8* @objc_retain(i8* %x)
80   store i8* %x, i8** %gep, align 8
81   %y = load i8** %A
82   call void @use_alloca(i8** %A)
83   call void @objc_release(i8* %y), !clang.imprecise_release !0
84   call void @use_pointer(i8* %x)
85   call void @objc_release(i8* %x), !clang.imprecise_release !0
86   ret void
87 }
88
89
90 ; CHECK: define void @test1c(i8* %x)
91 ; CHECK: @objc_retain(i8* %x)
92 ; CHECK: @objc_retain(i8* %x)
93 ; CHECK: @objc_release(i8* %y)
94 ; CHECK: @objc_release(i8* %x)
95 ; CHECK: ret void
96 ; CHECK: }
97 define void @test1c(i8* %x) {
98 entry:
99   %A = alloca i8*, i32 3
100   %gep = getelementptr i8** %A, i32 2
101   tail call i8* @objc_retain(i8* %x)
102   tail call i8* @objc_retain(i8* %x)
103   store i8* %x, i8** %gep, align 8
104   %y = load i8** %gep
105   call void @use_alloca(i8** %A)
106   call void @objc_release(i8* %y), !clang.imprecise_release !0
107   call void @use_pointer(i8* %x)
108   call void @objc_release(i8* %x), !clang.imprecise_release !0
109   ret void
110 }
111
112
113 ; CHECK: define void @test1d(i8* %x)
114 ; CHECK: @objc_retain(i8* %x)
115 ; CHECK: @objc_retain(i8* %x)
116 ; CHECK: @objc_release(i8* %y)
117 ; CHECK: @objc_release(i8* %x)
118 ; CHECK: ret void
119 ; CHECK: }
120 define void @test1d(i8* %x) {
121 entry:
122   br i1 undef, label %use_allocaA, label %use_allocaB
123
124 use_allocaA:
125   %allocaA = alloca i8*
126   br label %exit
127
128 use_allocaB:
129   %allocaB = alloca i8*
130   br label %exit
131
132 exit:
133   %A = phi i8** [ %allocaA, %use_allocaA ], [ %allocaB, %use_allocaB ]
134   %gep = getelementptr i8** %A, i32 0
135   tail call i8* @objc_retain(i8* %x)
136   tail call i8* @objc_retain(i8* %x)
137   store i8* %x, i8** %gep, align 8
138   %y = load i8** %gep
139   call void @use_alloca(i8** %A)
140   call void @objc_release(i8* %y), !clang.imprecise_release !0
141   call void @use_pointer(i8* %x)
142   call void @objc_release(i8* %x), !clang.imprecise_release !0
143   ret void
144 }
145
146 ; CHECK: define void @test1e(i8* %x)
147 ; CHECK: @objc_retain(i8* %x)
148 ; CHECK: @objc_retain(i8* %x)
149 ; CHECK: @objc_release(i8* %y)
150 ; CHECK: @objc_release(i8* %x)
151 ; CHECK: ret void
152 ; CHECK: }
153 define void @test1e(i8* %x) {
154 entry:
155   br i1 undef, label %use_allocaA, label %use_allocaB
156
157 use_allocaA:
158   %allocaA = alloca i8*, i32 4
159   br label %exit
160
161 use_allocaB:
162   %allocaB = alloca i8*, i32 4
163   br label %exit
164
165 exit:
166   %A = phi i8** [ %allocaA, %use_allocaA ], [ %allocaB, %use_allocaB ]
167   %gep = getelementptr i8** %A, i32 2
168   tail call i8* @objc_retain(i8* %x)
169   tail call i8* @objc_retain(i8* %x)
170   store i8* %x, i8** %gep, align 8
171   %y = load i8** %gep
172   call void @use_alloca(i8** %A)
173   call void @objc_release(i8* %y), !clang.imprecise_release !0
174   call void @use_pointer(i8* %x)
175   call void @objc_release(i8* %x), !clang.imprecise_release !0
176   ret void
177 }
178
179 ; CHECK: define void @test1f(i8* %x)
180 ; CHECK: @objc_retain(i8* %x)
181 ; CHECK: @objc_retain(i8* %x)
182 ; CHECK: @objc_release(i8* %y)
183 ; CHECK: @objc_release(i8* %x)
184 ; CHECK: ret void
185 ; CHECK: }
186 define void @test1f(i8* %x) {
187 entry:
188   %allocaOne = alloca i8*
189   %allocaTwo = alloca i8*
190   %A = select i1 undef, i8** %allocaOne, i8** %allocaTwo
191   tail call i8* @objc_retain(i8* %x)
192   tail call i8* @objc_retain(i8* %x)
193   store i8* %x, i8** %A, align 8
194   %y = load i8** %A
195   call void @use_alloca(i8** %A)
196   call void @objc_release(i8* %y), !clang.imprecise_release !0
197   call void @use_pointer(i8* %x)
198   call void @objc_release(i8* %x), !clang.imprecise_release !0
199   ret void
200 }
201
202 ; Make sure that if a store is in a different basic block we handle known safe
203 ; conservatively.
204
205
206 ; CHECK: define void @test2a(i8* %x)
207 ; CHECK: @objc_retain(i8* %x)
208 ; CHECK: @objc_retain(i8* %x)
209 ; CHECK: @objc_release(i8* %y)
210 ; CHECK: @objc_release(i8* %x)
211 ; CHECK: ret void
212 ; CHECK: }
213 define void @test2a(i8* %x) {
214 entry:
215   %A = alloca i8*
216   store i8* %x, i8** %A, align 8
217   %y = load i8** %A
218   br label %bb1
219
220 bb1:
221   br label %bb2
222
223 bb2:
224   br label %bb3
225
226 bb3:
227   tail call i8* @objc_retain(i8* %x)
228   tail call i8* @objc_retain(i8* %x)
229   call void @use_alloca(i8** %A)
230   call void @objc_release(i8* %y), !clang.imprecise_release !0
231   call void @use_pointer(i8* %x)
232   call void @objc_release(i8* %x), !clang.imprecise_release !0
233   ret void
234 }
235
236 ; CHECK: define void @test2b(i8* %x)
237 ; CHECK: @objc_retain(i8* %x)
238 ; CHECK: @objc_retain(i8* %x)
239 ; CHECK: @objc_release(i8* %y)
240 ; CHECK: @objc_release(i8* %x)
241 ; CHECK: ret void
242 ; CHECK: }
243 define void @test2b(i8* %x) {
244 entry:
245   %A = alloca i8*
246   %gep1 = getelementptr i8** %A, i32 0
247   store i8* %x, i8** %gep1, align 8
248   %gep2 = getelementptr i8** %A, i32 0
249   %y = load i8** %gep2
250   br label %bb1
251
252 bb1:
253   br label %bb2
254
255 bb2:
256   br label %bb3
257
258 bb3:
259   tail call i8* @objc_retain(i8* %x)
260   tail call i8* @objc_retain(i8* %x)
261   call void @use_alloca(i8** %A)
262   call void @objc_release(i8* %y), !clang.imprecise_release !0
263   call void @use_pointer(i8* %x)
264   call void @objc_release(i8* %x), !clang.imprecise_release !0
265   ret void
266 }
267
268 ; CHECK: define void @test2c(i8* %x)
269 ; CHECK: @objc_retain(i8* %x)
270 ; CHECK: @objc_retain(i8* %x)
271 ; CHECK: @objc_release(i8* %y)
272 ; CHECK: @objc_release(i8* %x)
273 ; CHECK: ret void
274 ; CHECK: }
275 define void @test2c(i8* %x) {
276 entry:
277   %A = alloca i8*, i32 3
278   %gep1 = getelementptr i8** %A, i32 2
279   store i8* %x, i8** %gep1, align 8
280   %gep2 = getelementptr i8** %A, i32 2
281   %y = load i8** %gep2
282   tail call i8* @objc_retain(i8* %x)
283   br label %bb1
284
285 bb1:
286   br label %bb2
287
288 bb2:
289   br label %bb3
290
291 bb3:
292   tail call i8* @objc_retain(i8* %x)
293   call void @use_alloca(i8** %A)
294   call void @objc_release(i8* %y), !clang.imprecise_release !0
295   call void @use_pointer(i8* %x)
296   call void @objc_release(i8* %x), !clang.imprecise_release !0
297   ret void
298 }
299
300 ; CHECK: define void @test2d(i8* %x)
301 ; CHECK: @objc_retain(i8* %x)
302 ; CHECK: @objc_retain(i8* %x)
303 ; CHECK: @objc_release(i8* %y)
304 ; CHECK: @objc_release(i8* %x)
305 ; CHECK: ret void
306 ; CHECK: }
307 define void @test2d(i8* %x) {
308 entry:
309   tail call i8* @objc_retain(i8* %x)
310   br label %bb1
311
312 bb1:
313   %Abb1 = alloca i8*, i32 3
314   %gepbb11 = getelementptr i8** %Abb1, i32 2
315   store i8* %x, i8** %gepbb11, align 8
316   %gepbb12 = getelementptr i8** %Abb1, i32 2
317   %ybb1 = load i8** %gepbb12
318   br label %bb3
319
320 bb2:
321   %Abb2 = alloca i8*, i32 4
322   %gepbb21 = getelementptr i8** %Abb2, i32 2
323   store i8* %x, i8** %gepbb21, align 8
324   %gepbb22 = getelementptr i8** %Abb2, i32 2
325   %ybb2 = load i8** %gepbb22
326   br label %bb3
327
328 bb3:
329   %A = phi i8** [ %Abb1, %bb1 ], [ %Abb2, %bb2 ]
330   %y = phi i8* [ %ybb1, %bb1 ], [ %ybb2, %bb2 ]
331   tail call i8* @objc_retain(i8* %x)
332   call void @use_alloca(i8** %A)
333   call void @objc_release(i8* %y), !clang.imprecise_release !0
334   call void @use_pointer(i8* %x)
335   call void @objc_release(i8* %x), !clang.imprecise_release !0
336   ret void
337 }
338
339 ; Make sure in the presence of allocas, if we find a cfghazard we do not perform
340 ; code motion even if we are known safe. These two concepts are separate and
341 ; should be treated as such.
342 ;
343 ; rdar://13949644
344
345 ; CHECK: define void @test3a() {
346 ; CHECK: entry:
347 ; CHECK:   @objc_retainAutoreleasedReturnValue
348 ; CHECK:   @objc_retain
349 ; CHECK:   @objc_retain
350 ; CHECK:   @objc_retain
351 ; CHECK:   @objc_retain
352 ; CHECK: arraydestroy.body:
353 ; CHECK:   @objc_release
354 ; CHECK-NOT: @objc_release
355 ; CHECK: arraydestroy.done:
356 ; CHECK-NOT: @objc_release
357 ; CHECK: arraydestroy.body1:
358 ; CHECK:   @objc_release
359 ; CHECK-NOT: @objc_release
360 ; CHECK: arraydestroy.done1:
361 ; CHECK: @objc_release
362 ; CHECK: ret void
363 ; CHECK: }
364 define void @test3a() {
365 entry:
366   %keys = alloca [2 x i8*], align 16
367   %objs = alloca [2 x i8*], align 16
368   
369   %call1 = call i8* @returner()
370   %tmp0 = tail call i8* @objc_retainAutoreleasedReturnValue(i8* %call1)
371
372   %objs.begin = getelementptr inbounds [2 x i8*]* %objs, i64 0, i64 0
373   tail call i8* @objc_retain(i8* %call1)
374   store i8* %call1, i8** %objs.begin, align 8
375   %objs.elt = getelementptr inbounds [2 x i8*]* %objs, i64 0, i64 1
376   tail call i8* @objc_retain(i8* %call1)
377   store i8* %call1, i8** %objs.elt
378
379   %call2 = call i8* @returner1()
380   %call3 = call i8* @returner2()
381   %keys.begin = getelementptr inbounds [2 x i8*]* %keys, i64 0, i64 0
382   tail call i8* @objc_retain(i8* %call2)
383   store i8* %call2, i8** %keys.begin, align 8
384   %keys.elt = getelementptr inbounds [2 x i8*]* %keys, i64 0, i64 1
385   tail call i8* @objc_retain(i8* %call3)
386   store i8* %call3, i8** %keys.elt  
387   
388   %gep = getelementptr inbounds [2 x i8*]* %objs, i64 0, i64 2
389   br label %arraydestroy.body
390
391 arraydestroy.body:
392   %arraydestroy.elementPast = phi i8** [ %gep, %entry ], [ %arraydestroy.element, %arraydestroy.body ]
393   %arraydestroy.element = getelementptr inbounds i8** %arraydestroy.elementPast, i64 -1
394   %destroy_tmp = load i8** %arraydestroy.element, align 8
395   call void @objc_release(i8* %destroy_tmp), !clang.imprecise_release !0
396   %objs_ptr = getelementptr inbounds [2 x i8*]* %objs, i64 0, i64 0
397   %arraydestroy.cmp = icmp eq i8** %arraydestroy.element, %objs_ptr
398   br i1 %arraydestroy.cmp, label %arraydestroy.done, label %arraydestroy.body
399
400 arraydestroy.done:
401   %gep1 = getelementptr inbounds [2 x i8*]* %keys, i64 0, i64 2
402   br label %arraydestroy.body1
403
404 arraydestroy.body1:
405   %arraydestroy.elementPast1 = phi i8** [ %gep1, %arraydestroy.done ], [ %arraydestroy.element1, %arraydestroy.body1 ]
406   %arraydestroy.element1 = getelementptr inbounds i8** %arraydestroy.elementPast1, i64 -1
407   %destroy_tmp1 = load i8** %arraydestroy.element1, align 8
408   call void @objc_release(i8* %destroy_tmp1), !clang.imprecise_release !0
409   %keys_ptr = getelementptr inbounds [2 x i8*]* %keys, i64 0, i64 0
410   %arraydestroy.cmp1 = icmp eq i8** %arraydestroy.element1, %keys_ptr
411   br i1 %arraydestroy.cmp1, label %arraydestroy.done1, label %arraydestroy.body1
412
413 arraydestroy.done1:
414   call void @objc_release(i8* %call1), !clang.imprecise_release !0
415   ret void
416 }
417
418 ; Make sure that even though we stop said code motion we still allow for
419 ; pointers to be removed if we are known safe in both directions.
420 ;
421 ; rdar://13949644
422
423 ; CHECK: define void @test3b() {
424 ; CHECK: entry:
425 ; CHECK:   @objc_retainAutoreleasedReturnValue
426 ; CHECK:   @objc_retain
427 ; CHECK:   @objc_retain
428 ; CHECK:   @objc_retain
429 ; CHECK:   @objc_retain
430 ; CHECK: arraydestroy.body:
431 ; CHECK:   @objc_release
432 ; CHECK-NOT: @objc_release
433 ; CHECK: arraydestroy.done:
434 ; CHECK-NOT: @objc_release
435 ; CHECK: arraydestroy.body1:
436 ; CHECK:   @objc_release
437 ; CHECK-NOT: @objc_release
438 ; CHECK: arraydestroy.done1:
439 ; CHECK: @objc_release
440 ; CHECK: ret void
441 ; CHECK: }
442 define void @test3b() {
443 entry:
444   %keys = alloca [2 x i8*], align 16
445   %objs = alloca [2 x i8*], align 16
446   
447   %call1 = call i8* @returner()
448   %tmp0 = tail call i8* @objc_retainAutoreleasedReturnValue(i8* %call1)
449   %tmp1 = tail call i8* @objc_retain(i8* %call1)
450
451   %objs.begin = getelementptr inbounds [2 x i8*]* %objs, i64 0, i64 0
452   tail call i8* @objc_retain(i8* %call1)
453   store i8* %call1, i8** %objs.begin, align 8
454   %objs.elt = getelementptr inbounds [2 x i8*]* %objs, i64 0, i64 1
455   tail call i8* @objc_retain(i8* %call1)
456   store i8* %call1, i8** %objs.elt
457
458   %call2 = call i8* @returner1()
459   %call3 = call i8* @returner2()
460   %keys.begin = getelementptr inbounds [2 x i8*]* %keys, i64 0, i64 0
461   tail call i8* @objc_retain(i8* %call2)
462   store i8* %call2, i8** %keys.begin, align 8
463   %keys.elt = getelementptr inbounds [2 x i8*]* %keys, i64 0, i64 1
464   tail call i8* @objc_retain(i8* %call3)
465   store i8* %call3, i8** %keys.elt  
466   
467   %gep = getelementptr inbounds [2 x i8*]* %objs, i64 0, i64 2
468   br label %arraydestroy.body
469
470 arraydestroy.body:
471   %arraydestroy.elementPast = phi i8** [ %gep, %entry ], [ %arraydestroy.element, %arraydestroy.body ]
472   %arraydestroy.element = getelementptr inbounds i8** %arraydestroy.elementPast, i64 -1
473   %destroy_tmp = load i8** %arraydestroy.element, align 8
474   call void @objc_release(i8* %destroy_tmp), !clang.imprecise_release !0
475   %objs_ptr = getelementptr inbounds [2 x i8*]* %objs, i64 0, i64 0
476   %arraydestroy.cmp = icmp eq i8** %arraydestroy.element, %objs_ptr
477   br i1 %arraydestroy.cmp, label %arraydestroy.done, label %arraydestroy.body
478
479 arraydestroy.done:
480   %gep1 = getelementptr inbounds [2 x i8*]* %keys, i64 0, i64 2
481   br label %arraydestroy.body1
482
483 arraydestroy.body1:
484   %arraydestroy.elementPast1 = phi i8** [ %gep1, %arraydestroy.done ], [ %arraydestroy.element1, %arraydestroy.body1 ]
485   %arraydestroy.element1 = getelementptr inbounds i8** %arraydestroy.elementPast1, i64 -1
486   %destroy_tmp1 = load i8** %arraydestroy.element1, align 8
487   call void @objc_release(i8* %destroy_tmp1), !clang.imprecise_release !0
488   %keys_ptr = getelementptr inbounds [2 x i8*]* %keys, i64 0, i64 0
489   %arraydestroy.cmp1 = icmp eq i8** %arraydestroy.element1, %keys_ptr
490   br i1 %arraydestroy.cmp1, label %arraydestroy.done1, label %arraydestroy.body1
491
492 arraydestroy.done1:
493   call void @objc_release(i8* %call1), !clang.imprecise_release !0
494   call void @objc_release(i8* %call1), !clang.imprecise_release !0
495   ret void
496 }
497
498 !0 = !{}
499
500 declare i32 @__gxx_personality_v0(...)