[rtsan] Add fork/execve interceptors (#117198)
[llvm-project.git] / llvm / test / Transforms / ObjCARC / basic.ll
blobd461bc0af680d481625e599ac5c6ec61ee5a3642
1 ; RUN: opt -aa-pipeline=basic-aa -passes=objc-arc -S < %s | FileCheck %s
3 target datalayout = "e-p:64:64:64"
5 declare ptr @llvm.objc.retain(ptr)
6 declare ptr @llvm.objc.retainAutoreleasedReturnValue(ptr)
7 declare ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue(ptr)
8 declare void @llvm.objc.release(ptr)
9 declare ptr @llvm.objc.autorelease(ptr)
10 declare ptr @llvm.objc.autoreleaseReturnValue(ptr)
11 declare void @llvm.objc.autoreleasePoolPop(ptr)
12 declare ptr @llvm.objc.autoreleasePoolPush()
13 declare ptr @llvm.objc.retainBlock(ptr)
15 declare ptr @llvm.objc.retainedObject(ptr)
16 declare ptr @llvm.objc.unretainedObject(ptr)
17 declare ptr @llvm.objc.unretainedPointer(ptr)
19 declare void @use_pointer(ptr)
20 declare void @callee()
21 declare void @callee2(ptr, ptr)
22 declare void @callee_fnptr(ptr)
23 declare void @invokee()
24 declare ptr @returner()
25 declare void @bar(ptr)
27 declare void @llvm.dbg.value(metadata, metadata, metadata)
29 declare ptr @objc_msgSend(ptr, ptr, ...)
31 ; Simple retain+release pair deletion, with some intervening control
32 ; flow and harmless instructions.
34 ; CHECK: define void @test0_precise(ptr %x, i1 %p) [[NUW:#[0-9]+]] {
35 ; CHECK: @llvm.objc.retain
36 ; CHECK: @llvm.objc.release
37 ; CHECK: {{^}}}
38 define void @test0_precise(ptr %x, i1 %p) nounwind {
39 entry:
40   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
41   br i1 %p, label %t, label %f
44   store i8 3, ptr %x
45   store float 2.0, ptr %x
46   br label %return
49   store i32 7, ptr %x
50   br label %return
52 return:
53   call void @llvm.objc.release(ptr %x) nounwind
54   ret void
57 ; CHECK: define void @test0_imprecise(ptr %x, i1 %p) [[NUW]] {
58 ; CHECK-NOT: @llvm.objc.
59 ; CHECK: {{^}}}
60 define void @test0_imprecise(ptr %x, i1 %p) nounwind {
61 entry:
62   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
63   br i1 %p, label %t, label %f
66   store i8 3, ptr %x
67   store float 2.0, ptr %x
68   br label %return
71   store i32 7, ptr %x
72   br label %return
74 return:
75   call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
76   ret void
79 ; Like test0 but the release isn't always executed when the retain is,
80 ; so the optimization is not safe.
82 ; TODO: Make the llvm.objc.release's argument be %0.
84 ; CHECK: define void @test1_precise(ptr %x, i1 %p, i1 %q) [[NUW]] {
85 ; CHECK: @llvm.objc.retain(ptr %x)
86 ; CHECK: @llvm.objc.release(ptr %x)
87 ; CHECK: {{^}}}
88 define void @test1_precise(ptr %x, i1 %p, i1 %q) nounwind {
89 entry:
90   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
91   br i1 %p, label %t, label %f
94   store i8 3, ptr %x
95   store float 2.0, ptr %x
96   br label %return
99   store i32 7, ptr %x
100   call void @callee()
101   br i1 %q, label %return, label %alt_return
103 return:
104   call void @llvm.objc.release(ptr %x) nounwind
105   ret void
107 alt_return:
108   ret void
111 ; CHECK: define void @test1_imprecise(ptr %x, i1 %p, i1 %q) [[NUW]] {
112 ; CHECK: @llvm.objc.retain(ptr %x)
113 ; CHECK: @llvm.objc.release
114 ; CHECK: {{^}}}
115 define void @test1_imprecise(ptr %x, i1 %p, i1 %q) nounwind {
116 entry:
117   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
118   br i1 %p, label %t, label %f
121   store i8 3, ptr %x
122   store float 2.0, ptr %x
123   br label %return
126   store i32 7, ptr %x
127   call void @callee()
128   br i1 %q, label %return, label %alt_return
130 return:
131   call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
132   ret void
134 alt_return:
135   ret void
139 ; Don't do partial elimination into two different CFG diamonds.
141 ; CHECK: define void @test1b_precise(ptr %x, i1 %p, i1 %q) {
142 ; CHECK: entry:
143 ; CHECK:   tail call ptr @llvm.objc.retain(ptr %x) [[NUW]]
144 ; CHECK-NOT: @llvm.objc.
145 ; CHECK: if.end5:
146 ; CHECK:   tail call void @llvm.objc.release(ptr %x) [[NUW]]
147 ; CHECK-NOT: @llvm.objc.
148 ; CHECK: {{^}}}
149 define void @test1b_precise(ptr %x, i1 %p, i1 %q) {
150 entry:
151   tail call ptr @llvm.objc.retain(ptr %x) nounwind
152   br i1 %p, label %if.then, label %if.end
154 if.then:                                          ; preds = %entry
155   tail call void @callee()
156   br label %if.end
158 if.end:                                           ; preds = %if.then, %entry
159   br i1 %q, label %if.then3, label %if.end5
161 if.then3:                                         ; preds = %if.end
162   tail call void @use_pointer(ptr %x)
163   br label %if.end5
165 if.end5:                                          ; preds = %if.then3, %if.end
166   tail call void @llvm.objc.release(ptr %x) nounwind
167   ret void
170 ; CHECK-LABEL: define void @test1b_imprecise(
171 ; CHECK: entry:
172 ; CHECK:   tail call ptr @llvm.objc.retain(ptr %x) [[NUW:#[0-9]+]]
173 ; CHECK-NOT: @llvm.objc.
174 ; CHECK: if.end5:
175 ; CHECK:   tail call void @llvm.objc.release(ptr %x) [[NUW]], !clang.imprecise_release ![[RELEASE:[0-9]+]]
176 ; CHECK-NOT: @llvm.objc.
177 ; CHECK: {{^}}}
178 define void @test1b_imprecise(ptr %x, i1 %p, i1 %q) {
179 entry:
180   tail call ptr @llvm.objc.retain(ptr %x) nounwind
181   br i1 %p, label %if.then, label %if.end
183 if.then:                                          ; preds = %entry
184   tail call void @callee()
185   br label %if.end
187 if.end:                                           ; preds = %if.then, %entry
188   br i1 %q, label %if.then3, label %if.end5
190 if.then3:                                         ; preds = %if.end
191   tail call void @use_pointer(ptr %x)
192   br label %if.end5
194 if.end5:                                          ; preds = %if.then3, %if.end
195   tail call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
196   ret void
200 ; Like test0 but the pointer is passed to an intervening call,
201 ; so the optimization is not safe.
203 ; CHECK-LABEL: define void @test2_precise(
204 ; CHECK: @llvm.objc.retain(ptr %x)
205 ; CHECK: @llvm.objc.release
206 ; CHECK: {{^}}}
207 define void @test2_precise(ptr %x, i1 %p) nounwind {
208 entry:
209   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
210   br i1 %p, label %t, label %f
213   store i8 3, ptr %x
214   store float 2.0, ptr %x
215   br label %return
218   store i32 7, ptr %x
219   call void @use_pointer(ptr %0)
220   store float 3.0, ptr %x
221   br label %return
223 return:
224   call void @llvm.objc.release(ptr %x) nounwind
225   ret void
228 ; CHECK-LABEL: define void @test2_imprecise(
229 ; CHECK: @llvm.objc.retain(ptr %x)
230 ; CHECK: @llvm.objc.release
231 ; CHECK: {{^}}}
232 define void @test2_imprecise(ptr %x, i1 %p) nounwind {
233 entry:
234   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
235   br i1 %p, label %t, label %f
238   store i8 3, ptr %x
239   store float 2.0, ptr %x
240   br label %return
243   store i32 7, ptr %x
244   call void @use_pointer(ptr %0)
245   store float 3.0, ptr %x
246   br label %return
248 return:
249   call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
250   ret void
253 ; Like test0 but the release is in a loop,
254 ; so the optimization is not safe.
256 ; TODO: For now, assume this can't happen.
258 ; CHECK-LABEL: define void @test3_precise(
259 ; TODO: @llvm.objc.retain(ptr %a)
260 ; TODO: @llvm.objc.release
261 ; CHECK: {{^}}}
262 define void @test3_precise(ptr %x, ptr %q) nounwind {
263 entry:
264   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
265   br label %loop
267 loop:
268   call void @llvm.objc.release(ptr %x) nounwind
269   %j = load volatile i1, ptr %q
270   br i1 %j, label %loop, label %return
272 return:
273   ret void
276 ; CHECK-LABEL: define void @test3_imprecise(
277 ; TODO: @llvm.objc.retain(ptr %a)
278 ; TODO: @llvm.objc.release
279 ; CHECK: {{^}}}
280 define void @test3_imprecise(ptr %x, ptr %q) nounwind {
281 entry:
282   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
283   br label %loop
285 loop:
286   call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
287   %j = load volatile i1, ptr %q
288   br i1 %j, label %loop, label %return
290 return:
291   ret void
295 ; TODO: For now, assume this can't happen.
297 ; Like test0 but the retain is in a loop,
298 ; so the optimization is not safe.
300 ; CHECK-LABEL: define void @test4_precise(
301 ; TODO: @llvm.objc.retain(ptr %a)
302 ; TODO: @llvm.objc.release
303 ; CHECK: {{^}}}
304 define void @test4_precise(ptr %x, ptr %q) nounwind {
305 entry:
306   br label %loop
308 loop:
309   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
310   %j = load volatile i1, ptr %q
311   br i1 %j, label %loop, label %return
313 return:
314   call void @llvm.objc.release(ptr %x) nounwind
315   ret void
318 ; CHECK-LABEL: define void @test4_imprecise(
319 ; TODO: @llvm.objc.retain(ptr %a)
320 ; TODO: @llvm.objc.release
321 ; CHECK: {{^}}}
322 define void @test4_imprecise(ptr %x, ptr %q) nounwind {
323 entry:
324   br label %loop
326 loop:
327   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
328   %j = load volatile i1, ptr %q
329   br i1 %j, label %loop, label %return
331 return:
332   call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
333   ret void
337 ; Like test0 but the pointer is conditionally passed to an intervening call,
338 ; so the optimization is not safe.
340 ; CHECK-LABEL: define void @test5a(
341 ; CHECK: @llvm.objc.retain(ptr
342 ; CHECK: @llvm.objc.release
343 ; CHECK: {{^}}}
344 define void @test5a(ptr %x, i1 %q, ptr %y) nounwind {
345 entry:
346   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
347   %s = select i1 %q, ptr %y, ptr %0
348   call void @use_pointer(ptr %s)
349   store i32 7, ptr %x
350   call void @llvm.objc.release(ptr %x) nounwind
351   ret void
354 ; CHECK-LABEL: define void @test5b(
355 ; CHECK: @llvm.objc.retain(ptr
356 ; CHECK: @llvm.objc.release
357 ; CHECK: {{^}}}
358 define void @test5b(ptr %x, i1 %q, ptr %y) nounwind {
359 entry:
360   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
361   %s = select i1 %q, ptr %y, ptr %0
362   call void @use_pointer(ptr %s)
363   store i32 7, ptr %x
364   call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
365   ret void
369 ; retain+release pair deletion, where the release happens on two different
370 ; flow paths.
372 ; CHECK-LABEL: define void @test6a(
373 ; CHECK: entry:
374 ; CHECK:   tail call ptr @llvm.objc.retain
375 ; CHECK: t:
376 ; CHECK:   call void @llvm.objc.release
377 ; CHECK: f:
378 ; CHECK:   call void @llvm.objc.release
379 ; CHECK: return:
380 ; CHECK: {{^}}}
381 define void @test6a(ptr %x, i1 %p) nounwind {
382 entry:
383   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
384   br i1 %p, label %t, label %f
387   store i8 3, ptr %x
388   store float 2.0, ptr %x
389   call void @llvm.objc.release(ptr %x) nounwind
390   br label %return
393   store i32 7, ptr %x
394   call void @callee()
395   call void @llvm.objc.release(ptr %x) nounwind
396   br label %return
398 return:
399   ret void
402 ; CHECK-LABEL: define void @test6b(
403 ; CHECK-NOT: @llvm.objc.
404 ; CHECK: {{^}}}
405 define void @test6b(ptr %x, i1 %p) nounwind {
406 entry:
407   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
408   br i1 %p, label %t, label %f
411   store i8 3, ptr %x
412   store float 2.0, ptr %x
413   call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
414   br label %return
417   store i32 7, ptr %x
418   call void @callee()
419   call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
420   br label %return
422 return:
423   ret void
426 ; CHECK-LABEL: define void @test6c(
427 ; CHECK: entry:
428 ; CHECK:   tail call ptr @llvm.objc.retain
429 ; CHECK: t:
430 ; CHECK:   call void @llvm.objc.release
431 ; CHECK: f:
432 ; CHECK:   call void @llvm.objc.release
433 ; CHECK: return:
434 ; CHECK: {{^}}}
435 define void @test6c(ptr %x, i1 %p) nounwind {
436 entry:
437   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
438   br i1 %p, label %t, label %f
441   store i8 3, ptr %x
442   store float 2.0, ptr %x
443   call void @llvm.objc.release(ptr %x) nounwind
444   br label %return
447   store i32 7, ptr %x
448   call void @callee()
449   call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
450   br label %return
452 return:
453   ret void
456 ; CHECK-LABEL: define void @test6d(
457 ; CHECK: entry:
458 ; CHECK:   tail call ptr @llvm.objc.retain
459 ; CHECK: t:
460 ; CHECK:   call void @llvm.objc.release
461 ; CHECK: f:
462 ; CHECK:   call void @llvm.objc.release
463 ; CHECK: return:
464 ; CHECK: {{^}}}
465 define void @test6d(ptr %x, i1 %p) nounwind {
466 entry:
467   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
468   br i1 %p, label %t, label %f
471   store i8 3, ptr %x
472   store float 2.0, ptr %x
473   call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
474   br label %return
477   store i32 7, ptr %x
478   call void @callee()
479   call void @llvm.objc.release(ptr %x) nounwind
480   br label %return
482 return:
483   ret void
487 ; retain+release pair deletion, where the retain happens on two different
488 ; flow paths.
490 ; CHECK-LABEL:     define void @test7(
491 ; CHECK:     entry:
492 ; CHECK-NOT:   llvm.objc.
493 ; CHECK:     t:
494 ; CHECK:       call ptr @llvm.objc.retain
495 ; CHECK:     f:
496 ; CHECK:       call ptr @llvm.objc.retain
497 ; CHECK:     return:
498 ; CHECK:       call void @llvm.objc.release
499 ; CHECK: {{^}}}
500 define void @test7(ptr %x, i1 %p) nounwind {
501 entry:
502   br i1 %p, label %t, label %f
505   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
506   store i8 3, ptr %x
507   store float 2.0, ptr %x
508   br label %return
511   %1 = call ptr @llvm.objc.retain(ptr %x) nounwind
512   store i32 7, ptr %x
513   call void @callee()
514   br label %return
516 return:
517   call void @llvm.objc.release(ptr %x) nounwind
518   ret void
521 ; CHECK-LABEL: define void @test7b(
522 ; CHECK-NOT: @llvm.objc.
523 ; CHECK: {{^}}}
524 define void @test7b(ptr %x, i1 %p) nounwind {
525 entry:
526   br i1 %p, label %t, label %f
529   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
530   store i8 3, ptr %x
531   store float 2.0, ptr %x
532   br label %return
535   %1 = call ptr @llvm.objc.retain(ptr %x) nounwind
536   store i32 7, ptr %x
537   call void @callee()
538   br label %return
540 return:
541   call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
542   ret void
545 ; Like test7, but there's a retain/retainBlock mismatch. Don't delete!
547 ; CHECK-LABEL: define void @test7c(
548 ; CHECK: t:
549 ; CHECK:   call ptr @llvm.objc.retainBlock
550 ; CHECK: f:
551 ; CHECK:   call ptr @llvm.objc.retain
552 ; CHECK: return:
553 ; CHECK:   call void @llvm.objc.release
554 ; CHECK: {{^}}}
555 define void @test7c(ptr %x, i1 %p) nounwind {
556 entry:
557   br i1 %p, label %t, label %f
560   %0 = call ptr @llvm.objc.retainBlock(ptr %x) nounwind
561   store i8 3, ptr %x
562   store float 2.0, ptr %x
563   br label %return
566   %1 = call ptr @llvm.objc.retain(ptr %x) nounwind
567   store i32 7, ptr %x
568   call void @callee()
569   br label %return
571 return:
572   call void @llvm.objc.release(ptr %x) nounwind
573   ret void
576 ; retain+release pair deletion, where the retain and release both happen on
577 ; different flow paths. Wild!
579 ; CHECK-LABEL: define void @test8a(
580 ; CHECK: entry:
581 ; CHECK: t:
582 ; CHECK:   @llvm.objc.retain
583 ; CHECK: f:
584 ; CHECK:   @llvm.objc.retain
585 ; CHECK: mid:
586 ; CHECK: u:
587 ; CHECK:   @llvm.objc.release
588 ; CHECK: g:
589 ; CHECK:   @llvm.objc.release
590 ; CHECK: return:
591 ; CHECK: {{^}}}
592 define void @test8a(ptr %x, i1 %p, i1 %q) nounwind {
593 entry:
594   br i1 %p, label %t, label %f
597   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
598   store i8 3, ptr %x
599   store float 2.0, ptr %x
600   br label %mid
603   %1 = call ptr @llvm.objc.retain(ptr %x) nounwind
604   store i32 7, ptr %x
605   br label %mid
607 mid:
608   br i1 %q, label %u, label %g
611   call void @callee()
612   call void @llvm.objc.release(ptr %x) nounwind
613   br label %return
616   call void @llvm.objc.release(ptr %x) nounwind
617   br label %return
619 return:
620   ret void
623 ; CHECK-LABEL: define void @test8b(
624 ; CHECK-NOT: @llvm.objc.
625 ; CHECK: {{^}}}
626 define void @test8b(ptr %x, i1 %p, i1 %q) nounwind {
627 entry:
628   br i1 %p, label %t, label %f
631   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
632   store i8 3, ptr %x
633   store float 2.0, ptr %x
634   br label %mid
637   %1 = call ptr @llvm.objc.retain(ptr %x) nounwind
638   store i32 7, ptr %x
639   br label %mid
641 mid:
642   br i1 %q, label %u, label %g
645   call void @callee()
646   call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
647   br label %return
650   call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
651   br label %return
653 return:
654   ret void
657 ; CHECK-LABEL: define void @test8c(
658 ; CHECK: entry:
659 ; CHECK: t:
660 ; CHECK-NOT: @llvm.objc.
661 ; CHECK: f:
662 ; CHECK-NOT: @llvm.objc.
663 ; CHECK: mid:
664 ; CHECK: u:
665 ; CHECK:   @llvm.objc.retain
666 ; CHECK:   @llvm.objc.release
667 ; CHECK: g:
668 ; CHECK-NOT: @llvm.objc.
669 ; CHECK: return:
670 ; CHECK: {{^}}}
671 define void @test8c(ptr %x, i1 %p, i1 %q) nounwind {
672 entry:
673   br i1 %p, label %t, label %f
676   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
677   store i8 3, ptr %x
678   store float 2.0, ptr %x
679   br label %mid
682   %1 = call ptr @llvm.objc.retain(ptr %x) nounwind
683   store i32 7, ptr %x
684   br label %mid
686 mid:
687   br i1 %q, label %u, label %g
690   call void @callee()
691   call void @llvm.objc.release(ptr %x) nounwind
692   br label %return
695   call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
696   br label %return
698 return:
699   ret void
702 ; CHECK-LABEL: define void @test8d(
703 ; CHECK: entry:
704 ; CHECK: t:
705 ; CHECK:   @llvm.objc.retain
706 ; CHECK: f:
707 ; CHECK:   @llvm.objc.retain
708 ; CHECK: mid:
709 ; CHECK: u:
710 ; CHECK:   @llvm.objc.release
711 ; CHECK: g:
712 ; CHECK:   @llvm.objc.release
713 ; CHECK: return:
714 ; CHECK: {{^}}}
715 define void @test8d(ptr %x, i1 %p, i1 %q) nounwind {
716 entry:
717   br i1 %p, label %t, label %f
720   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
721   store i8 3, ptr %x
722   store float 2.0, ptr %x
723   br label %mid
726   %1 = call ptr @llvm.objc.retain(ptr %x) nounwind
727   store i32 7, ptr %x
728   br label %mid
730 mid:
731   br i1 %q, label %u, label %g
734   call void @callee()
735   call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
736   br label %return
739   call void @llvm.objc.release(ptr %x) nounwind
740   br label %return
742 return:
743   ret void
746 ; Trivial retain+release pair deletion.
748 ; CHECK-LABEL: define void @test9(
749 ; CHECK-NOT: @llvm.objc.
750 ; CHECK: {{^}}}
751 define void @test9(ptr %x) nounwind {
752 entry:
753   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
754   call void @llvm.objc.release(ptr %0) nounwind
755   ret void
758 ; Retain+release pair, but on an unknown pointer relationship. Don't delete!
760 ; CHECK-LABEL: define void @test9b(
761 ; CHECK: @llvm.objc.retain(ptr %x)
762 ; CHECK: @llvm.objc.release(ptr %s)
763 ; CHECK: {{^}}}
764 define void @test9b(ptr %x, i1 %j, ptr %p) nounwind {
765 entry:
766   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
767   %s = select i1 %j, ptr %x, ptr %p
768   call void @llvm.objc.release(ptr %s) nounwind
769   ret void
772 ; Trivial retain+release pair with intervening calls - don't delete!
774 ; CHECK-LABEL: define void @test10(
775 ; CHECK: @llvm.objc.retain(ptr %x)
776 ; CHECK: @callee
777 ; CHECK: @use_pointer
778 ; CHECK: @llvm.objc.release
779 ; CHECK: {{^}}}
780 define void @test10(ptr %x) nounwind {
781 entry:
782   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
783   call void @callee()
784   call void @use_pointer(ptr %x)
785   call void @llvm.objc.release(ptr %0) nounwind
786   ret void
789 ; Trivial retain+autoreleaserelease pair. Don't delete!
790 ; Also, add a tail keyword, since llvm.objc.retain can never be passed
791 ; a stack argument.
793 ; CHECK-LABEL: define void @test11(
794 ; CHECK: tail call ptr @llvm.objc.retain(ptr %x) [[NUW]]
795 ; CHECK: call ptr @llvm.objc.autorelease(ptr %0) [[NUW]]
796 ; CHECK: {{^}}}
797 define void @test11(ptr %x) nounwind {
798 entry:
799   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
800   call ptr @llvm.objc.autorelease(ptr %0) nounwind
801   call void @use_pointer(ptr %x)
802   ret void
805 ; Same as test11 but with no use_pointer call. Delete the pair!
807 ; CHECK-LABEL: define void @test11a(
808 ; CHECK: entry:
809 ; CHECK-NEXT: ret void
810 ; CHECK: {{^}}}
811 define void @test11a(ptr %x) nounwind {
812 entry:
813   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
814   call ptr @llvm.objc.autorelease(ptr %0) nounwind
815   ret void
818 ; Same as test11 but the value is returned. Do not perform an RV optimization
819 ; since if the frontend emitted code for an __autoreleasing variable, we may
820 ; want it to be in the autorelease pool.
822 ; CHECK-LABEL: define ptr @test11b(
823 ; CHECK: tail call ptr @llvm.objc.retain(ptr %x) [[NUW]]
824 ; CHECK: call ptr @llvm.objc.autorelease(ptr %0) [[NUW]]
825 ; CHECK: {{^}}}
826 define ptr @test11b(ptr %x) nounwind {
827 entry:
828   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
829   call ptr @llvm.objc.autorelease(ptr %0) nounwind
830   ret ptr %x
833 ; We can not delete this retain, release since we do not have a post-dominating
834 ; use of the release.
836 ; CHECK-LABEL: define void @test12(
837 ; CHECK-NEXT: entry:
838 ; CHECK-NEXT: @llvm.objc.retain(ptr %x)
839 ; CHECK-NEXT: @llvm.objc.retain
840 ; CHECK: @llvm.objc.release
841 ; CHECK: {{^}}}
842 define void @test12(ptr %x, i64 %n) {
843 entry:
844   call ptr @llvm.objc.retain(ptr %x) nounwind
845   call ptr @llvm.objc.retain(ptr %x) nounwind
846   call void @use_pointer(ptr %x)
847   call void @use_pointer(ptr %x)
848   call void @llvm.objc.release(ptr %x) nounwind
849   ret void
852 ; Trivial retain,autorelease pair. Don't delete!
854 ; CHECK-LABEL: define void @test13(
855 ; CHECK: tail call ptr @llvm.objc.retain(ptr %x) [[NUW]]
856 ; CHECK: tail call ptr @llvm.objc.retain(ptr %x) [[NUW]]
857 ; CHECK: @use_pointer(ptr %x)
858 ; CHECK: call ptr @llvm.objc.autorelease(ptr %x) [[NUW]]
859 ; CHECK: {{^}}}
860 define void @test13(ptr %x, i64 %n) {
861 entry:
862   call ptr @llvm.objc.retain(ptr %x) nounwind
863   call ptr @llvm.objc.retain(ptr %x) nounwind
864   call void @use_pointer(ptr %x)
865   call ptr @llvm.objc.autorelease(ptr %x) nounwind
866   ret void
869 ; Delete the retain+release pair.
871 ; CHECK-LABEL: define void @test13b(
872 ; CHECK-NEXT: entry:
873 ; CHECK-NEXT: @llvm.objc.retain(ptr %x)
874 ; CHECK-NEXT: @use_pointer
875 ; CHECK-NEXT: @use_pointer
876 ; CHECK-NEXT: @use_pointer
877 ; CHECK-NEXT: @llvm.objc.release
878 ; CHECK-NEXT: ret void
879 ; CHECK-NEXT: }
880 define void @test13b(ptr %x, i64 %n) {
881 entry:
882   call ptr @llvm.objc.retain(ptr %x) nounwind
883   call ptr @llvm.objc.retain(ptr %x) nounwind
884   call void @use_pointer(ptr %x)
885   call void @use_pointer(ptr %x)
886   call void @llvm.objc.release(ptr %x) nounwind
887   call void @use_pointer(ptr %x)
888   call void @llvm.objc.release(ptr %x) nounwind
889   ret void
892 ; Don't delete the retain+release pair because there's an
893 ; autoreleasePoolPop in the way.
895 ; CHECK-LABEL: define void @test13c(
896 ; CHECK: @llvm.objc.retain(ptr %x)
897 ; CHECK: @llvm.objc.autoreleasePoolPop
898 ; CHECK: @llvm.objc.retain(ptr %x)
899 ; CHECK: @use_pointer
900 ; CHECK: @llvm.objc.release
901 ; CHECK: {{^}}}
902 define void @test13c(ptr %x, i64 %n) {
903 entry:
904   call ptr @llvm.objc.retain(ptr %x) nounwind
905   call void @llvm.objc.autoreleasePoolPop(ptr undef)
906   call ptr @llvm.objc.retain(ptr %x) nounwind
907   call void @use_pointer(ptr %x)
908   call void @use_pointer(ptr %x)
909   call void @llvm.objc.release(ptr %x) nounwind
910   ret void
913 ; Like test13c, but there's an autoreleasePoolPush in the way, but that
914 ; doesn't matter.
916 ; CHECK-LABEL: define void @test13d(
917 ; CHECK-NEXT: entry:
918 ; CHECK-NEXT: @llvm.objc.retain(ptr %x)
919 ; CHECK-NEXT: @llvm.objc.autoreleasePoolPush
920 ; CHECK-NEXT: @use_pointer
921 ; CHECK-NEXT: @use_pointer
922 ; CHECK-NEXT: @use_pointer
923 ; CHECK-NEXT: @llvm.objc.release
924 ; CHECK-NEXT: ret void
925 ; CHECK-NEXT: }
926 define void @test13d(ptr %x, i64 %n) {
927 entry:
928   call ptr @llvm.objc.retain(ptr %x) nounwind
929   call ptr @llvm.objc.autoreleasePoolPush()
930   call ptr @llvm.objc.retain(ptr %x) nounwind
931   call void @use_pointer(ptr %x)
932   call void @use_pointer(ptr %x)
933   call void @llvm.objc.release(ptr %x) nounwind
934   call void @use_pointer(ptr %x)
935   call void @llvm.objc.release(ptr %x) nounwind
936   ret void
939 ; Trivial retain,release pair with intervening call, and it's post-dominated by
940 ; another release. But it is not known safe in the top down direction. We can
941 ; not eliminate it.
943 ; CHECK-LABEL: define void @test14(
944 ; CHECK-NEXT: entry:
945 ; CHECK-NEXT: @llvm.objc.retain
946 ; CHECK-NEXT: @use_pointer
947 ; CHECK-NEXT: @use_pointer
948 ; CHECK-NEXT: @llvm.objc.release
949 ; CHECK-NEXT: @llvm.objc.release
950 ; CHECK-NEXT: ret void
951 ; CHECK-NEXT: }
952 define void @test14(ptr %x, i64 %n) {
953 entry:
954   call ptr @llvm.objc.retain(ptr %x) nounwind
955   call void @use_pointer(ptr %x)
956   call void @use_pointer(ptr %x)
957   call void @llvm.objc.release(ptr %x) nounwind
958   call void @llvm.objc.release(ptr %x) nounwind
959   ret void
962 ; Trivial retain,autorelease pair with intervening call, but it's post-dominated
963 ; by another release. Don't delete anything.
965 ; CHECK-LABEL: define void @test15(
966 ; CHECK-NEXT: entry:
967 ; CHECK-NEXT: @llvm.objc.retain(ptr %x)
968 ; CHECK-NEXT: @use_pointer
969 ; CHECK-NEXT: @llvm.objc.autorelease(ptr %x)
970 ; CHECK-NEXT: @llvm.objc.release
971 ; CHECK-NEXT: ret void
972 ; CHECK-NEXT: }
973 define void @test15(ptr %x, i64 %n) {
974 entry:
975   call ptr @llvm.objc.retain(ptr %x) nounwind
976   call void @use_pointer(ptr %x)
977   call ptr @llvm.objc.autorelease(ptr %x) nounwind
978   call void @llvm.objc.release(ptr %x) nounwind
979   ret void
982 ; Trivial retain,autorelease pair, post-dominated
983 ; by another release. Delete the retain and release.
985 ; CHECK-LABEL: define void @test15b(
986 ; CHECK-NEXT: entry:
987 ; CHECK-NEXT: @llvm.objc.retain
988 ; CHECK-NEXT: @llvm.objc.autorelease
989 ; CHECK-NEXT: @llvm.objc.release
990 ; CHECK-NEXT: ret void
991 ; CHECK-NEXT: }
992 define void @test15b(ptr %x, i64 %n) {
993 entry:
994   call ptr @llvm.objc.retain(ptr %x) nounwind
995   call ptr @llvm.objc.autorelease(ptr %x) nounwind
996   call void @llvm.objc.release(ptr %x) nounwind
997   ret void
1000 ; CHECK-LABEL: define void @test15c(
1001 ; CHECK-NEXT: entry:
1002 ; CHECK-NEXT: @llvm.objc.autorelease
1003 ; CHECK-NEXT: ret void
1004 ; CHECK-NEXT: }
1005 define void @test15c(ptr %x, i64 %n) {
1006 entry:
1007   call ptr @llvm.objc.retain(ptr %x) nounwind
1008   call ptr @llvm.objc.autorelease(ptr %x) nounwind
1009   call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
1010   ret void
1013 ; Retain+release pairs in diamonds, all dominated by a retain.
1015 ; CHECK-LABEL: define void @test16a(
1016 ; CHECK: @llvm.objc.retain(ptr %x)
1017 ; CHECK-NOT: @objc
1018 ; CHECK: purple:
1019 ; CHECK: @use_pointer
1020 ; CHECK: @llvm.objc.release
1021 ; CHECK: {{^}}}
1022 define void @test16a(i1 %a, i1 %b, ptr %x) {
1023 entry:
1024   call ptr @llvm.objc.retain(ptr %x) nounwind
1025   br i1 %a, label %red, label %orange
1027 red:
1028   call ptr @llvm.objc.retain(ptr %x) nounwind
1029   br label %yellow
1031 orange:
1032   call ptr @llvm.objc.retain(ptr %x) nounwind
1033   br label %yellow
1035 yellow:
1036   call void @use_pointer(ptr %x)
1037   call void @use_pointer(ptr %x)
1038   br i1 %b, label %green, label %blue
1040 green:
1041   call void @llvm.objc.release(ptr %x) nounwind
1042   br label %purple
1044 blue:
1045   call void @llvm.objc.release(ptr %x) nounwind
1046   br label %purple
1048 purple:
1049   call void @use_pointer(ptr %x)
1050   call void @llvm.objc.release(ptr %x) nounwind
1051   ret void
1054 ; CHECK-LABEL: define void @test16b(
1055 ; CHECK: @llvm.objc.retain(ptr %x)
1056 ; CHECK-NOT: @objc
1057 ; CHECK: purple:
1058 ; CHECK-NEXT: @use_pointer
1059 ; CHECK-NEXT: @use_pointer
1060 ; CHECK-NEXT: @llvm.objc.release
1061 ; CHECK: {{^}}}
1062 define void @test16b(i1 %a, i1 %b, ptr %x) {
1063 entry:
1064   call ptr @llvm.objc.retain(ptr %x) nounwind
1065   br i1 %a, label %red, label %orange
1067 red:
1068   call ptr @llvm.objc.retain(ptr %x) nounwind
1069   br label %yellow
1071 orange:
1072   call ptr @llvm.objc.retain(ptr %x) nounwind
1073   br label %yellow
1075 yellow:
1076   call void @use_pointer(ptr %x)
1077   call void @use_pointer(ptr %x)
1078   br i1 %b, label %green, label %blue
1080 green:
1081   call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
1082   br label %purple
1084 blue:
1085   call void @llvm.objc.release(ptr %x) nounwind
1086   br label %purple
1088 purple:
1089   call void @use_pointer(ptr %x)
1090   call void @use_pointer(ptr %x)
1091   call void @llvm.objc.release(ptr %x) nounwind
1092   ret void
1095 ; CHECK-LABEL: define void @test16c(
1096 ; CHECK: @llvm.objc.retain(ptr %x)
1097 ; CHECK-NOT: @objc
1098 ; CHECK: purple:
1099 ; CHECK: @use_pointer
1100 ; CHECK: @llvm.objc.release
1101 ; CHECK: {{^}}}
1102 define void @test16c(i1 %a, i1 %b, ptr %x) {
1103 entry:
1104   call ptr @llvm.objc.retain(ptr %x) nounwind
1105   br i1 %a, label %red, label %orange
1107 red:
1108   call ptr @llvm.objc.retain(ptr %x) nounwind
1109   br label %yellow
1111 orange:
1112   call ptr @llvm.objc.retain(ptr %x) nounwind
1113   br label %yellow
1115 yellow:
1116   call void @use_pointer(ptr %x)
1117   call void @use_pointer(ptr %x)
1118   br i1 %b, label %green, label %blue
1120 green:
1121   call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
1122   br label %purple
1124 blue:
1125   call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
1126   br label %purple
1128 purple:
1129   call void @use_pointer(ptr %x)
1130   call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
1131   ret void
1134 ; CHECK-LABEL: define void @test16d(
1135 ; CHECK: @llvm.objc.retain(ptr %x)
1136 ; CHECK: @llvm.objc
1137 ; CHECK: {{^}}}
1138 define void @test16d(i1 %a, i1 %b, ptr %x) {
1139 entry:
1140   call ptr @llvm.objc.retain(ptr %x) nounwind
1141   br i1 %a, label %red, label %orange
1143 red:
1144   call ptr @llvm.objc.retain(ptr %x) nounwind
1145   br label %yellow
1147 orange:
1148   call ptr @llvm.objc.retain(ptr %x) nounwind
1149   br label %yellow
1151 yellow:
1152   call void @use_pointer(ptr %x)
1153   call void @use_pointer(ptr %x)
1154   br i1 %b, label %green, label %blue
1156 green:
1157   call void @llvm.objc.release(ptr %x) nounwind
1158   br label %purple
1160 blue:
1161   call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
1162   br label %purple
1164 purple:
1165   ret void
1168 ; Delete no-ops.
1170 ; CHECK-LABEL: define void @test18(
1171 ; CHECK-NOT: @llvm.objc.
1172 ; CHECK: {{^}}}
1173 define void @test18() {
1174   call ptr @llvm.objc.retain(ptr null)
1175   call void @llvm.objc.release(ptr null)
1176   call ptr @llvm.objc.autorelease(ptr null)
1177   ret void
1180 ; Delete no-ops where undef can be assumed to be null.
1182 ; CHECK-LABEL: define void @test18b(
1183 ; CHECK-NOT: @llvm.objc.
1184 ; CHECK: {{^}}}
1185 define void @test18b() {
1186   call ptr @llvm.objc.retain(ptr undef)
1187   call void @llvm.objc.release(ptr undef)
1188   call ptr @llvm.objc.autorelease(ptr undef)
1189   ret void
1192 ; Replace uses of arguments with uses of return values, to reduce
1193 ; register pressure.
1195 ; CHECK: define void @test19(ptr %y) {
1196 ; CHECK:   %0 = tail call ptr @llvm.objc.retain(ptr %y)
1197 ; CHECK:   call void @use_pointer(ptr %y)
1198 ; CHECK:   call void @use_pointer(ptr %y)
1199 ; CHECK:   call void @llvm.objc.release(ptr %y)
1200 ; CHECK:   ret void
1201 ; CHECK: {{^}}}
1202 define void @test19(ptr %y) {
1203 entry:
1204   %0 = call ptr @llvm.objc.retain(ptr %y) nounwind
1205   call void @use_pointer(ptr %y)
1206   call void @use_pointer(ptr %y)
1207   call void @llvm.objc.release(ptr %y)
1208   ret void
1211 ; Bitcast insertion
1213 ; CHECK-LABEL: define void @test20(
1214 ; CHECK: %tmp1 = tail call ptr @llvm.objc.retain(ptr %self) [[NUW]]
1215 ; CHECK-NEXT: invoke
1216 ; CHECK: {{^}}}
1217 define void @test20(ptr %self) personality ptr @__gxx_personality_v0 {
1218 if.then12:
1219   %tmp1 = call ptr @llvm.objc.retain(ptr %self) nounwind
1220   invoke void @invokee()
1221           to label %invoke.cont23 unwind label %lpad20
1223 invoke.cont23:                                    ; preds = %if.then12
1224   invoke void @invokee()
1225           to label %if.end unwind label %lpad20
1227 lpad20:                                           ; preds = %invoke.cont23, %if.then12
1228   %tmp502 = phi ptr [ undef, %invoke.cont23 ], [ %self, %if.then12 ]
1229   %exn = landingpad {ptr, i32}
1230            cleanup
1231   unreachable
1233 if.end:                                           ; preds = %invoke.cont23
1234   ret void
1237 ; Delete a redundant retain,autorelease when forwaring a call result
1238 ; directly to a return value.
1240 ; CHECK-LABEL: define ptr @test21(
1241 ; CHECK: call ptr @returner()
1242 ; CHECK-NEXT: ret ptr %call
1243 ; CHECK-NEXT: }
1244 define ptr @test21() {
1245 entry:
1246   %call = call ptr @returner()
1247   %0 = call ptr @llvm.objc.retain(ptr %call) nounwind
1248   %1 = call ptr @llvm.objc.autorelease(ptr %0) nounwind
1249   ret ptr %1
1252 ; Move an objc call up through a phi that has null operands.
1254 ; CHECK-LABEL: define void @test22(
1255 ; CHECK: B:
1256 ; CHECK:   call void @llvm.objc.release(ptr %p)
1257 ; CHECK:   br label %C
1258 ; CHECK: C:                                                ; preds = %B, %A
1259 ; CHECK-NOT: @llvm.objc.release
1260 ; CHECK: {{^}}}
1261 define void @test22(ptr %p, i1 %a) {
1262   br i1 %a, label %A, label %B
1264   br label %C
1266   br label %C
1268   %h = phi ptr [ null, %A ], [ %p, %B ]
1269   call void @llvm.objc.release(ptr %h), !clang.imprecise_release !0
1270   ret void
1273 ; Do not move an llvm.objc.release that doesn't have the clang.imprecise_release tag.
1275 ; CHECK-LABEL: define void @test22_precise(
1276 ; CHECK: %[[P0:.*]] = phi ptr
1277 ; CHECK: call void @llvm.objc.release(ptr %[[P0]])
1278 ; CHECK: ret void
1279 define void @test22_precise(ptr %p, i1 %a) {
1280   br i1 %a, label %A, label %B
1282   br label %C
1284   br label %C
1286   %h = phi ptr [ null, %A ], [ %p, %B ]
1287   call void @llvm.objc.release(ptr %h)
1288   ret void
1291 ; Any call can decrement a retain count.
1293 ; CHECK-LABEL: define void @test24(
1294 ; CHECK: @llvm.objc.retain(ptr %a)
1295 ; CHECK: @llvm.objc.release
1296 ; CHECK: {{^}}}
1297 define void @test24(ptr %r, ptr %a) {
1298   call ptr @llvm.objc.retain(ptr %a)
1299   call void @use_pointer(ptr %r)
1300   %q = load i8, ptr %a
1301   call void @llvm.objc.release(ptr %a)
1302   ret void
1305 ; Don't move a retain/release pair if the release can be moved
1306 ; but the retain can't be moved to balance it.
1308 ; CHECK-LABEL: define void @test25(
1309 ; CHECK: entry:
1310 ; CHECK:   call ptr @llvm.objc.retain(ptr %p)
1311 ; CHECK: true:
1312 ; CHECK: done:
1313 ; CHECK:   call void @llvm.objc.release(ptr %p)
1314 ; CHECK: {{^}}}
1315 define void @test25(ptr %p, i1 %x) {
1316 entry:
1317   %f0 = call ptr @llvm.objc.retain(ptr %p)
1318   call void @callee()
1319   br i1 %x, label %true, label %done
1321 true:
1322   store i8 0, ptr %p
1323   br label %done
1325 done:
1326   call void @llvm.objc.release(ptr %p)
1327   ret void
1330 ; Don't move a retain/release pair if the retain can be moved
1331 ; but the release can't be moved to balance it.
1333 ; CHECK-LABEL: define void @test26(
1334 ; CHECK: entry:
1335 ; CHECK:   call ptr @llvm.objc.retain(ptr %p)
1336 ; CHECK: true:
1337 ; CHECK: done:
1338 ; CHECK:   call void @llvm.objc.release(ptr %p)
1339 ; CHECK: {{^}}}
1340 define void @test26(ptr %p, i1 %x) {
1341 entry:
1342   %f0 = call ptr @llvm.objc.retain(ptr %p)
1343   br i1 %x, label %true, label %done
1345 true:
1346   call void @callee()
1347   br label %done
1349 done:
1350   store i8 0, ptr %p
1351   call void @llvm.objc.release(ptr %p)
1352   ret void
1355 ; Don't sink the retain,release into the loop.
1357 ; CHECK-LABEL: define void @test27(
1358 ; CHECK: entry:
1359 ; CHECK: call ptr @llvm.objc.retain(ptr %p)
1360 ; CHECK: loop:
1361 ; CHECK-NOT: @llvm.objc.
1362 ; CHECK: done:
1363 ; CHECK: call void @llvm.objc.release
1364 ; CHECK: {{^}}}
1365 define void @test27(ptr %p, i1 %x, i1 %y) {
1366 entry:
1367   %f0 = call ptr @llvm.objc.retain(ptr %p)
1368   br i1 %x, label %loop, label %done
1370 loop:
1371   call void @callee()
1372   store i8 0, ptr %p
1373   br i1 %y, label %done, label %loop
1375 done:
1376   call void @llvm.objc.release(ptr %p)
1377   ret void
1380 ; Trivial code motion case: Triangle.
1382 ; CHECK-LABEL: define void @test28(
1383 ; CHECK-NOT: @llvm.objc.
1384 ; CHECK: true:
1385 ; CHECK: call ptr @llvm.objc.retain
1386 ; CHECK: call void @callee()
1387 ; CHECK: store
1388 ; CHECK: call void @llvm.objc.release
1389 ; CHECK: done:
1390 ; CHECK-NOT: @llvm.objc.
1391 ; CHECK: {{^}}}
1392 define void @test28(ptr %p, i1 %x) {
1393 entry:
1394   %f0 = call ptr @llvm.objc.retain(ptr %p)
1395   br i1 %x, label %true, label %done
1397 true:
1398   call void @callee()
1399   store i8 0, ptr %p
1400   br label %done
1402 done:
1403   call void @llvm.objc.release(ptr %p), !clang.imprecise_release !0
1404   ret void
1407 ; Trivial code motion case: Triangle, but no metadata. Don't move past
1408 ; unrelated memory references!
1410 ; CHECK-LABEL: define void @test28b(
1411 ; CHECK: call ptr @llvm.objc.retain
1412 ; CHECK: true:
1413 ; CHECK-NOT: @llvm.objc.
1414 ; CHECK: call void @callee()
1415 ; CHECK-NOT: @llvm.objc.
1416 ; CHECK: store
1417 ; CHECK-NOT: @llvm.objc.
1418 ; CHECK: done:
1419 ; CHECK: @llvm.objc.release
1420 ; CHECK: {{^}}}
1421 define void @test28b(ptr %p, i1 %x, ptr noalias %t) {
1422 entry:
1423   %f0 = call ptr @llvm.objc.retain(ptr %p)
1424   br i1 %x, label %true, label %done
1426 true:
1427   call void @callee()
1428   store i8 0, ptr %p
1429   br label %done
1431 done:
1432   store i8 0, ptr %t
1433   call void @llvm.objc.release(ptr %p)
1434   ret void
1437 ; Trivial code motion case: Triangle, with metadata. Do move past
1438 ; unrelated memory references! And preserve the metadata.
1440 ; CHECK-LABEL: define void @test28c(
1441 ; CHECK-NOT: @llvm.objc.
1442 ; CHECK: true:
1443 ; CHECK: call ptr @llvm.objc.retain
1444 ; CHECK: call void @callee()
1445 ; CHECK: store
1446 ; CHECK: call void @llvm.objc.release(ptr %p) [[NUW]], !clang.imprecise_release
1447 ; CHECK: done:
1448 ; CHECK-NOT: @llvm.objc.
1449 ; CHECK: {{^}}}
1450 define void @test28c(ptr %p, i1 %x, ptr noalias %t) {
1451 entry:
1452   %f0 = call ptr @llvm.objc.retain(ptr %p)
1453   br i1 %x, label %true, label %done
1455 true:
1456   call void @callee()
1457   store i8 0, ptr %p
1458   br label %done
1460 done:
1461   store i8 0, ptr %t
1462   call void @llvm.objc.release(ptr %p), !clang.imprecise_release !0
1463   ret void
1466 ; Like test28. but with two releases.
1468 ; CHECK-LABEL: define void @test29(
1469 ; CHECK: call ptr @llvm.objc.retain
1470 ; CHECK: true:
1471 ; CHECK: call void @callee()
1472 ; CHECK: store
1473 ; CHECK: done:
1474 ; CHECK: call void @llvm.objc.release
1475 ; CHECK: ohno:
1476 ; CHECK: call void @llvm.objc.release
1477 ; CHECK: {{^}}}
1478 define void @test29(ptr %p, i1 %x, i1 %y) {
1479 entry:
1480   %f0 = call ptr @llvm.objc.retain(ptr %p)
1481   br i1 %x, label %true, label %done
1483 true:
1484   call void @callee()
1485   store i8 0, ptr %p
1486   br i1 %y, label %done, label %ohno
1488 done:
1489   call void @llvm.objc.release(ptr %p)
1490   ret void
1492 ohno:
1493   call void @llvm.objc.release(ptr %p)
1494   ret void
1497 ; Basic case with the use and call in a diamond
1498 ; with an extra release.
1500 ; CHECK-LABEL: define void @test30(
1501 ; CHECK: call ptr @llvm.objc.retain
1502 ; CHECK: true:
1503 ; CHECK: call void @callee()
1504 ; CHECK: store
1505 ; CHECK: false:
1506 ; CHECK: done:
1507 ; CHECK: call void @llvm.objc.release
1508 ; CHECK: ohno:
1509 ; CHECK: call void @llvm.objc.release
1510 ; CHECK: {{^}}}
1511 define void @test30(ptr %p, i1 %x, i1 %y, i1 %z) {
1512 entry:
1513   %f0 = call ptr @llvm.objc.retain(ptr %p)
1514   br i1 %x, label %true, label %false
1516 true:
1517   call void @callee()
1518   store i8 0, ptr %p
1519   br i1 %y, label %done, label %ohno
1521 false:
1522   br i1 %z, label %done, label %ohno
1524 done:
1525   call void @llvm.objc.release(ptr %p)
1526   ret void
1528 ohno:
1529   call void @llvm.objc.release(ptr %p)
1530   ret void
1533 ; Basic case with a mergeable release.
1535 ; CHECK-LABEL: define void @test31(
1536 ; CHECK: call ptr @llvm.objc.retain(ptr %p)
1537 ; CHECK: call void @callee()
1538 ; CHECK: store
1539 ; CHECK: true:
1540 ; CHECK: call void @llvm.objc.release
1541 ; CHECK: false:
1542 ; CHECK: call void @llvm.objc.release
1543 ; CHECK: ret void
1544 ; CHECK: {{^}}}
1545 define void @test31(ptr %p, i1 %x) {
1546 entry:
1547   %f0 = call ptr @llvm.objc.retain(ptr %p)
1548   call void @callee()
1549   store i8 0, ptr %p
1550   br i1 %x, label %true, label %false
1551 true:
1552   call void @llvm.objc.release(ptr %p)
1553   ret void
1554 false:
1555   call void @llvm.objc.release(ptr %p)
1556   ret void
1559 ; Don't consider bitcasts or getelementptrs direct uses.
1561 ; CHECK-LABEL: define void @test32(
1562 ; CHECK: call ptr @llvm.objc.retain
1563 ; CHECK: true:
1564 ; CHECK: call void @callee()
1565 ; CHECK: store
1566 ; CHECK: done:
1567 ; CHECK: call void @llvm.objc.release
1568 ; CHECK: {{^}}}
1569 define void @test32(ptr %p, i1 %x) {
1570 entry:
1571   %f0 = call ptr @llvm.objc.retain(ptr %p)
1572   br i1 %x, label %true, label %done
1574 true:
1575   call void @callee()
1576   store i8 0, ptr %p
1577   br label %done
1579 done:
1580   call void @llvm.objc.release(ptr %p)
1581   ret void
1584 ; Do consider icmps to be direct uses.
1586 ; CHECK-LABEL: define void @test33(
1587 ; CHECK: call ptr @llvm.objc.retain
1588 ; CHECK: true:
1589 ; CHECK: call void @callee()
1590 ; CHECK: icmp
1591 ; CHECK: done:
1592 ; CHECK: call void @llvm.objc.release
1593 ; CHECK: {{^}}}
1594 define void @test33(ptr %p, i1 %x, ptr %y) {
1595 entry:
1596   %f0 = call ptr @llvm.objc.retain(ptr %p)
1597   br i1 %x, label %true, label %done
1599 true:
1600   call void @callee()
1601   %v = icmp eq ptr %p, %y
1602   br label %done
1604 done:
1605   call void @llvm.objc.release(ptr %p)
1606   ret void
1609 ; Delete retain,release if there's just a possible dec and we have imprecise
1610 ; releases.
1612 ; CHECK-LABEL: define void @test34a(
1613 ; CHECK:   call ptr @llvm.objc.retain
1614 ; CHECK: true:
1615 ; CHECK: done:
1616 ; CHECK: call void @llvm.objc.release
1617 ; CHECK: {{^}}}
1618 define void @test34a(ptr %p, i1 %x, ptr %y) {
1619 entry:
1620   %f0 = call ptr @llvm.objc.retain(ptr %p)
1621   br i1 %x, label %true, label %done
1623 true:
1624   call void @callee()
1625   br label %done
1627 done:
1628   call void @llvm.objc.release(ptr %p)
1629   ret void
1632 ; CHECK-LABEL: define void @test34b(
1633 ; CHECK-NOT: @llvm.objc.
1634 ; CHECK: {{^}}}
1635 define void @test34b(ptr %p, i1 %x, ptr %y) {
1636 entry:
1637   %f0 = call ptr @llvm.objc.retain(ptr %p)
1638   br i1 %x, label %true, label %done
1640 true:
1641   call void @callee()
1642   br label %done
1644 done:
1645   call void @llvm.objc.release(ptr %p), !clang.imprecise_release !0
1646   ret void
1650 ; Delete retain,release if there's just a use and we do not have a precise
1651 ; release.
1653 ; Precise.
1654 ; CHECK-LABEL: define void @test35a(
1655 ; CHECK: entry:
1656 ; CHECK:   call ptr @llvm.objc.retain
1657 ; CHECK: true:
1658 ; CHECK: done:
1659 ; CHECK:   call void @llvm.objc.release
1660 ; CHECK: {{^}}}
1661 define void @test35a(ptr %p, i1 %x, ptr %y) {
1662 entry:
1663   %f0 = call ptr @llvm.objc.retain(ptr %p)
1664   br i1 %x, label %true, label %done
1666 true:
1667   %v = icmp eq ptr %p, %y
1668   br label %done
1670 done:
1671   call void @llvm.objc.release(ptr %p)
1672   ret void
1675 ; Imprecise.
1676 ; CHECK-LABEL: define void @test35b(
1677 ; CHECK-NOT: @llvm.objc.
1678 ; CHECK: {{^}}}
1679 define void @test35b(ptr %p, i1 %x, ptr %y) {
1680 entry:
1681   %f0 = call ptr @llvm.objc.retain(ptr %p)
1682   br i1 %x, label %true, label %done
1684 true:
1685   %v = icmp eq ptr %p, %y
1686   br label %done
1688 done:
1689   call void @llvm.objc.release(ptr %p), !clang.imprecise_release !0
1690   ret void
1693 ; Delete a retain,release if there's no actual use and we have precise release.
1695 ; CHECK-LABEL: define void @test36a(
1696 ; CHECK: @llvm.objc.retain
1697 ; CHECK: call void @callee()
1698 ; CHECK-NOT: @llvm.objc.
1699 ; CHECK: call void @callee()
1700 ; CHECK: @llvm.objc.release
1701 ; CHECK: {{^}}}
1702 define void @test36a(ptr %p) {
1703 entry:
1704   call ptr @llvm.objc.retain(ptr %p)
1705   call void @callee()
1706   call void @callee()
1707   call void @llvm.objc.release(ptr %p)
1708   ret void
1711 ; Like test36, but with metadata.
1713 ; CHECK-LABEL: define void @test36b(
1714 ; CHECK-NOT: @llvm.objc.
1715 ; CHECK: {{^}}}
1716 define void @test36b(ptr %p) {
1717 entry:
1718   call ptr @llvm.objc.retain(ptr %p)
1719   call void @callee()
1720   call void @callee()
1721   call void @llvm.objc.release(ptr %p), !clang.imprecise_release !0
1722   ret void
1725 ; Be aggressive about analyzing phis to eliminate possible uses.
1727 ; CHECK-LABEL: define void @test38(
1728 ; CHECK-NOT: @llvm.objc.
1729 ; CHECK: {{^}}}
1730 define void @test38(ptr %p, i1 %u, i1 %m, ptr %z, ptr %y, ptr %x, ptr %w) {
1731 entry:
1732   call ptr @llvm.objc.retain(ptr %p)
1733   br i1 %u, label %true, label %false
1734 true:
1735   br i1 %m, label %a, label %b
1736 false:
1737   br i1 %m, label %c, label %d
1739   br label %e
1741   br label %e
1743   br label %f
1745   br label %f
1747   %j = phi ptr [ %z, %a ], [ %y, %b ]
1748   br label %g
1750   %k = phi ptr [ %w, %c ], [ %x, %d ]
1751   br label %g
1753   %h = phi ptr [ %j, %e ], [ %k, %f ]
1754   call void @use_pointer(ptr %h)
1755   call void @llvm.objc.release(ptr %p), !clang.imprecise_release !0
1756   ret void
1759 ; Delete retain,release pairs around loops.
1761 ; CHECK-LABEL: define void @test39(
1762 ; CHECK-NOT: @llvm.objc.
1763 ; CHECK: {{^}}}
1764 define void @test39(ptr %p, i1 %arg) {
1765 entry:
1766   %0 = call ptr @llvm.objc.retain(ptr %p)
1767   br label %loop
1769 loop:                                             ; preds = %loop, %entry
1770   br i1 %arg, label %loop, label %exit
1772 exit:                                             ; preds = %loop
1773   call void @llvm.objc.release(ptr %0), !clang.imprecise_release !0
1774   ret void
1777 ; Delete retain,release pairs around loops containing uses.
1779 ; CHECK-LABEL: define void @test39b(
1780 ; CHECK-NOT: @llvm.objc.
1781 ; CHECK: {{^}}}
1782 define void @test39b(ptr %p, i1 %arg) {
1783 entry:
1784   %0 = call ptr @llvm.objc.retain(ptr %p)
1785   br label %loop
1787 loop:                                             ; preds = %loop, %entry
1788   store i8 0, ptr %0
1789   br i1 %arg, label %loop, label %exit
1791 exit:                                             ; preds = %loop
1792   call void @llvm.objc.release(ptr %0), !clang.imprecise_release !0
1793   ret void
1796 ; Delete retain,release pairs around loops containing potential decrements.
1798 ; CHECK-LABEL: define void @test39c(
1799 ; CHECK-NOT: @llvm.objc.
1800 ; CHECK: {{^}}}
1801 define void @test39c(ptr %p, i1 %arg) {
1802 entry:
1803   %0 = call ptr @llvm.objc.retain(ptr %p)
1804   br label %loop
1806 loop:                                             ; preds = %loop, %entry
1807   call void @use_pointer(ptr %0)
1808   br i1 %arg, label %loop, label %exit
1810 exit:                                             ; preds = %loop
1811   call void @llvm.objc.release(ptr %0), !clang.imprecise_release !0
1812   ret void
1815 ; Delete retain,release pairs around loops even if
1816 ; the successors are in a different order.
1818 ; CHECK-LABEL: define void @test40(
1819 ; CHECK-NOT: @llvm.objc.
1820 ; CHECK: {{^}}}
1821 define void @test40(ptr %p, i1 %arg) {
1822 entry:
1823   %0 = call ptr @llvm.objc.retain(ptr %p)
1824   br label %loop
1826 loop:                                             ; preds = %loop, %entry
1827   call void @use_pointer(ptr %0)
1828   br i1 %arg, label %exit, label %loop
1830 exit:                                             ; preds = %loop
1831   call void @llvm.objc.release(ptr %0), !clang.imprecise_release !0
1832   ret void
1835 ; Do the known-incremented retain+release elimination even if the pointer
1836 ; is also autoreleased.
1838 ; CHECK-LABEL: define void @test42(
1839 ; CHECK-NEXT: entry:
1840 ; CHECK-NEXT: call ptr @llvm.objc.retain(ptr %p)
1841 ; CHECK-NEXT: call ptr @llvm.objc.autorelease(ptr %p)
1842 ; CHECK-NEXT: call void @use_pointer(ptr %p)
1843 ; CHECK-NEXT: call void @use_pointer(ptr %p)
1844 ; CHECK-NEXT: call void @use_pointer(ptr %p)
1845 ; CHECK-NEXT: call void @use_pointer(ptr %p)
1846 ; CHECK-NEXT: call void @llvm.objc.release(ptr %p)
1847 ; CHECK-NEXT: ret void
1848 ; CHECK-NEXT: }
1849 define void @test42(ptr %p) {
1850 entry:
1851   call ptr @llvm.objc.retain(ptr %p)
1852   call ptr @llvm.objc.autorelease(ptr %p)
1853   call ptr @llvm.objc.retain(ptr %p)
1854   call void @use_pointer(ptr %p)
1855   call void @use_pointer(ptr %p)
1856   call void @llvm.objc.release(ptr %p)
1857   call void @use_pointer(ptr %p)
1858   call void @use_pointer(ptr %p)
1859   call void @llvm.objc.release(ptr %p)
1860   ret void
1863 ; Don't the known-incremented retain+release elimination if the pointer is
1864 ; autoreleased and there's an autoreleasePoolPop.
1866 ; CHECK-LABEL: define void @test43(
1867 ; CHECK-NEXT: entry:
1868 ; CHECK-NEXT: call ptr @llvm.objc.retain(ptr %p)
1869 ; CHECK-NEXT: call ptr @llvm.objc.autorelease(ptr %p)
1870 ; CHECK-NEXT: call ptr @llvm.objc.retain
1871 ; CHECK-NEXT: call void @use_pointer(ptr %p)
1872 ; CHECK-NEXT: call void @use_pointer(ptr %p)
1873 ; CHECK-NEXT: call void @llvm.objc.autoreleasePoolPop(ptr undef)
1874 ; CHECK-NEXT: call void @llvm.objc.release
1875 ; CHECK-NEXT: ret void
1876 ; CHECK-NEXT: }
1877 define void @test43(ptr %p) {
1878 entry:
1879   call ptr @llvm.objc.retain(ptr %p)
1880   call ptr @llvm.objc.autorelease(ptr %p)
1881   call ptr @llvm.objc.retain(ptr %p)
1882   call void @use_pointer(ptr %p)
1883   call void @use_pointer(ptr %p)
1884   call void @llvm.objc.autoreleasePoolPop(ptr undef)
1885   call void @llvm.objc.release(ptr %p)
1886   ret void
1889 ; Do the known-incremented retain+release elimination if the pointer is
1890 ; autoreleased and there's an autoreleasePoolPush.
1892 ; CHECK-LABEL: define void @test43b(
1893 ; CHECK-NEXT: entry:
1894 ; CHECK-NEXT: call ptr @llvm.objc.retain(ptr %p)
1895 ; CHECK-NEXT: call ptr @llvm.objc.autorelease(ptr %p)
1896 ; CHECK-NEXT: call void @use_pointer(ptr %p)
1897 ; CHECK-NEXT: call void @use_pointer(ptr %p)
1898 ; CHECK-NEXT: call ptr @llvm.objc.autoreleasePoolPush()
1899 ; CHECK-NEXT: call void @use_pointer(ptr %p)
1900 ; CHECK-NEXT: call void @llvm.objc.release
1901 ; CHECK-NEXT: ret void
1902 ; CHECK-NEXT: }
1903 define void @test43b(ptr %p) {
1904 entry:
1905   call ptr @llvm.objc.retain(ptr %p)
1906   call ptr @llvm.objc.autorelease(ptr %p)
1907   call ptr @llvm.objc.retain(ptr %p)
1908   call void @use_pointer(ptr %p)
1909   call void @use_pointer(ptr %p)
1910   call ptr @llvm.objc.autoreleasePoolPush()
1911   call void @llvm.objc.release(ptr %p)
1912   call void @use_pointer(ptr %p)
1913   call void @llvm.objc.release(ptr %p)
1914   ret void
1917 ; Do retain+release elimination for non-provenance pointers.
1919 ; CHECK-LABEL: define void @test44(
1920 ; CHECK-NOT: llvm.objc.
1921 ; CHECK: {{^}}}
1922 define void @test44(ptr %pp) {
1923   %p = load ptr, ptr %pp
1924   %q = call ptr @llvm.objc.retain(ptr %p)
1925   call void @llvm.objc.release(ptr %q)
1926   ret void
1929 ; Don't delete retain+release with an unknown-provenance
1930 ; may-alias llvm.objc.release between them.
1932 ; CHECK-LABEL: define void @test45(
1933 ; CHECK: call ptr @llvm.objc.retain(ptr %p)
1934 ; CHECK: call void @llvm.objc.release(ptr %q)
1935 ; CHECK: call void @use_pointer(ptr %p)
1936 ; CHECK: call void @llvm.objc.release(ptr %p)
1937 ; CHECK: {{^}}}
1938 define void @test45(ptr %pp, ptr %qq) {
1939   %p = load ptr, ptr %pp
1940   %q = load ptr, ptr %qq
1941   call ptr @llvm.objc.retain(ptr %p)
1942   call void @llvm.objc.release(ptr %q)
1943   call void @use_pointer(ptr %p)
1944   call void @llvm.objc.release(ptr %p)
1945   ret void
1948 ; Don't delete retain and autorelease here.
1950 ; CHECK-LABEL: define void @test46(
1951 ; CHECK: tail call ptr @llvm.objc.retain(ptr %p) [[NUW]]
1952 ; CHECK: true:
1953 ; CHECK: call ptr @llvm.objc.autorelease(ptr %p) [[NUW]]
1954 ; CHECK: {{^}}}
1955 define void @test46(ptr %p, i1 %a) {
1956 entry:
1957   call ptr @llvm.objc.retain(ptr %p)
1958   br i1 %a, label %true, label %false
1960 true:
1961   call ptr @llvm.objc.autorelease(ptr %p)
1962   call void @use_pointer(ptr %p)
1963   ret void
1965 false:
1966   ret void
1969 ; Delete no-op cast calls.
1971 ; CHECK-LABEL: define ptr @test47(
1972 ; CHECK-NOT: call
1973 ; CHECK: ret ptr %p
1974 ; CHECK: {{^}}}
1975 define ptr @test47(ptr %p) nounwind {
1976   %x = call ptr @llvm.objc.retainedObject(ptr %p)
1977   ret ptr %x
1980 ; Delete no-op cast calls.
1982 ; CHECK-LABEL: define ptr @test48(
1983 ; CHECK-NOT: call
1984 ; CHECK: ret ptr %p
1985 ; CHECK: {{^}}}
1986 define ptr @test48(ptr %p) nounwind {
1987   %x = call ptr @llvm.objc.unretainedObject(ptr %p)
1988   ret ptr %x
1991 ; Delete no-op cast calls.
1993 ; CHECK-LABEL: define ptr @test49(
1994 ; CHECK-NOT: call
1995 ; CHECK: ret ptr %p
1996 ; CHECK: {{^}}}
1997 define ptr @test49(ptr %p) nounwind {
1998   %x = call ptr @llvm.objc.unretainedPointer(ptr %p)
1999   ret ptr %x
2002 ; Do delete retain+release with intervening stores of the address value if we
2003 ; have imprecise release attached to llvm.objc.release.
2005 ; CHECK-LABEL:      define void @test50a(
2006 ; CHECK-NEXT:   call ptr @llvm.objc.retain
2007 ; CHECK-NEXT:   call void @callee
2008 ; CHECK-NEXT:   store
2009 ; CHECK-NEXT:   call void @llvm.objc.release
2010 ; CHECK-NEXT:   ret void
2011 ; CHECK-NEXT: }
2012 define void @test50a(ptr %p, ptr %pp) {
2013   call ptr @llvm.objc.retain(ptr %p)
2014   call void @callee()
2015   store ptr %p, ptr %pp
2016   call void @llvm.objc.release(ptr %p)
2017   ret void
2020 ; CHECK-LABEL: define void @test50b(
2021 ; CHECK-NOT: @llvm.objc.
2022 ; CHECK: {{^}}}
2023 define void @test50b(ptr %p, ptr %pp) {
2024   call ptr @llvm.objc.retain(ptr %p)
2025   call void @callee()
2026   store ptr %p, ptr %pp
2027   call void @llvm.objc.release(ptr %p), !clang.imprecise_release !0
2028   ret void
2032 ; Don't delete retain+release with intervening stores through the
2033 ; address value.
2035 ; CHECK-LABEL: define void @test51a(
2036 ; CHECK: call ptr @llvm.objc.retain(ptr %p)
2037 ; CHECK: call void @llvm.objc.release(ptr %p)
2038 ; CHECK: ret void
2039 ; CHECK: {{^}}}
2040 define void @test51a(ptr %p) {
2041   call ptr @llvm.objc.retain(ptr %p)
2042   call void @callee()
2043   store i8 0, ptr %p
2044   call void @llvm.objc.release(ptr %p)
2045   ret void
2048 ; CHECK-LABEL: define void @test51b(
2049 ; CHECK: call ptr @llvm.objc.retain(ptr %p)
2050 ; CHECK: call void @llvm.objc.release(ptr %p)
2051 ; CHECK: ret void
2052 ; CHECK: {{^}}}
2053 define void @test51b(ptr %p) {
2054   call ptr @llvm.objc.retain(ptr %p)
2055   call void @callee()
2056   store i8 0, ptr %p
2057   call void @llvm.objc.release(ptr %p), !clang.imprecise_release !0
2058   ret void
2061 ; Don't delete retain+release with intervening use of a pointer of
2062 ; unknown provenance.
2064 ; CHECK-LABEL: define void @test52a(
2065 ; CHECK: call ptr @llvm.objc.retain
2066 ; CHECK: call void @callee()
2067 ; CHECK: call void @use_pointer(ptr %z)
2068 ; CHECK: call void @llvm.objc.release
2069 ; CHECK: ret void
2070 ; CHECK: {{^}}}
2071 define void @test52a(ptr %zz, ptr %pp) {
2072   %p = load ptr, ptr %pp
2073   %1 = call ptr @llvm.objc.retain(ptr %p)
2074   call void @callee()
2075   %z = load ptr, ptr %zz
2076   call void @use_pointer(ptr %z)
2077   call void @llvm.objc.release(ptr %p)
2078   ret void
2081 ; CHECK-LABEL: define void @test52b(
2082 ; CHECK: call ptr @llvm.objc.retain
2083 ; CHECK: call void @callee()
2084 ; CHECK: call void @use_pointer(ptr %z)
2085 ; CHECK: call void @llvm.objc.release
2086 ; CHECK: ret void
2087 ; CHECK: {{^}}}
2088 define void @test52b(ptr %zz, ptr %pp) {
2089   %p = load ptr, ptr %pp
2090   %1 = call ptr @llvm.objc.retain(ptr %p)
2091   call void @callee()
2092   %z = load ptr, ptr %zz
2093   call void @use_pointer(ptr %z)
2094   call void @llvm.objc.release(ptr %p), !clang.imprecise_release !0
2095   ret void
2098 ; Like test52, but the pointer has function type, so it's assumed to
2099 ; be not reference counted.
2100 ; Oops. That's wrong. Clang sometimes uses function types gratuitously.
2101 ; See rdar://10551239.
2103 ; CHECK-LABEL: define void @test53(
2104 ; CHECK: @llvm.objc.
2105 ; CHECK: {{^}}}
2106 define void @test53(ptr %zz, ptr %pp) {
2107   %p = load ptr, ptr %pp
2108   %1 = call ptr @llvm.objc.retain(ptr %p)
2109   call void @callee()
2110   %z = load ptr, ptr %zz
2111   call void @callee_fnptr(ptr %z)
2112   call void @llvm.objc.release(ptr %p)
2113   ret void
2116 ; Convert autorelease to release if the value is unused.
2118 ; CHECK-LABEL: define void @test54(
2119 ; CHECK: call ptr @returner()
2120 ; CHECK-NEXT: call void @llvm.objc.release(ptr %t) [[NUW]], !clang.imprecise_release ![[RELEASE]]
2121 ; CHECK-NEXT: ret void
2122 ; CHECK: {{^}}}
2123 define void @test54() {
2124   %t = call ptr @returner()
2125   call ptr @llvm.objc.autorelease(ptr %t)
2126   ret void
2129 ; Nested retain+release pairs. Delete them both.
2131 ; CHECK-LABEL: define void @test55(
2132 ; CHECK-NOT: @objc
2133 ; CHECK: {{^}}}
2134 define void @test55(ptr %x) {
2135 entry:
2136   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
2137   %1 = call ptr @llvm.objc.retain(ptr %x) nounwind
2138   call void @llvm.objc.release(ptr %x) nounwind
2139   call void @llvm.objc.release(ptr %x) nounwind
2140   ret void
2143 ; Nested retain+release pairs where the inner pair depends
2144 ; on the outer pair to be removed, and then the outer pair
2145 ; can be partially eliminated. Plus an extra outer pair to
2146 ; eliminate, for fun.
2148 ; CHECK-LABEL: define void @test56(
2149 ; CHECK-NOT: @objc
2150 ; CHECK: if.then:
2151 ; CHECK-NEXT: %0 = tail call ptr @llvm.objc.retain(ptr %x) [[NUW]]
2152 ; CHECK-NEXT: tail call void @use_pointer(ptr %x)
2153 ; CHECK-NEXT: tail call void @use_pointer(ptr %x)
2154 ; CHECK-NEXT: tail call void @llvm.objc.release(ptr %x) [[NUW]], !clang.imprecise_release ![[RELEASE]]
2155 ; CHECK-NEXT: br label %if.end
2156 ; CHECK-NOT: @objc
2157 ; CHECK: {{^}}}
2158 define void @test56(ptr %x, i32 %n) {
2159 entry:
2160   %0 = tail call ptr @llvm.objc.retain(ptr %x) nounwind
2161   %1 = tail call ptr @llvm.objc.retain(ptr %0) nounwind
2162   %tobool = icmp eq i32 %n, 0
2163   br i1 %tobool, label %if.end, label %if.then
2165 if.then:                                          ; preds = %entry
2166   %2 = tail call ptr @llvm.objc.retain(ptr %1) nounwind
2167   tail call void @use_pointer(ptr %2)
2168   tail call void @use_pointer(ptr %2)
2169   tail call void @llvm.objc.release(ptr %2) nounwind, !clang.imprecise_release !0
2170   br label %if.end
2172 if.end:                                           ; preds = %entry, %if.then
2173   tail call void @llvm.objc.release(ptr %1) nounwind, !clang.imprecise_release !0
2174   tail call void @llvm.objc.release(ptr %0) nounwind, !clang.imprecise_release !0
2175   ret void
2178 ; When there are adjacent retain+release pairs, the first one is known
2179 ; unnecessary because the presence of the second one means that the first one
2180 ; won't be deleting the object.
2182 ; CHECK-LABEL:      define void @test57(
2183 ; CHECK-NEXT: entry:
2184 ; CHECK-NEXT:   tail call ptr @llvm.objc.retain(ptr %x) [[NUW]]
2185 ; CHECK-NEXT:   call void @use_pointer(ptr %x)
2186 ; CHECK-NEXT:   call void @use_pointer(ptr %x)
2187 ; CHECK-NEXT:   tail call ptr @llvm.objc.retain(ptr %x) [[NUW]]
2188 ; CHECK-NEXT:   call void @use_pointer(ptr %x)
2189 ; CHECK-NEXT:   call void @use_pointer(ptr %x)
2190 ; CHECK-NEXT:   call void @llvm.objc.release(ptr %x) [[NUW]]
2191 ; CHECK-NEXT:   ret void
2192 ; CHECK-NEXT: }
2193 define void @test57(ptr %x) nounwind {
2194 entry:
2195   call ptr @llvm.objc.retain(ptr %x) nounwind
2196   call ptr @llvm.objc.retain(ptr %x) nounwind
2197   call void @use_pointer(ptr %x)
2198   call void @use_pointer(ptr %x)
2199   call void @llvm.objc.release(ptr %x) nounwind
2200   call ptr @llvm.objc.retain(ptr %x) nounwind
2201   call void @use_pointer(ptr %x)
2202   call void @use_pointer(ptr %x)
2203   call void @llvm.objc.release(ptr %x) nounwind
2204   ret void
2207 ; An adjacent retain+release pair is sufficient even if it will be
2208 ; removed itself.
2210 ; CHECK-LABEL:      define void @test58(
2211 ; CHECK-NEXT: entry:
2212 ; CHECK-NEXT:   @llvm.objc.retain
2213 ; CHECK-NEXT:   call void @use_pointer(ptr %x)
2214 ; CHECK-NEXT:   call void @use_pointer(ptr %x)
2215 ; CHECK-NEXT:   ret void
2216 ; CHECK-NEXT: }
2217 define void @test58(ptr %x) nounwind {
2218 entry:
2219   call ptr @llvm.objc.retain(ptr %x) nounwind
2220   call ptr @llvm.objc.retain(ptr %x) nounwind
2221   call void @use_pointer(ptr %x)
2222   call void @use_pointer(ptr %x)
2223   call void @llvm.objc.release(ptr %x) nounwind
2224   call ptr @llvm.objc.retain(ptr %x) nounwind
2225   call void @llvm.objc.release(ptr %x) nounwind
2226   ret void
2229 ; Don't delete the second retain+release pair in an adjacent set.
2231 ; CHECK-LABEL:      define void @test59(
2232 ; CHECK-NEXT: entry:
2233 ; CHECK-NEXT:   %0 = tail call ptr @llvm.objc.retain(ptr %x) [[NUW]]
2234 ; CHECK-NEXT:   call void @use_pointer(ptr %x)
2235 ; CHECK-NEXT:   call void @use_pointer(ptr %x)
2236 ; CHECK-NEXT:   call void @llvm.objc.release(ptr %x) [[NUW]]
2237 ; CHECK-NEXT:   ret void
2238 ; CHECK-NEXT: }
2239 define void @test59(ptr %x) nounwind {
2240 entry:
2241   %a = call ptr @llvm.objc.retain(ptr %x) nounwind
2242   call void @llvm.objc.release(ptr %x) nounwind
2243   %b = call ptr @llvm.objc.retain(ptr %x) nounwind
2244   call void @use_pointer(ptr %x)
2245   call void @use_pointer(ptr %x)
2246   call void @llvm.objc.release(ptr %x) nounwind
2247   ret void
2250 ; Constant pointers to objects don't need reference counting.
2252 @constptr = external constant ptr
2253 @something = external global ptr
2255 ; We have a precise lifetime retain/release here. We can not remove them since
2256 ; @something is not constant.
2258 ; CHECK-LABEL: define void @test60a(
2259 ; CHECK: call ptr @llvm.objc.retain
2260 ; CHECK: call void @llvm.objc.release
2261 ; CHECK: {{^}}}
2262 define void @test60a() {
2263   %t = load ptr, ptr @constptr
2264   %s = load ptr, ptr @something
2265   call ptr @llvm.objc.retain(ptr %s)
2266   call void @callee()
2267   call void @use_pointer(ptr %t)
2268   call void @llvm.objc.release(ptr %s)
2269   ret void
2272 ; CHECK-LABEL: define void @test60b(
2273 ; CHECK: call ptr @llvm.objc.retain
2274 ; CHECK-NOT: call ptr @llvm.objc.retain
2275 ; CHECK-NOT: call ptr @llvm.objc.release
2276 ; CHECK: {{^}}}
2277 define void @test60b() {
2278   %t = load ptr, ptr @constptr
2279   %s = load ptr, ptr @something
2280   call ptr @llvm.objc.retain(ptr %t)
2281   call ptr @llvm.objc.retain(ptr %t)
2282   call void @callee()
2283   call void @use_pointer(ptr %s)
2284   call void @llvm.objc.release(ptr %t)
2285   ret void
2288 ; CHECK-LABEL: define void @test60c(
2289 ; CHECK-NOT: @llvm.objc.
2290 ; CHECK: {{^}}}
2291 define void @test60c() {
2292   %t = load ptr, ptr @constptr
2293   %s = load ptr, ptr @something
2294   call ptr @llvm.objc.retain(ptr %t)
2295   call void @callee()
2296   call void @use_pointer(ptr %s)
2297   call void @llvm.objc.release(ptr %t), !clang.imprecise_release !0
2298   ret void
2301 ; CHECK-LABEL: define void @test60d(
2302 ; CHECK-NOT: @llvm.objc.
2303 ; CHECK: {{^}}}
2304 define void @test60d() {
2305   %t = load ptr, ptr @constptr
2306   %s = load ptr, ptr @something
2307   call ptr @llvm.objc.retain(ptr %t)
2308   call void @callee()
2309   call void @use_pointer(ptr %s)
2310   call void @llvm.objc.release(ptr %t)
2311   ret void
2314 ; CHECK-LABEL: define void @test60e(
2315 ; CHECK-NOT: @llvm.objc.
2316 ; CHECK: {{^}}}
2317 define void @test60e() {
2318   %t = load ptr, ptr @constptr
2319   %s = load ptr, ptr @something
2320   call ptr @llvm.objc.retain(ptr %t)
2321   call void @callee()
2322   call void @use_pointer(ptr %s)
2323   call void @llvm.objc.release(ptr %t), !clang.imprecise_release !0
2324   ret void
2327 ; Constant pointers to objects don't need to be considered related to other
2328 ; pointers.
2330 ; CHECK-LABEL: define void @test61(
2331 ; CHECK-NOT: @llvm.objc.
2332 ; CHECK: {{^}}}
2333 define void @test61() {
2334   %t = load ptr, ptr @constptr
2335   call ptr @llvm.objc.retain(ptr %t)
2336   call void @callee()
2337   call void @use_pointer(ptr %t)
2338   call void @llvm.objc.release(ptr %t)
2339   ret void
2342 ; Delete a retain matched by releases when one is inside the loop and the
2343 ; other is outside the loop.
2345 ; CHECK-LABEL: define void @test62(
2346 ; CHECK-NOT: @llvm.objc.
2347 ; CHECK: {{^}}}
2348 define void @test62(ptr %x, ptr %p) nounwind {
2349 entry:
2350   br label %loop
2352 loop:
2353   call ptr @llvm.objc.retain(ptr %x)
2354   %q = load i1, ptr %p
2355   br i1 %q, label %loop.more, label %exit
2357 loop.more:
2358   call void @llvm.objc.release(ptr %x)
2359   br label %loop
2361 exit:
2362   call void @llvm.objc.release(ptr %x)
2363   ret void
2366 ; Like test62 but with no release in exit.
2367 ; Don't delete anything!
2369 ; CHECK-LABEL: define void @test63(
2370 ; CHECK: loop:
2371 ; CHECK:   tail call ptr @llvm.objc.retain(ptr %x)
2372 ; CHECK: loop.more:
2373 ; CHECK:   call void @llvm.objc.release(ptr %x)
2374 ; CHECK: {{^}}}
2375 define void @test63(ptr %x, ptr %p) nounwind {
2376 entry:
2377   br label %loop
2379 loop:
2380   call ptr @llvm.objc.retain(ptr %x)
2381   %q = load i1, ptr %p
2382   br i1 %q, label %loop.more, label %exit
2384 loop.more:
2385   call void @llvm.objc.release(ptr %x)
2386   br label %loop
2388 exit:
2389   ret void
2392 ; Like test62 but with no release in loop.more.
2393 ; Don't delete anything!
2395 ; CHECK-LABEL: define void @test64(
2396 ; CHECK: loop:
2397 ; CHECK:   tail call ptr @llvm.objc.retain(ptr %x)
2398 ; CHECK: exit:
2399 ; CHECK:   call void @llvm.objc.release(ptr %x)
2400 ; CHECK: {{^}}}
2401 define void @test64(ptr %x, ptr %p) nounwind {
2402 entry:
2403   br label %loop
2405 loop:
2406   call ptr @llvm.objc.retain(ptr %x)
2407   %q = load i1, ptr %p
2408   br i1 %q, label %loop.more, label %exit
2410 loop.more:
2411   br label %loop
2413 exit:
2414   call void @llvm.objc.release(ptr %x)
2415   ret void
2418 ; Move an autorelease past a phi with a null.
2420 ; CHECK-LABEL: define ptr @test65(
2421 ; CHECK: if.then:
2422 ; CHECK:   call ptr @llvm.objc.autorelease(
2423 ; CHECK: return:
2424 ; CHECK-NOT: @llvm.objc.autorelease
2425 ; CHECK: {{^}}}
2426 define ptr @test65(i1 %x) {
2427 entry:
2428   br i1 %x, label %return, label %if.then
2430 if.then:                                          ; preds = %entry
2431   %c = call ptr @returner()
2432   %s = call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr %c) nounwind
2433   br label %return
2435 return:                                           ; preds = %if.then, %entry
2436   %retval = phi ptr [ %s, %if.then ], [ null, %entry ]
2437   %q = call ptr @llvm.objc.autorelease(ptr %retval) nounwind
2438   ret ptr %retval
2441 ; Don't move an autorelease past an autorelease pool boundary.
2443 ; CHECK-LABEL: define ptr @test65b(
2444 ; CHECK: if.then:
2445 ; CHECK-NOT: @llvm.objc.autorelease
2446 ; CHECK: return:
2447 ; CHECK:   call ptr @llvm.objc.autorelease(
2448 ; CHECK: {{^}}}
2449 define ptr @test65b(i1 %x) {
2450 entry:
2451   %t = call ptr @llvm.objc.autoreleasePoolPush()
2452   br i1 %x, label %return, label %if.then
2454 if.then:                                          ; preds = %entry
2455   %c = call ptr @returner()
2456   %s = call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr %c) nounwind
2457   br label %return
2459 return:                                           ; preds = %if.then, %entry
2460   %retval = phi ptr [ %s, %if.then ], [ null, %entry ]
2461   call void @llvm.objc.autoreleasePoolPop(ptr %t)
2462   %q = call ptr @llvm.objc.autorelease(ptr %retval) nounwind
2463   ret ptr %retval
2466 ; Don't move an autoreleaseReuturnValue, which would break
2467 ; the RV optimization.
2469 ; CHECK-LABEL: define ptr @test65c(
2470 ; CHECK: if.then:
2471 ; CHECK-NOT: @llvm.objc.autorelease
2472 ; CHECK: return:
2473 ; CHECK:   call ptr @llvm.objc.autoreleaseReturnValue(
2474 ; CHECK: {{^}}}
2475 define ptr @test65c(i1 %x) {
2476 entry:
2477   br i1 %x, label %return, label %if.then
2479 if.then:                                          ; preds = %entry
2480   %c = call ptr @returner()
2481   %s = call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr %c) nounwind
2482   br label %return
2484 return:                                           ; preds = %if.then, %entry
2485   %retval = phi ptr [ %s, %if.then ], [ null, %entry ]
2486   %q = call ptr @llvm.objc.autoreleaseReturnValue(ptr %retval) nounwind
2487   ret ptr %retval
2490 ; CHECK-LABEL: define ptr @test65d(
2491 ; CHECK: if.then:
2492 ; CHECK-NOT: @llvm.objc.autorelease
2493 ; CHECK: return:
2494 ; CHECK:   call ptr @llvm.objc.autoreleaseReturnValue(
2495 ; CHECK: {{^}}}
2496 define ptr @test65d(i1 %x) {
2497 entry:
2498   br i1 %x, label %return, label %if.then
2500 if.then:                                          ; preds = %entry
2501   %c = call ptr @returner()
2502   %s = call ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue(ptr %c) nounwind
2503   br label %return
2505 return:                                           ; preds = %if.then, %entry
2506   %retval = phi ptr [ %s, %if.then ], [ null, %entry ]
2507   %q = call ptr @llvm.objc.autoreleaseReturnValue(ptr %retval) nounwind
2508   ret ptr %retval
2511 ; An llvm.objc.retain can serve as a may-use for a different pointer.
2512 ; rdar://11931823
2514 ; CHECK-LABEL: define void @test66a(
2515 ; CHECK:   tail call ptr @llvm.objc.retain(ptr %cond) [[NUW]]
2516 ; CHECK:   tail call void @llvm.objc.release(ptr %call) [[NUW]]
2517 ; CHECK:   tail call ptr @llvm.objc.retain(ptr %tmp8) [[NUW]]
2518 ; CHECK:   tail call void @llvm.objc.release(ptr %cond) [[NUW]]
2519 ; CHECK: {{^}}}
2520 define void @test66a(ptr %tmp5, ptr %bar, i1 %tobool, i1 %tobool1, ptr %call) {
2521 entry:
2522   br i1 %tobool, label %cond.true, label %cond.end
2524 cond.true:
2525   br label %cond.end
2527 cond.end:                                         ; preds = %cond.true, %entry
2528   %cond = phi ptr [ %tmp5, %cond.true ], [ %call, %entry ]
2529   %tmp7 = tail call ptr @llvm.objc.retain(ptr %cond) nounwind
2530   tail call void @llvm.objc.release(ptr %call) nounwind
2531   %tmp8 = select i1 %tobool1, ptr %cond, ptr %bar
2532   %tmp9 = tail call ptr @llvm.objc.retain(ptr %tmp8) nounwind
2533   tail call void @llvm.objc.release(ptr %cond) nounwind
2534   ret void
2537 ; CHECK-LABEL: define void @test66b(
2538 ; CHECK:   tail call ptr @llvm.objc.retain(ptr %cond) [[NUW]]
2539 ; CHECK:   tail call void @llvm.objc.release(ptr %call) [[NUW]]
2540 ; CHECK:   tail call ptr @llvm.objc.retain(ptr %tmp8) [[NUW]]
2541 ; CHECK:   tail call void @llvm.objc.release(ptr %cond) [[NUW]]
2542 ; CHECK: {{^}}}
2543 define void @test66b(ptr %tmp5, ptr %bar, i1 %tobool, i1 %tobool1, ptr %call) {
2544 entry:
2545   br i1 %tobool, label %cond.true, label %cond.end
2547 cond.true:
2548   br label %cond.end
2550 cond.end:                                         ; preds = %cond.true, %entry
2551   %cond = phi ptr [ %tmp5, %cond.true ], [ %call, %entry ]
2552   %tmp7 = tail call ptr @llvm.objc.retain(ptr %cond) nounwind
2553   tail call void @llvm.objc.release(ptr %call) nounwind, !clang.imprecise_release !0
2554   %tmp8 = select i1 %tobool1, ptr %cond, ptr %bar
2555   %tmp9 = tail call ptr @llvm.objc.retain(ptr %tmp8) nounwind
2556   tail call void @llvm.objc.release(ptr %cond) nounwind
2557   ret void
2560 ; CHECK-LABEL: define void @test66c(
2561 ; CHECK:   tail call ptr @llvm.objc.retain(ptr %cond) [[NUW]]
2562 ; CHECK:   tail call void @llvm.objc.release(ptr %call) [[NUW]]
2563 ; CHECK:   tail call ptr @llvm.objc.retain(ptr %tmp8) [[NUW]]
2564 ; CHECK:   tail call void @llvm.objc.release(ptr %cond) [[NUW]]
2565 ; CHECK: {{^}}}
2566 define void @test66c(ptr %tmp5, ptr %bar, i1 %tobool, i1 %tobool1, ptr %call) {
2567 entry:
2568   br i1 %tobool, label %cond.true, label %cond.end
2570 cond.true:
2571   br label %cond.end
2573 cond.end:                                         ; preds = %cond.true, %entry
2574   %cond = phi ptr [ %tmp5, %cond.true ], [ %call, %entry ]
2575   %tmp7 = tail call ptr @llvm.objc.retain(ptr %cond) nounwind
2576   tail call void @llvm.objc.release(ptr %call) nounwind
2577   %tmp8 = select i1 %tobool1, ptr %cond, ptr %bar
2578   %tmp9 = tail call ptr @llvm.objc.retain(ptr %tmp8) nounwind, !clang.imprecise_release !0
2579   tail call void @llvm.objc.release(ptr %cond) nounwind
2580   ret void
2583 ; CHECK-LABEL: define void @test66d(
2584 ; CHECK:   tail call ptr @llvm.objc.retain(ptr %cond) [[NUW]]
2585 ; CHECK:   tail call void @llvm.objc.release(ptr %call) [[NUW]]
2586 ; CHECK:   tail call ptr @llvm.objc.retain(ptr %tmp8) [[NUW]]
2587 ; CHECK:   tail call void @llvm.objc.release(ptr %cond) [[NUW]]
2588 ; CHECK: {{^}}}
2589 define void @test66d(ptr %tmp5, ptr %bar, i1 %tobool, i1 %tobool1, ptr %call) {
2590 entry:
2591   br i1 %tobool, label %cond.true, label %cond.end
2593 cond.true:
2594   br label %cond.end
2596 cond.end:                                         ; preds = %cond.true, %entry
2597   %cond = phi ptr [ %tmp5, %cond.true ], [ %call, %entry ]
2598   %tmp7 = tail call ptr @llvm.objc.retain(ptr %cond) nounwind
2599   tail call void @llvm.objc.release(ptr %call) nounwind, !clang.imprecise_release !0
2600   %tmp8 = select i1 %tobool1, ptr %cond, ptr %bar
2601   %tmp9 = tail call ptr @llvm.objc.retain(ptr %tmp8) nounwind
2602   tail call void @llvm.objc.release(ptr %cond) nounwind, !clang.imprecise_release !0
2603   ret void
2606 ; A few real-world testcases.
2608 @.str4 = private unnamed_addr constant [33 x i8] c"-[A z] = { %f, %f, { %f, %f } }\0A\00"
2609 @"OBJC_IVAR_$_A.myZ" = global i64 20, section "__DATA, __objc_const", align 8
2610 declare i32 @printf(ptr nocapture, ...) nounwind
2611 declare i32 @puts(ptr nocapture) nounwind
2612 @str = internal constant [16 x i8] c"-[ Top0 _getX ]\00"
2614 ; FIXME: Should be able to eliminate the retain and release
2615 ; CHECK-LABEL: define { <2 x float>, <2 x float> } @"\01-[A z]"(ptr %self, ptr nocapture %_cmd)
2616 ; CHECK: tail call ptr @llvm.objc.retain(ptr %self)
2617 ; CHECK-NEXT: %call = tail call i32 (ptr, ...) @printf(
2618 ; CHECK: tail call void @llvm.objc.release(ptr %self)
2619 ; CHECK: {{^}}}
2620 define { <2 x float>, <2 x float> } @"\01-[A z]"(ptr %self, ptr nocapture %_cmd) nounwind {
2621 invoke.cont:
2622   %i1 = tail call ptr @llvm.objc.retain(ptr %self) nounwind
2623   tail call void @llvm.dbg.value(metadata ptr %self, metadata !DILocalVariable(scope: !2), metadata !DIExpression()), !dbg !DILocation(scope: !2)
2624   tail call void @llvm.dbg.value(metadata ptr %self, metadata !DILocalVariable(scope: !2), metadata !DIExpression()), !dbg !DILocation(scope: !2)
2625   %ivar = load i64, ptr @"OBJC_IVAR_$_A.myZ", align 8
2626   %add.ptr = getelementptr i8, ptr %self, i64 %ivar
2627   %tmp2 = load float, ptr %add.ptr, align 4
2628   %conv = fpext float %tmp2 to double
2629   %add.ptr.sum = add i64 %ivar, 4
2630   %tmp6 = getelementptr inbounds i8, ptr %self, i64 %add.ptr.sum
2631   %tmp7 = load float, ptr %tmp6, align 4
2632   %conv8 = fpext float %tmp7 to double
2633   %add.ptr.sum36 = add i64 %ivar, 8
2634   %tmp12 = getelementptr inbounds i8, ptr %self, i64 %add.ptr.sum36
2635   %tmp13 = load float, ptr %tmp12, align 4
2636   %conv14 = fpext float %tmp13 to double
2637   %tmp12.sum = add i64 %ivar, 12
2638   %arrayidx19 = getelementptr inbounds i8, ptr %self, i64 %tmp12.sum
2639   %tmp20 = load float, ptr %arrayidx19, align 4
2640   %conv21 = fpext float %tmp20 to double
2641   %call = tail call i32 (ptr, ...) @printf(ptr @.str4, double %conv, double %conv8, double %conv14, double %conv21)
2642   %ivar23 = load i64, ptr @"OBJC_IVAR_$_A.myZ", align 8
2643   %add.ptr24 = getelementptr i8, ptr %self, i64 %ivar23
2644   %srcval = load i128, ptr %add.ptr24, align 4
2645   tail call void @llvm.objc.release(ptr %self) nounwind
2646   %tmp29 = trunc i128 %srcval to i64
2647   %tmp30 = bitcast i64 %tmp29 to <2 x float>
2648   %tmp31 = insertvalue { <2 x float>, <2 x float> } undef, <2 x float> %tmp30, 0
2649   %tmp32 = lshr i128 %srcval, 64
2650   %tmp33 = trunc i128 %tmp32 to i64
2651   %tmp34 = bitcast i64 %tmp33 to <2 x float>
2652   %tmp35 = insertvalue { <2 x float>, <2 x float> } %tmp31, <2 x float> %tmp34, 1
2653   ret { <2 x float>, <2 x float> } %tmp35
2656 ; FIXME: Should be able to eliminate the retain and release
2657 ; CHECK-LABEL: @"\01-[Top0 _getX]"(ptr %self, ptr nocapture %_cmd)
2658 ; CHECK: tail call ptr @llvm.objc.retain(ptr %self)
2659 ; CHECK: %puts = tail call i32 @puts
2660 ; CHECK: tail call void @llvm.objc.release(ptr %self)
2661 define i32 @"\01-[Top0 _getX]"(ptr %self, ptr nocapture %_cmd) nounwind {
2662 invoke.cont:
2663   %i1 = tail call ptr @llvm.objc.retain(ptr %self) nounwind
2664   %puts = tail call i32 @puts(ptr @str)
2665   tail call void @llvm.objc.release(ptr %self) nounwind
2666   ret i32 0
2669 @"\01L_OBJC_METH_VAR_NAME_" = internal global [5 x i8] c"frob\00", section "__TEXT,__cstring,cstring_literals", align 1@"\01L_OBJC_SELECTOR_REFERENCES_" = internal global ptr @"\01L_OBJC_METH_VAR_NAME_", section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
2670 @"\01L_OBJC_IMAGE_INFO" = internal constant [2 x i32] [i32 0, i32 16], section "__DATA, __objc_imageinfo, regular, no_dead_strip"
2671 @llvm.used = appending global [3 x ptr] [ptr @"\01L_OBJC_METH_VAR_NAME_", ptr @"\01L_OBJC_SELECTOR_REFERENCES_", ptr @"\01L_OBJC_IMAGE_INFO"], section "llvm.metadata"
2673 ; A simple loop. Eliminate the retain and release inside of it!
2675 ; CHECK: define void @loop(ptr %x, i64 %n) {
2676 ; CHECK: for.body:
2677 ; CHECK-NOT: @llvm.objc.
2678 ; CHECK: @objc_msgSend
2679 ; CHECK-NOT: @llvm.objc.
2680 ; CHECK: for.end:
2681 ; CHECK: {{^}}}
2682 define void @loop(ptr %x, i64 %n) {
2683 entry:
2684   %0 = tail call ptr @llvm.objc.retain(ptr %x) nounwind
2685   %cmp9 = icmp sgt i64 %n, 0
2686   br i1 %cmp9, label %for.body, label %for.end
2688 for.body:                                         ; preds = %entry, %for.body
2689   %i.010 = phi i64 [ %inc, %for.body ], [ 0, %entry ]
2690   %1 = tail call ptr @llvm.objc.retain(ptr %x) nounwind
2691   %tmp5 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
2692   %call = tail call ptr (ptr, ptr, ...) @objc_msgSend(ptr %1, ptr %tmp5)
2693   tail call void @llvm.objc.release(ptr %1) nounwind, !clang.imprecise_release !0
2694   %inc = add nsw i64 %i.010, 1
2695   %exitcond = icmp eq i64 %inc, %n
2696   br i1 %exitcond, label %for.end, label %for.body
2698 for.end:                                          ; preds = %for.body, %entry
2699   tail call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
2700   ret void
2703 ; ObjCARCOpt can delete the retain,release on self.
2705 ; CHECK: define void @TextEditTest(ptr %self, ptr %pboard) {
2706 ; CHECK-NOT: call ptr @llvm.objc.retain(ptr %tmp7)
2707 ; CHECK: {{^}}}
2709 %0 = type { ptr, ptr }
2710 %1 = type opaque
2711 %2 = type opaque
2712 %3 = type opaque
2713 %4 = type opaque
2714 %5 = type opaque
2715 %struct.NSConstantString = type { ptr, i32, ptr, i64 }
2716 %struct._NSRange = type { i64, i64 }
2717 %struct.__CFString = type opaque
2718 %struct.__method_list_t = type { i32, i32, [0 x %struct._objc_method] }
2719 %struct._class_ro_t = type { i32, i32, i32, ptr, ptr, ptr, ptr, ptr, ptr, ptr }
2720 %struct._class_t = type { ptr, ptr, ptr, ptr, ptr }
2721 %struct._ivar_list_t = type { i32, i32, [0 x %struct._ivar_t] }
2722 %struct._ivar_t = type { ptr, ptr, ptr, i32, i32 }
2723 %struct._message_ref_t = type { ptr, ptr }
2724 %struct._objc_cache = type opaque
2725 %struct._objc_method = type { ptr, ptr, ptr }
2726 %struct._objc_protocol_list = type { i64, [0 x ptr] }
2727 %struct._prop_list_t = type { i32, i32, [0 x %struct._message_ref_t] }
2728 %struct._protocol_t = type { ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, i32, i32 }
2730 @"\01L_OBJC_CLASSLIST_REFERENCES_$_17" = external hidden global ptr, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8
2731 @kUTTypePlainText = external constant ptr
2732 @"\01L_OBJC_SELECTOR_REFERENCES_19" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
2733 @"\01L_OBJC_SELECTOR_REFERENCES_21" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
2734 @"\01L_OBJC_SELECTOR_REFERENCES_23" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
2735 @"\01L_OBJC_SELECTOR_REFERENCES_25" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
2736 @"\01L_OBJC_CLASSLIST_REFERENCES_$_26" = external hidden global ptr, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8
2737 @"\01L_OBJC_SELECTOR_REFERENCES_28" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
2738 @"\01L_OBJC_CLASSLIST_REFERENCES_$_29" = external hidden global ptr, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8
2739 @"\01L_OBJC_SELECTOR_REFERENCES_31" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
2740 @"\01L_OBJC_SELECTOR_REFERENCES_33" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
2741 @"\01L_OBJC_SELECTOR_REFERENCES_35" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
2742 @"\01L_OBJC_SELECTOR_REFERENCES_37" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
2743 @"\01L_OBJC_CLASSLIST_REFERENCES_$_38" = external hidden global ptr, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8
2744 @"\01L_OBJC_SELECTOR_REFERENCES_40" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
2745 @"\01L_OBJC_SELECTOR_REFERENCES_42" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
2746 @_unnamed_cfstring_44 = external hidden constant %struct.NSConstantString, section "__DATA,__cfstring"
2747 @"\01L_OBJC_SELECTOR_REFERENCES_46" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
2748 @"\01L_OBJC_SELECTOR_REFERENCES_48" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
2749 @"\01l_objc_msgSend_fixup_isEqual_" = external hidden global %0, section "__DATA, __objc_msgrefs, coalesced", align 16
2750 @"\01L_OBJC_CLASSLIST_REFERENCES_$_50" = external hidden global ptr, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8
2751 @NSCocoaErrorDomain = external constant ptr
2752 @"\01L_OBJC_CLASSLIST_REFERENCES_$_51" = external hidden global ptr, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8
2753 @NSFilePathErrorKey = external constant ptr
2754 @"\01L_OBJC_SELECTOR_REFERENCES_53" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
2755 @"\01L_OBJC_SELECTOR_REFERENCES_55" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
2756 @"\01L_OBJC_CLASSLIST_REFERENCES_$_56" = external hidden global ptr, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8
2757 @"\01L_OBJC_SELECTOR_REFERENCES_58" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
2758 @"\01L_OBJC_SELECTOR_REFERENCES_60" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
2760 declare ptr @truncatedString(ptr, i64)
2761 define void @TextEditTest(ptr %self, ptr %pboard) {
2762 entry:
2763   %err = alloca ptr, align 8
2764   %tmp8 = call ptr @llvm.objc.retain(ptr %self) nounwind
2765   store ptr null, ptr %err, align 8
2766   %tmp1 = load ptr, ptr @"\01L_OBJC_CLASSLIST_REFERENCES_$_17", align 8
2767   %tmp2 = load ptr, ptr @kUTTypePlainText, align 8
2768   %tmp3 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_19", align 8
2769   %call5 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %tmp1, ptr %tmp3, ptr %tmp2)
2770   %tmp5 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_21", align 8
2771   %call76 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %pboard, ptr %tmp5, ptr %call5)
2772   %tmp9 = call ptr @llvm.objc.retain(ptr %call76) nounwind
2773   %tobool = icmp eq ptr %tmp9, null
2774   br i1 %tobool, label %end, label %land.lhs.true
2776 land.lhs.true:                                    ; preds = %entry
2777   %tmp11 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_23", align 8
2778   %call137 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %pboard, ptr %tmp11, ptr %tmp9)
2779   %tmp10 = call ptr @llvm.objc.retain(ptr %call137) nounwind
2780   call void @llvm.objc.release(ptr null) nounwind
2781   %tmp12 = call ptr @llvm.objc.retain(ptr %call137) nounwind
2782   call void @llvm.objc.release(ptr null) nounwind
2783   %tobool16 = icmp eq ptr %call137, null
2784   br i1 %tobool16, label %end, label %if.then
2786 if.then:                                          ; preds = %land.lhs.true
2787   %tmp19 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_25", align 8
2788   %call21 = call signext i8 @objc_msgSend(ptr %call137, ptr %tmp19)
2789   %tobool22 = icmp eq i8 %call21, 0
2790   br i1 %tobool22, label %if.then44, label %land.lhs.true23
2792 land.lhs.true23:                                  ; preds = %if.then
2793   %tmp24 = load ptr, ptr @"\01L_OBJC_CLASSLIST_REFERENCES_$_26", align 8
2794   %tmp26 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_28", align 8
2795   %call2822 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %tmp24, ptr %tmp26, ptr %call137)
2796   %tmp14 = call ptr @llvm.objc.retain(ptr %call2822) nounwind
2797   call void @llvm.objc.release(ptr null) nounwind
2798   %tobool30 = icmp eq ptr %call2822, null
2799   br i1 %tobool30, label %if.then44, label %if.end
2801 if.end:                                           ; preds = %land.lhs.true23
2802   %tmp32 = load ptr, ptr @"\01L_OBJC_CLASSLIST_REFERENCES_$_29", align 8
2803   %tmp33 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_31", align 8
2804   %call35 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %tmp32, ptr %tmp33)
2805   %tmp37 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_33", align 8
2806   %call3923 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %call35, ptr %tmp37, ptr %call2822, i32 signext 1, ptr %err)
2807   %cmp = icmp eq ptr %call3923, null
2808   br i1 %cmp, label %if.then44, label %end
2810 if.then44:                                        ; preds = %if.end, %land.lhs.true23, %if.then
2811   %url.025 = phi ptr [ %call2822, %if.end ], [ %call2822, %land.lhs.true23 ], [ null, %if.then ]
2812   %tmp49 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_35", align 8
2813   %call51 = call %struct._NSRange @objc_msgSend(ptr %call137, ptr %tmp49, i64 0, i64 0)
2814   %call513 = extractvalue %struct._NSRange %call51, 0
2815   %call514 = extractvalue %struct._NSRange %call51, 1
2816   %tmp52 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_37", align 8
2817   %call548 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %call137, ptr %tmp52, i64 %call513, i64 %call514)
2818   %tmp55 = load ptr, ptr @"\01L_OBJC_CLASSLIST_REFERENCES_$_38", align 8
2819   %tmp56 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_40", align 8
2820   %call58 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %tmp55, ptr %tmp56)
2821   %tmp59 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_42", align 8
2822   %call6110 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %call548, ptr %tmp59, ptr %call58)
2823   %tmp15 = call ptr @llvm.objc.retain(ptr %call6110) nounwind
2824   call void @llvm.objc.release(ptr %call137) nounwind
2825   %tmp64 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_46", align 8
2826   %call66 = call signext i8 @objc_msgSend(ptr %call6110, ptr %tmp64, ptr @_unnamed_cfstring_44)
2827   %tobool67 = icmp eq i8 %call66, 0
2828   br i1 %tobool67, label %if.end74, label %if.then68
2830 if.then68:                                        ; preds = %if.then44
2831   %tmp70 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_48", align 8
2832   %call7220 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %call6110, ptr %tmp70)
2833   %tmp16 = call ptr @llvm.objc.retain(ptr %call7220) nounwind
2834   call void @llvm.objc.release(ptr %call6110) nounwind
2835   br label %if.end74
2837 if.end74:                                         ; preds = %if.then68, %if.then44
2838   %filename.0.in = phi ptr [ %call7220, %if.then68 ], [ %call6110, %if.then44 ]
2839   %tmp17 = load ptr, ptr @"\01l_objc_msgSend_fixup_isEqual_", align 16
2840   %call78 = call signext i8 (ptr, ptr, ptr, ...) %tmp17(ptr %call137, ptr @"\01l_objc_msgSend_fixup_isEqual_", ptr %filename.0.in)
2841   %tobool79 = icmp eq i8 %call78, 0
2842   br i1 %tobool79, label %land.lhs.true80, label %if.then109
2844 land.lhs.true80:                                  ; preds = %if.end74
2845   %tmp82 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_25", align 8
2846   %call84 = call signext i8 @objc_msgSend(ptr %filename.0.in, ptr %tmp82)
2847   %tobool86 = icmp eq i8 %call84, 0
2848   br i1 %tobool86, label %if.then109, label %if.end106
2850 if.end106:                                        ; preds = %land.lhs.true80
2851   %tmp88 = load ptr, ptr @"\01L_OBJC_CLASSLIST_REFERENCES_$_26", align 8
2852   %tmp90 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_28", align 8
2853   %call9218 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %tmp88, ptr %tmp90, ptr %filename.0.in)
2854   %tmp21 = call ptr @llvm.objc.retain(ptr %call9218) nounwind
2855   call void @llvm.objc.release(ptr %url.025) nounwind
2856   %tmp94 = load ptr, ptr @"\01L_OBJC_CLASSLIST_REFERENCES_$_29", align 8
2857   %tmp95 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_31", align 8
2858   %call97 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %tmp94, ptr %tmp95)
2859   %tmp99 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_33", align 8
2860   %call10119 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %call97, ptr %tmp99, ptr %call9218, i32 signext 1, ptr %err)
2861   %phitmp = icmp eq ptr %call10119, null
2862   br i1 %phitmp, label %if.then109, label %end
2864 if.then109:                                       ; preds = %if.end106, %land.lhs.true80, %if.end74
2865   %url.129 = phi ptr [ %call9218, %if.end106 ], [ %url.025, %if.end74 ], [ %url.025, %land.lhs.true80 ]
2866   %tmp110 = load ptr, ptr %err, align 8
2867   %tobool111 = icmp eq ptr %tmp110, null
2868   br i1 %tobool111, label %if.then112, label %if.end125
2870 if.then112:                                       ; preds = %if.then109
2871   %tmp113 = load ptr, ptr @"\01L_OBJC_CLASSLIST_REFERENCES_$_50", align 8
2872   %tmp114 = load ptr, ptr @NSCocoaErrorDomain, align 8
2873   %tmp115 = load ptr, ptr @"\01L_OBJC_CLASSLIST_REFERENCES_$_51", align 8
2874   %call117 = call ptr @truncatedString(ptr %filename.0.in, i64 1034)
2875   %tmp118 = load ptr, ptr @NSFilePathErrorKey, align 8
2876   %tmp119 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_53", align 8
2877   %call12113 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %tmp115, ptr %tmp119, ptr %call117, ptr %tmp118, ptr null)
2878   %tmp122 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_55", align 8
2879   %call12414 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %tmp113, ptr %tmp122, ptr %tmp114, i64 258, ptr %call12113)
2880   %tmp23 = call ptr @llvm.objc.retain(ptr %call12414) nounwind
2881   %tmp25 = call ptr @llvm.objc.autorelease(ptr %tmp23) nounwind
2882   store ptr %tmp25, ptr %err, align 8
2883   br label %if.end125
2885 if.end125:                                        ; preds = %if.then112, %if.then109
2886   %tmp127 = phi ptr [ %tmp110, %if.then109 ], [ %tmp25, %if.then112 ]
2887   %tmp126 = load ptr, ptr @"\01L_OBJC_CLASSLIST_REFERENCES_$_56", align 8
2888   %tmp128 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_58", align 8
2889   %call13015 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %tmp126, ptr %tmp128, ptr %tmp127)
2890   %tmp131 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_60", align 8
2891   %call13317 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %call13015, ptr %tmp131)
2892   br label %end
2894 end:                                              ; preds = %if.end125, %if.end106, %if.end, %land.lhs.true, %entry
2895   %filename.2 = phi ptr [ %filename.0.in, %if.end106 ], [ %filename.0.in, %if.end125 ], [ %call137, %land.lhs.true ], [ null, %entry ], [ %call137, %if.end ]
2896   %origFilename.0 = phi ptr [ %call137, %if.end106 ], [ %call137, %if.end125 ], [ %call137, %land.lhs.true ], [ null, %entry ], [ %call137, %if.end ]
2897   %url.2 = phi ptr [ %call9218, %if.end106 ], [ %url.129, %if.end125 ], [ null, %land.lhs.true ], [ null, %entry ], [ %call2822, %if.end ]
2898   call void @llvm.objc.release(ptr %tmp9) nounwind, !clang.imprecise_release !0
2899   call void @llvm.objc.release(ptr %url.2) nounwind, !clang.imprecise_release !0
2900   call void @llvm.objc.release(ptr %origFilename.0) nounwind, !clang.imprecise_release !0
2901   call void @llvm.objc.release(ptr %filename.2) nounwind, !clang.imprecise_release !0
2902   call void @llvm.objc.release(ptr %self) nounwind, !clang.imprecise_release !0
2903   ret void
2906 declare i32 @__gxx_personality_v0(...)
2908 declare i32 @llvm.objc.sync.enter(ptr)
2909 declare i32 @llvm.objc.sync.exit(ptr)
2911 ; Make sure that we understand that objc_sync_{enter,exit} are IC_User not
2912 ; IC_Call/IC_CallOrUser.
2914 ; CHECK-LABEL:      define void @test67(
2915 ; CHECK-NEXT:   call i32 @llvm.objc.sync.enter(ptr %x)
2916 ; CHECK-NEXT:   call i32 @llvm.objc.sync.exit(ptr %x)
2917 ; CHECK-NEXT:   ret void
2918 ; CHECK-NEXT: }
2919 define void @test67(ptr %x) {
2920   call ptr @llvm.objc.retain(ptr %x)
2921   call i32 @llvm.objc.sync.enter(ptr %x)
2922   call i32 @llvm.objc.sync.exit(ptr %x)
2923   call void @llvm.objc.release(ptr %x), !clang.imprecise_release !0
2924   ret void
2927 ; CHECK-LABEL: define void @test68(
2928 ; CHECK-NOT:     call
2929 ; CHECK:         call void @callee2(
2930 ; CHECK-NOT:     call
2931 ; CHECK:         ret void
2933 define void @test68(ptr %a, ptr %b) {
2934   call ptr @llvm.objc.retain(ptr %a)
2935   call ptr @llvm.objc.retain(ptr %b)
2936   call void @callee2(ptr %a, ptr %b)
2937   call void @llvm.objc.release(ptr %b), !clang.imprecise_release !0
2938   call void @llvm.objc.release(ptr %a), !clang.imprecise_release !0
2939   ret void
2942 !llvm.module.flags = !{!1}
2943 !llvm.dbg.cu = !{!3}
2945 !0 = !{}
2946 !1 = !{i32 1, !"Debug Info Version", i32 3}
2947 !2 = distinct !DISubprogram(unit: !3)
2948 !3 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang",
2949                              file: !4,
2950                              isOptimized: true, flags: "-O2",
2951                              splitDebugFilename: "abc.debug", emissionKind: 2)
2952 !4 = !DIFile(filename: "path/to/file", directory: "/path/to/dir")
2953 !5 = !{i32 2, !"Debug Info Version", i32 3}
2955 ; CHECK: attributes [[NUW]] = { nounwind }
2956 ; CHECK: ![[RELEASE]] = !{}