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
38 define void @test0_precise(ptr %x, i1 %p) nounwind {
40 %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
41 br i1 %p, label %t, label %f
45 store float 2.0, ptr %x
53 call void @llvm.objc.release(ptr %x) nounwind
57 ; CHECK: define void @test0_imprecise(ptr %x, i1 %p) [[NUW]] {
58 ; CHECK-NOT: @llvm.objc.
60 define void @test0_imprecise(ptr %x, i1 %p) nounwind {
62 %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
63 br i1 %p, label %t, label %f
67 store float 2.0, ptr %x
75 call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
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)
88 define void @test1_precise(ptr %x, i1 %p, i1 %q) nounwind {
90 %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
91 br i1 %p, label %t, label %f
95 store float 2.0, ptr %x
101 br i1 %q, label %return, label %alt_return
104 call void @llvm.objc.release(ptr %x) nounwind
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
115 define void @test1_imprecise(ptr %x, i1 %p, i1 %q) nounwind {
117 %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
118 br i1 %p, label %t, label %f
122 store float 2.0, ptr %x
128 br i1 %q, label %return, label %alt_return
131 call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
139 ; Don't do partial elimination into two different CFG diamonds.
141 ; CHECK: define void @test1b_precise(ptr %x, i1 %p, i1 %q) {
143 ; CHECK: tail call ptr @llvm.objc.retain(ptr %x) [[NUW]]
144 ; CHECK-NOT: @llvm.objc.
146 ; CHECK: tail call void @llvm.objc.release(ptr %x) [[NUW]]
147 ; CHECK-NOT: @llvm.objc.
149 define void @test1b_precise(ptr %x, i1 %p, i1 %q) {
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()
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)
165 if.end5: ; preds = %if.then3, %if.end
166 tail call void @llvm.objc.release(ptr %x) nounwind
170 ; CHECK-LABEL: define void @test1b_imprecise(
172 ; CHECK: tail call ptr @llvm.objc.retain(ptr %x) [[NUW:#[0-9]+]]
173 ; CHECK-NOT: @llvm.objc.
175 ; CHECK: tail call void @llvm.objc.release(ptr %x) [[NUW]], !clang.imprecise_release ![[RELEASE:[0-9]+]]
176 ; CHECK-NOT: @llvm.objc.
178 define void @test1b_imprecise(ptr %x, i1 %p, i1 %q) {
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()
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)
194 if.end5: ; preds = %if.then3, %if.end
195 tail call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
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
207 define void @test2_precise(ptr %x, i1 %p) nounwind {
209 %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
210 br i1 %p, label %t, label %f
214 store float 2.0, ptr %x
219 call void @use_pointer(ptr %0)
220 store float 3.0, ptr %x
224 call void @llvm.objc.release(ptr %x) nounwind
228 ; CHECK-LABEL: define void @test2_imprecise(
229 ; CHECK: @llvm.objc.retain(ptr %x)
230 ; CHECK: @llvm.objc.release
232 define void @test2_imprecise(ptr %x, i1 %p) nounwind {
234 %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
235 br i1 %p, label %t, label %f
239 store float 2.0, ptr %x
244 call void @use_pointer(ptr %0)
245 store float 3.0, ptr %x
249 call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
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
262 define void @test3_precise(ptr %x, ptr %q) nounwind {
264 %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
268 call void @llvm.objc.release(ptr %x) nounwind
269 %j = load volatile i1, ptr %q
270 br i1 %j, label %loop, label %return
276 ; CHECK-LABEL: define void @test3_imprecise(
277 ; TODO: @llvm.objc.retain(ptr %a)
278 ; TODO: @llvm.objc.release
280 define void @test3_imprecise(ptr %x, ptr %q) nounwind {
282 %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
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
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
304 define void @test4_precise(ptr %x, ptr %q) nounwind {
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
314 call void @llvm.objc.release(ptr %x) nounwind
318 ; CHECK-LABEL: define void @test4_imprecise(
319 ; TODO: @llvm.objc.retain(ptr %a)
320 ; TODO: @llvm.objc.release
322 define void @test4_imprecise(ptr %x, ptr %q) nounwind {
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
332 call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
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
344 define void @test5a(ptr %x, i1 %q, ptr %y) nounwind {
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)
350 call void @llvm.objc.release(ptr %x) nounwind
354 ; CHECK-LABEL: define void @test5b(
355 ; CHECK: @llvm.objc.retain(ptr
356 ; CHECK: @llvm.objc.release
358 define void @test5b(ptr %x, i1 %q, ptr %y) nounwind {
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)
364 call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
369 ; retain+release pair deletion, where the release happens on two different
372 ; CHECK-LABEL: define void @test6a(
374 ; CHECK: tail call ptr @llvm.objc.retain
376 ; CHECK: call void @llvm.objc.release
378 ; CHECK: call void @llvm.objc.release
381 define void @test6a(ptr %x, i1 %p) nounwind {
383 %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
384 br i1 %p, label %t, label %f
388 store float 2.0, ptr %x
389 call void @llvm.objc.release(ptr %x) nounwind
395 call void @llvm.objc.release(ptr %x) nounwind
402 ; CHECK-LABEL: define void @test6b(
403 ; CHECK-NOT: @llvm.objc.
405 define void @test6b(ptr %x, i1 %p) nounwind {
407 %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
408 br i1 %p, label %t, label %f
412 store float 2.0, ptr %x
413 call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
419 call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
426 ; CHECK-LABEL: define void @test6c(
428 ; CHECK: tail call ptr @llvm.objc.retain
430 ; CHECK: call void @llvm.objc.release
432 ; CHECK: call void @llvm.objc.release
435 define void @test6c(ptr %x, i1 %p) nounwind {
437 %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
438 br i1 %p, label %t, label %f
442 store float 2.0, ptr %x
443 call void @llvm.objc.release(ptr %x) nounwind
449 call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
456 ; CHECK-LABEL: define void @test6d(
458 ; CHECK: tail call ptr @llvm.objc.retain
460 ; CHECK: call void @llvm.objc.release
462 ; CHECK: call void @llvm.objc.release
465 define void @test6d(ptr %x, i1 %p) nounwind {
467 %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
468 br i1 %p, label %t, label %f
472 store float 2.0, ptr %x
473 call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
479 call void @llvm.objc.release(ptr %x) nounwind
487 ; retain+release pair deletion, where the retain happens on two different
490 ; CHECK-LABEL: define void @test7(
492 ; CHECK-NOT: llvm.objc.
494 ; CHECK: call ptr @llvm.objc.retain
496 ; CHECK: call ptr @llvm.objc.retain
498 ; CHECK: call void @llvm.objc.release
500 define void @test7(ptr %x, i1 %p) nounwind {
502 br i1 %p, label %t, label %f
505 %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
507 store float 2.0, ptr %x
511 %1 = call ptr @llvm.objc.retain(ptr %x) nounwind
517 call void @llvm.objc.release(ptr %x) nounwind
521 ; CHECK-LABEL: define void @test7b(
522 ; CHECK-NOT: @llvm.objc.
524 define void @test7b(ptr %x, i1 %p) nounwind {
526 br i1 %p, label %t, label %f
529 %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
531 store float 2.0, ptr %x
535 %1 = call ptr @llvm.objc.retain(ptr %x) nounwind
541 call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
545 ; Like test7, but there's a retain/retainBlock mismatch. Don't delete!
547 ; CHECK-LABEL: define void @test7c(
549 ; CHECK: call ptr @llvm.objc.retainBlock
551 ; CHECK: call ptr @llvm.objc.retain
553 ; CHECK: call void @llvm.objc.release
555 define void @test7c(ptr %x, i1 %p) nounwind {
557 br i1 %p, label %t, label %f
560 %0 = call ptr @llvm.objc.retainBlock(ptr %x) nounwind
562 store float 2.0, ptr %x
566 %1 = call ptr @llvm.objc.retain(ptr %x) nounwind
572 call void @llvm.objc.release(ptr %x) nounwind
576 ; retain+release pair deletion, where the retain and release both happen on
577 ; different flow paths. Wild!
579 ; CHECK-LABEL: define void @test8a(
582 ; CHECK: @llvm.objc.retain
584 ; CHECK: @llvm.objc.retain
587 ; CHECK: @llvm.objc.release
589 ; CHECK: @llvm.objc.release
592 define void @test8a(ptr %x, i1 %p, i1 %q) nounwind {
594 br i1 %p, label %t, label %f
597 %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
599 store float 2.0, ptr %x
603 %1 = call ptr @llvm.objc.retain(ptr %x) nounwind
608 br i1 %q, label %u, label %g
612 call void @llvm.objc.release(ptr %x) nounwind
616 call void @llvm.objc.release(ptr %x) nounwind
623 ; CHECK-LABEL: define void @test8b(
624 ; CHECK-NOT: @llvm.objc.
626 define void @test8b(ptr %x, i1 %p, i1 %q) nounwind {
628 br i1 %p, label %t, label %f
631 %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
633 store float 2.0, ptr %x
637 %1 = call ptr @llvm.objc.retain(ptr %x) nounwind
642 br i1 %q, label %u, label %g
646 call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
650 call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
657 ; CHECK-LABEL: define void @test8c(
660 ; CHECK-NOT: @llvm.objc.
662 ; CHECK-NOT: @llvm.objc.
665 ; CHECK: @llvm.objc.retain
666 ; CHECK: @llvm.objc.release
668 ; CHECK-NOT: @llvm.objc.
671 define void @test8c(ptr %x, i1 %p, i1 %q) nounwind {
673 br i1 %p, label %t, label %f
676 %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
678 store float 2.0, ptr %x
682 %1 = call ptr @llvm.objc.retain(ptr %x) nounwind
687 br i1 %q, label %u, label %g
691 call void @llvm.objc.release(ptr %x) nounwind
695 call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
702 ; CHECK-LABEL: define void @test8d(
705 ; CHECK: @llvm.objc.retain
707 ; CHECK: @llvm.objc.retain
710 ; CHECK: @llvm.objc.release
712 ; CHECK: @llvm.objc.release
715 define void @test8d(ptr %x, i1 %p, i1 %q) nounwind {
717 br i1 %p, label %t, label %f
720 %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
722 store float 2.0, ptr %x
726 %1 = call ptr @llvm.objc.retain(ptr %x) nounwind
731 br i1 %q, label %u, label %g
735 call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
739 call void @llvm.objc.release(ptr %x) nounwind
746 ; Trivial retain+release pair deletion.
748 ; CHECK-LABEL: define void @test9(
749 ; CHECK-NOT: @llvm.objc.
751 define void @test9(ptr %x) nounwind {
753 %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
754 call void @llvm.objc.release(ptr %0) nounwind
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)
764 define void @test9b(ptr %x, i1 %j, ptr %p) nounwind {
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
772 ; Trivial retain+release pair with intervening calls - don't delete!
774 ; CHECK-LABEL: define void @test10(
775 ; CHECK: @llvm.objc.retain(ptr %x)
777 ; CHECK: @use_pointer
778 ; CHECK: @llvm.objc.release
780 define void @test10(ptr %x) nounwind {
782 %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
784 call void @use_pointer(ptr %x)
785 call void @llvm.objc.release(ptr %0) nounwind
789 ; Trivial retain+autoreleaserelease pair. Don't delete!
790 ; Also, add a tail keyword, since llvm.objc.retain can never be passed
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]]
797 define void @test11(ptr %x) nounwind {
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)
805 ; Same as test11 but with no use_pointer call. Delete the pair!
807 ; CHECK-LABEL: define void @test11a(
809 ; CHECK-NEXT: ret void
811 define void @test11a(ptr %x) nounwind {
813 %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
814 call ptr @llvm.objc.autorelease(ptr %0) nounwind
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]]
826 define ptr @test11b(ptr %x) nounwind {
828 %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
829 call ptr @llvm.objc.autorelease(ptr %0) nounwind
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(
838 ; CHECK-NEXT: @llvm.objc.retain(ptr %x)
839 ; CHECK-NEXT: @llvm.objc.retain
840 ; CHECK: @llvm.objc.release
842 define void @test12(ptr %x, i64 %n) {
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
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]]
860 define void @test13(ptr %x, i64 %n) {
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
869 ; Delete the retain+release pair.
871 ; CHECK-LABEL: define void @test13b(
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
880 define void @test13b(ptr %x, i64 %n) {
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
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
902 define void @test13c(ptr %x, i64 %n) {
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
913 ; Like test13c, but there's an autoreleasePoolPush in the way, but that
916 ; CHECK-LABEL: define void @test13d(
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
926 define void @test13d(ptr %x, i64 %n) {
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
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
943 ; CHECK-LABEL: define void @test14(
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
952 define void @test14(ptr %x, i64 %n) {
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
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(
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
973 define void @test15(ptr %x, i64 %n) {
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
982 ; Trivial retain,autorelease pair, post-dominated
983 ; by another release. Delete the retain and release.
985 ; CHECK-LABEL: define void @test15b(
987 ; CHECK-NEXT: @llvm.objc.retain
988 ; CHECK-NEXT: @llvm.objc.autorelease
989 ; CHECK-NEXT: @llvm.objc.release
990 ; CHECK-NEXT: ret void
992 define void @test15b(ptr %x, i64 %n) {
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
1000 ; CHECK-LABEL: define void @test15c(
1001 ; CHECK-NEXT: entry:
1002 ; CHECK-NEXT: @llvm.objc.autorelease
1003 ; CHECK-NEXT: ret void
1005 define void @test15c(ptr %x, i64 %n) {
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
1013 ; Retain+release pairs in diamonds, all dominated by a retain.
1015 ; CHECK-LABEL: define void @test16a(
1016 ; CHECK: @llvm.objc.retain(ptr %x)
1019 ; CHECK: @use_pointer
1020 ; CHECK: @llvm.objc.release
1022 define void @test16a(i1 %a, i1 %b, ptr %x) {
1024 call ptr @llvm.objc.retain(ptr %x) nounwind
1025 br i1 %a, label %red, label %orange
1028 call ptr @llvm.objc.retain(ptr %x) nounwind
1032 call ptr @llvm.objc.retain(ptr %x) nounwind
1036 call void @use_pointer(ptr %x)
1037 call void @use_pointer(ptr %x)
1038 br i1 %b, label %green, label %blue
1041 call void @llvm.objc.release(ptr %x) nounwind
1045 call void @llvm.objc.release(ptr %x) nounwind
1049 call void @use_pointer(ptr %x)
1050 call void @llvm.objc.release(ptr %x) nounwind
1054 ; CHECK-LABEL: define void @test16b(
1055 ; CHECK: @llvm.objc.retain(ptr %x)
1058 ; CHECK-NEXT: @use_pointer
1059 ; CHECK-NEXT: @use_pointer
1060 ; CHECK-NEXT: @llvm.objc.release
1062 define void @test16b(i1 %a, i1 %b, ptr %x) {
1064 call ptr @llvm.objc.retain(ptr %x) nounwind
1065 br i1 %a, label %red, label %orange
1068 call ptr @llvm.objc.retain(ptr %x) nounwind
1072 call ptr @llvm.objc.retain(ptr %x) nounwind
1076 call void @use_pointer(ptr %x)
1077 call void @use_pointer(ptr %x)
1078 br i1 %b, label %green, label %blue
1081 call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
1085 call void @llvm.objc.release(ptr %x) nounwind
1089 call void @use_pointer(ptr %x)
1090 call void @use_pointer(ptr %x)
1091 call void @llvm.objc.release(ptr %x) nounwind
1095 ; CHECK-LABEL: define void @test16c(
1096 ; CHECK: @llvm.objc.retain(ptr %x)
1099 ; CHECK: @use_pointer
1100 ; CHECK: @llvm.objc.release
1102 define void @test16c(i1 %a, i1 %b, ptr %x) {
1104 call ptr @llvm.objc.retain(ptr %x) nounwind
1105 br i1 %a, label %red, label %orange
1108 call ptr @llvm.objc.retain(ptr %x) nounwind
1112 call ptr @llvm.objc.retain(ptr %x) nounwind
1116 call void @use_pointer(ptr %x)
1117 call void @use_pointer(ptr %x)
1118 br i1 %b, label %green, label %blue
1121 call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
1125 call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
1129 call void @use_pointer(ptr %x)
1130 call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
1134 ; CHECK-LABEL: define void @test16d(
1135 ; CHECK: @llvm.objc.retain(ptr %x)
1138 define void @test16d(i1 %a, i1 %b, ptr %x) {
1140 call ptr @llvm.objc.retain(ptr %x) nounwind
1141 br i1 %a, label %red, label %orange
1144 call ptr @llvm.objc.retain(ptr %x) nounwind
1148 call ptr @llvm.objc.retain(ptr %x) nounwind
1152 call void @use_pointer(ptr %x)
1153 call void @use_pointer(ptr %x)
1154 br i1 %b, label %green, label %blue
1157 call void @llvm.objc.release(ptr %x) nounwind
1161 call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0
1170 ; CHECK-LABEL: define void @test18(
1171 ; CHECK-NOT: @llvm.objc.
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)
1180 ; Delete no-ops where undef can be assumed to be null.
1182 ; CHECK-LABEL: define void @test18b(
1183 ; CHECK-NOT: @llvm.objc.
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)
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)
1202 define void @test19(ptr %y) {
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)
1213 ; CHECK-LABEL: define void @test20(
1214 ; CHECK: %tmp1 = tail call ptr @llvm.objc.retain(ptr %self) [[NUW]]
1215 ; CHECK-NEXT: invoke
1217 define void @test20(ptr %self) personality ptr @__gxx_personality_v0 {
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}
1233 if.end: ; preds = %invoke.cont23
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
1244 define ptr @test21() {
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
1252 ; Move an objc call up through a phi that has null operands.
1254 ; CHECK-LABEL: define void @test22(
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
1261 define void @test22(ptr %p, i1 %a) {
1262 br i1 %a, label %A, label %B
1268 %h = phi ptr [ null, %A ], [ %p, %B ]
1269 call void @llvm.objc.release(ptr %h), !clang.imprecise_release !0
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]])
1279 define void @test22_precise(ptr %p, i1 %a) {
1280 br i1 %a, label %A, label %B
1286 %h = phi ptr [ null, %A ], [ %p, %B ]
1287 call void @llvm.objc.release(ptr %h)
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
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)
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(
1310 ; CHECK: call ptr @llvm.objc.retain(ptr %p)
1313 ; CHECK: call void @llvm.objc.release(ptr %p)
1315 define void @test25(ptr %p, i1 %x) {
1317 %f0 = call ptr @llvm.objc.retain(ptr %p)
1319 br i1 %x, label %true, label %done
1326 call void @llvm.objc.release(ptr %p)
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(
1335 ; CHECK: call ptr @llvm.objc.retain(ptr %p)
1338 ; CHECK: call void @llvm.objc.release(ptr %p)
1340 define void @test26(ptr %p, i1 %x) {
1342 %f0 = call ptr @llvm.objc.retain(ptr %p)
1343 br i1 %x, label %true, label %done
1351 call void @llvm.objc.release(ptr %p)
1355 ; Don't sink the retain,release into the loop.
1357 ; CHECK-LABEL: define void @test27(
1359 ; CHECK: call ptr @llvm.objc.retain(ptr %p)
1361 ; CHECK-NOT: @llvm.objc.
1363 ; CHECK: call void @llvm.objc.release
1365 define void @test27(ptr %p, i1 %x, i1 %y) {
1367 %f0 = call ptr @llvm.objc.retain(ptr %p)
1368 br i1 %x, label %loop, label %done
1373 br i1 %y, label %done, label %loop
1376 call void @llvm.objc.release(ptr %p)
1380 ; Trivial code motion case: Triangle.
1382 ; CHECK-LABEL: define void @test28(
1383 ; CHECK-NOT: @llvm.objc.
1385 ; CHECK: call ptr @llvm.objc.retain
1386 ; CHECK: call void @callee()
1388 ; CHECK: call void @llvm.objc.release
1390 ; CHECK-NOT: @llvm.objc.
1392 define void @test28(ptr %p, i1 %x) {
1394 %f0 = call ptr @llvm.objc.retain(ptr %p)
1395 br i1 %x, label %true, label %done
1403 call void @llvm.objc.release(ptr %p), !clang.imprecise_release !0
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
1413 ; CHECK-NOT: @llvm.objc.
1414 ; CHECK: call void @callee()
1415 ; CHECK-NOT: @llvm.objc.
1417 ; CHECK-NOT: @llvm.objc.
1419 ; CHECK: @llvm.objc.release
1421 define void @test28b(ptr %p, i1 %x, ptr noalias %t) {
1423 %f0 = call ptr @llvm.objc.retain(ptr %p)
1424 br i1 %x, label %true, label %done
1433 call void @llvm.objc.release(ptr %p)
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.
1443 ; CHECK: call ptr @llvm.objc.retain
1444 ; CHECK: call void @callee()
1446 ; CHECK: call void @llvm.objc.release(ptr %p) [[NUW]], !clang.imprecise_release
1448 ; CHECK-NOT: @llvm.objc.
1450 define void @test28c(ptr %p, i1 %x, ptr noalias %t) {
1452 %f0 = call ptr @llvm.objc.retain(ptr %p)
1453 br i1 %x, label %true, label %done
1462 call void @llvm.objc.release(ptr %p), !clang.imprecise_release !0
1466 ; Like test28. but with two releases.
1468 ; CHECK-LABEL: define void @test29(
1469 ; CHECK: call ptr @llvm.objc.retain
1471 ; CHECK: call void @callee()
1474 ; CHECK: call void @llvm.objc.release
1476 ; CHECK: call void @llvm.objc.release
1478 define void @test29(ptr %p, i1 %x, i1 %y) {
1480 %f0 = call ptr @llvm.objc.retain(ptr %p)
1481 br i1 %x, label %true, label %done
1486 br i1 %y, label %done, label %ohno
1489 call void @llvm.objc.release(ptr %p)
1493 call void @llvm.objc.release(ptr %p)
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
1503 ; CHECK: call void @callee()
1507 ; CHECK: call void @llvm.objc.release
1509 ; CHECK: call void @llvm.objc.release
1511 define void @test30(ptr %p, i1 %x, i1 %y, i1 %z) {
1513 %f0 = call ptr @llvm.objc.retain(ptr %p)
1514 br i1 %x, label %true, label %false
1519 br i1 %y, label %done, label %ohno
1522 br i1 %z, label %done, label %ohno
1525 call void @llvm.objc.release(ptr %p)
1529 call void @llvm.objc.release(ptr %p)
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()
1540 ; CHECK: call void @llvm.objc.release
1542 ; CHECK: call void @llvm.objc.release
1545 define void @test31(ptr %p, i1 %x) {
1547 %f0 = call ptr @llvm.objc.retain(ptr %p)
1550 br i1 %x, label %true, label %false
1552 call void @llvm.objc.release(ptr %p)
1555 call void @llvm.objc.release(ptr %p)
1559 ; Don't consider bitcasts or getelementptrs direct uses.
1561 ; CHECK-LABEL: define void @test32(
1562 ; CHECK: call ptr @llvm.objc.retain
1564 ; CHECK: call void @callee()
1567 ; CHECK: call void @llvm.objc.release
1569 define void @test32(ptr %p, i1 %x) {
1571 %f0 = call ptr @llvm.objc.retain(ptr %p)
1572 br i1 %x, label %true, label %done
1580 call void @llvm.objc.release(ptr %p)
1584 ; Do consider icmps to be direct uses.
1586 ; CHECK-LABEL: define void @test33(
1587 ; CHECK: call ptr @llvm.objc.retain
1589 ; CHECK: call void @callee()
1592 ; CHECK: call void @llvm.objc.release
1594 define void @test33(ptr %p, i1 %x, ptr %y) {
1596 %f0 = call ptr @llvm.objc.retain(ptr %p)
1597 br i1 %x, label %true, label %done
1601 %v = icmp eq ptr %p, %y
1605 call void @llvm.objc.release(ptr %p)
1609 ; Delete retain,release if there's just a possible dec and we have imprecise
1612 ; CHECK-LABEL: define void @test34a(
1613 ; CHECK: call ptr @llvm.objc.retain
1616 ; CHECK: call void @llvm.objc.release
1618 define void @test34a(ptr %p, i1 %x, ptr %y) {
1620 %f0 = call ptr @llvm.objc.retain(ptr %p)
1621 br i1 %x, label %true, label %done
1628 call void @llvm.objc.release(ptr %p)
1632 ; CHECK-LABEL: define void @test34b(
1633 ; CHECK-NOT: @llvm.objc.
1635 define void @test34b(ptr %p, i1 %x, ptr %y) {
1637 %f0 = call ptr @llvm.objc.retain(ptr %p)
1638 br i1 %x, label %true, label %done
1645 call void @llvm.objc.release(ptr %p), !clang.imprecise_release !0
1650 ; Delete retain,release if there's just a use and we do not have a precise
1654 ; CHECK-LABEL: define void @test35a(
1656 ; CHECK: call ptr @llvm.objc.retain
1659 ; CHECK: call void @llvm.objc.release
1661 define void @test35a(ptr %p, i1 %x, ptr %y) {
1663 %f0 = call ptr @llvm.objc.retain(ptr %p)
1664 br i1 %x, label %true, label %done
1667 %v = icmp eq ptr %p, %y
1671 call void @llvm.objc.release(ptr %p)
1676 ; CHECK-LABEL: define void @test35b(
1677 ; CHECK-NOT: @llvm.objc.
1679 define void @test35b(ptr %p, i1 %x, ptr %y) {
1681 %f0 = call ptr @llvm.objc.retain(ptr %p)
1682 br i1 %x, label %true, label %done
1685 %v = icmp eq ptr %p, %y
1689 call void @llvm.objc.release(ptr %p), !clang.imprecise_release !0
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
1702 define void @test36a(ptr %p) {
1704 call ptr @llvm.objc.retain(ptr %p)
1707 call void @llvm.objc.release(ptr %p)
1711 ; Like test36, but with metadata.
1713 ; CHECK-LABEL: define void @test36b(
1714 ; CHECK-NOT: @llvm.objc.
1716 define void @test36b(ptr %p) {
1718 call ptr @llvm.objc.retain(ptr %p)
1721 call void @llvm.objc.release(ptr %p), !clang.imprecise_release !0
1725 ; Be aggressive about analyzing phis to eliminate possible uses.
1727 ; CHECK-LABEL: define void @test38(
1728 ; CHECK-NOT: @llvm.objc.
1730 define void @test38(ptr %p, i1 %u, i1 %m, ptr %z, ptr %y, ptr %x, ptr %w) {
1732 call ptr @llvm.objc.retain(ptr %p)
1733 br i1 %u, label %true, label %false
1735 br i1 %m, label %a, label %b
1737 br i1 %m, label %c, label %d
1747 %j = phi ptr [ %z, %a ], [ %y, %b ]
1750 %k = phi ptr [ %w, %c ], [ %x, %d ]
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
1759 ; Delete retain,release pairs around loops.
1761 ; CHECK-LABEL: define void @test39(
1762 ; CHECK-NOT: @llvm.objc.
1764 define void @test39(ptr %p, i1 %arg) {
1766 %0 = call ptr @llvm.objc.retain(ptr %p)
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
1777 ; Delete retain,release pairs around loops containing uses.
1779 ; CHECK-LABEL: define void @test39b(
1780 ; CHECK-NOT: @llvm.objc.
1782 define void @test39b(ptr %p, i1 %arg) {
1784 %0 = call ptr @llvm.objc.retain(ptr %p)
1787 loop: ; preds = %loop, %entry
1789 br i1 %arg, label %loop, label %exit
1791 exit: ; preds = %loop
1792 call void @llvm.objc.release(ptr %0), !clang.imprecise_release !0
1796 ; Delete retain,release pairs around loops containing potential decrements.
1798 ; CHECK-LABEL: define void @test39c(
1799 ; CHECK-NOT: @llvm.objc.
1801 define void @test39c(ptr %p, i1 %arg) {
1803 %0 = call ptr @llvm.objc.retain(ptr %p)
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
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.
1821 define void @test40(ptr %p, i1 %arg) {
1823 %0 = call ptr @llvm.objc.retain(ptr %p)
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
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
1849 define void @test42(ptr %p) {
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)
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
1877 define void @test43(ptr %p) {
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)
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
1903 define void @test43b(ptr %p) {
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)
1917 ; Do retain+release elimination for non-provenance pointers.
1919 ; CHECK-LABEL: define void @test44(
1920 ; CHECK-NOT: llvm.objc.
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)
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)
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)
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]]
1953 ; CHECK: call ptr @llvm.objc.autorelease(ptr %p) [[NUW]]
1955 define void @test46(ptr %p, i1 %a) {
1957 call ptr @llvm.objc.retain(ptr %p)
1958 br i1 %a, label %true, label %false
1961 call ptr @llvm.objc.autorelease(ptr %p)
1962 call void @use_pointer(ptr %p)
1969 ; Delete no-op cast calls.
1971 ; CHECK-LABEL: define ptr @test47(
1975 define ptr @test47(ptr %p) nounwind {
1976 %x = call ptr @llvm.objc.retainedObject(ptr %p)
1980 ; Delete no-op cast calls.
1982 ; CHECK-LABEL: define ptr @test48(
1986 define ptr @test48(ptr %p) nounwind {
1987 %x = call ptr @llvm.objc.unretainedObject(ptr %p)
1991 ; Delete no-op cast calls.
1993 ; CHECK-LABEL: define ptr @test49(
1997 define ptr @test49(ptr %p) nounwind {
1998 %x = call ptr @llvm.objc.unretainedPointer(ptr %p)
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
2009 ; CHECK-NEXT: call void @llvm.objc.release
2010 ; CHECK-NEXT: ret void
2012 define void @test50a(ptr %p, ptr %pp) {
2013 call ptr @llvm.objc.retain(ptr %p)
2015 store ptr %p, ptr %pp
2016 call void @llvm.objc.release(ptr %p)
2020 ; CHECK-LABEL: define void @test50b(
2021 ; CHECK-NOT: @llvm.objc.
2023 define void @test50b(ptr %p, ptr %pp) {
2024 call ptr @llvm.objc.retain(ptr %p)
2026 store ptr %p, ptr %pp
2027 call void @llvm.objc.release(ptr %p), !clang.imprecise_release !0
2032 ; Don't delete retain+release with intervening stores through the
2035 ; CHECK-LABEL: define void @test51a(
2036 ; CHECK: call ptr @llvm.objc.retain(ptr %p)
2037 ; CHECK: call void @llvm.objc.release(ptr %p)
2040 define void @test51a(ptr %p) {
2041 call ptr @llvm.objc.retain(ptr %p)
2044 call void @llvm.objc.release(ptr %p)
2048 ; CHECK-LABEL: define void @test51b(
2049 ; CHECK: call ptr @llvm.objc.retain(ptr %p)
2050 ; CHECK: call void @llvm.objc.release(ptr %p)
2053 define void @test51b(ptr %p) {
2054 call ptr @llvm.objc.retain(ptr %p)
2057 call void @llvm.objc.release(ptr %p), !clang.imprecise_release !0
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
2071 define void @test52a(ptr %zz, ptr %pp) {
2072 %p = load ptr, ptr %pp
2073 %1 = call ptr @llvm.objc.retain(ptr %p)
2075 %z = load ptr, ptr %zz
2076 call void @use_pointer(ptr %z)
2077 call void @llvm.objc.release(ptr %p)
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
2088 define void @test52b(ptr %zz, ptr %pp) {
2089 %p = load ptr, ptr %pp
2090 %1 = call ptr @llvm.objc.retain(ptr %p)
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
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.
2106 define void @test53(ptr %zz, ptr %pp) {
2107 %p = load ptr, ptr %pp
2108 %1 = call ptr @llvm.objc.retain(ptr %p)
2110 %z = load ptr, ptr %zz
2111 call void @callee_fnptr(ptr %z)
2112 call void @llvm.objc.release(ptr %p)
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
2123 define void @test54() {
2124 %t = call ptr @returner()
2125 call ptr @llvm.objc.autorelease(ptr %t)
2129 ; Nested retain+release pairs. Delete them both.
2131 ; CHECK-LABEL: define void @test55(
2134 define void @test55(ptr %x) {
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
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(
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
2158 define void @test56(ptr %x, i32 %n) {
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
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
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
2193 define void @test57(ptr %x) nounwind {
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
2207 ; An adjacent retain+release pair is sufficient even if it will be
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
2217 define void @test58(ptr %x) nounwind {
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
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
2239 define void @test59(ptr %x) nounwind {
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
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
2262 define void @test60a() {
2263 %t = load ptr, ptr @constptr
2264 %s = load ptr, ptr @something
2265 call ptr @llvm.objc.retain(ptr %s)
2267 call void @use_pointer(ptr %t)
2268 call void @llvm.objc.release(ptr %s)
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
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)
2283 call void @use_pointer(ptr %s)
2284 call void @llvm.objc.release(ptr %t)
2288 ; CHECK-LABEL: define void @test60c(
2289 ; CHECK-NOT: @llvm.objc.
2291 define void @test60c() {
2292 %t = load ptr, ptr @constptr
2293 %s = load ptr, ptr @something
2294 call ptr @llvm.objc.retain(ptr %t)
2296 call void @use_pointer(ptr %s)
2297 call void @llvm.objc.release(ptr %t), !clang.imprecise_release !0
2301 ; CHECK-LABEL: define void @test60d(
2302 ; CHECK-NOT: @llvm.objc.
2304 define void @test60d() {
2305 %t = load ptr, ptr @constptr
2306 %s = load ptr, ptr @something
2307 call ptr @llvm.objc.retain(ptr %t)
2309 call void @use_pointer(ptr %s)
2310 call void @llvm.objc.release(ptr %t)
2314 ; CHECK-LABEL: define void @test60e(
2315 ; CHECK-NOT: @llvm.objc.
2317 define void @test60e() {
2318 %t = load ptr, ptr @constptr
2319 %s = load ptr, ptr @something
2320 call ptr @llvm.objc.retain(ptr %t)
2322 call void @use_pointer(ptr %s)
2323 call void @llvm.objc.release(ptr %t), !clang.imprecise_release !0
2327 ; Constant pointers to objects don't need to be considered related to other
2330 ; CHECK-LABEL: define void @test61(
2331 ; CHECK-NOT: @llvm.objc.
2333 define void @test61() {
2334 %t = load ptr, ptr @constptr
2335 call ptr @llvm.objc.retain(ptr %t)
2337 call void @use_pointer(ptr %t)
2338 call void @llvm.objc.release(ptr %t)
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.
2348 define void @test62(ptr %x, ptr %p) nounwind {
2353 call ptr @llvm.objc.retain(ptr %x)
2354 %q = load i1, ptr %p
2355 br i1 %q, label %loop.more, label %exit
2358 call void @llvm.objc.release(ptr %x)
2362 call void @llvm.objc.release(ptr %x)
2366 ; Like test62 but with no release in exit.
2367 ; Don't delete anything!
2369 ; CHECK-LABEL: define void @test63(
2371 ; CHECK: tail call ptr @llvm.objc.retain(ptr %x)
2373 ; CHECK: call void @llvm.objc.release(ptr %x)
2375 define void @test63(ptr %x, ptr %p) nounwind {
2380 call ptr @llvm.objc.retain(ptr %x)
2381 %q = load i1, ptr %p
2382 br i1 %q, label %loop.more, label %exit
2385 call void @llvm.objc.release(ptr %x)
2392 ; Like test62 but with no release in loop.more.
2393 ; Don't delete anything!
2395 ; CHECK-LABEL: define void @test64(
2397 ; CHECK: tail call ptr @llvm.objc.retain(ptr %x)
2399 ; CHECK: call void @llvm.objc.release(ptr %x)
2401 define void @test64(ptr %x, ptr %p) nounwind {
2406 call ptr @llvm.objc.retain(ptr %x)
2407 %q = load i1, ptr %p
2408 br i1 %q, label %loop.more, label %exit
2414 call void @llvm.objc.release(ptr %x)
2418 ; Move an autorelease past a phi with a null.
2420 ; CHECK-LABEL: define ptr @test65(
2422 ; CHECK: call ptr @llvm.objc.autorelease(
2424 ; CHECK-NOT: @llvm.objc.autorelease
2426 define ptr @test65(i1 %x) {
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
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
2441 ; Don't move an autorelease past an autorelease pool boundary.
2443 ; CHECK-LABEL: define ptr @test65b(
2445 ; CHECK-NOT: @llvm.objc.autorelease
2447 ; CHECK: call ptr @llvm.objc.autorelease(
2449 define ptr @test65b(i1 %x) {
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
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
2466 ; Don't move an autoreleaseReuturnValue, which would break
2467 ; the RV optimization.
2469 ; CHECK-LABEL: define ptr @test65c(
2471 ; CHECK-NOT: @llvm.objc.autorelease
2473 ; CHECK: call ptr @llvm.objc.autoreleaseReturnValue(
2475 define ptr @test65c(i1 %x) {
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
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
2490 ; CHECK-LABEL: define ptr @test65d(
2492 ; CHECK-NOT: @llvm.objc.autorelease
2494 ; CHECK: call ptr @llvm.objc.autoreleaseReturnValue(
2496 define ptr @test65d(i1 %x) {
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
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
2511 ; An llvm.objc.retain can serve as a may-use for a different pointer.
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]]
2520 define void @test66a(ptr %tmp5, ptr %bar, i1 %tobool, i1 %tobool1, ptr %call) {
2522 br i1 %tobool, label %cond.true, 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
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]]
2543 define void @test66b(ptr %tmp5, ptr %bar, i1 %tobool, i1 %tobool1, ptr %call) {
2545 br i1 %tobool, label %cond.true, 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
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]]
2566 define void @test66c(ptr %tmp5, ptr %bar, i1 %tobool, i1 %tobool1, ptr %call) {
2568 br i1 %tobool, label %cond.true, 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
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]]
2589 define void @test66d(ptr %tmp5, ptr %bar, i1 %tobool, i1 %tobool1, ptr %call) {
2591 br i1 %tobool, label %cond.true, 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
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)
2620 define { <2 x float>, <2 x float> } @"\01-[A z]"(ptr %self, ptr nocapture %_cmd) nounwind {
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 {
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
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) {
2677 ; CHECK-NOT: @llvm.objc.
2678 ; CHECK: @objc_msgSend
2679 ; CHECK-NOT: @llvm.objc.
2682 define void @loop(ptr %x, i64 %n) {
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
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)
2709 %0 = type { ptr, ptr }
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) {
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
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
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)
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
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
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
2927 ; CHECK-LABEL: define void @test68(
2929 ; CHECK: call void @callee2(
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
2942 !llvm.module.flags = !{!1}
2943 !llvm.dbg.cu = !{!3}
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",
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]] = !{}