1 ; RUN: opt -S -objc-arc < %s | FileCheck %s
3 declare i8* @objc_retain(i8*) nonlazybind
4 declare void @objc_release(i8*) nonlazybind
5 declare i8* @objc_retainBlock(i8*)
7 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8 ; Use by an instruction which copies the value is an escape if the ;
9 ; result is an escape. The current instructions with this property are: ;
16 ; Make sure that such instructions do not confuse the optimizer into removing ;
17 ; an objc_retainBlock that is needed. ;
19 ; rdar://13273675. (With extra test cases to handle bitcast, phi, and select. ;
20 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
22 define void @bitcasttest(i8* %storage, void (...)* %block) {
23 ; CHECK: define void @bitcasttest
25 %t1 = bitcast void (...)* %block to i8*
26 ; CHECK: tail call i8* @objc_retain
27 %t2 = tail call i8* @objc_retain(i8* %t1)
28 ; CHECK: tail call i8* @objc_retainBlock
29 %t3 = tail call i8* @objc_retainBlock(i8* %t1), !clang.arc.copy_on_escape !0
30 %t4 = bitcast i8* %storage to void (...)**
31 %t5 = bitcast i8* %t3 to void (...)*
32 store void (...)* %t5, void (...)** %t4, align 8
33 ; CHECK: call void @objc_release
34 call void @objc_release(i8* %t1)
39 define void @bitcasttest_a(i8* %storage, void (...)* %block) {
40 ; CHECK: define void @bitcasttest_a
42 %t1 = bitcast void (...)* %block to i8*
43 ; CHECK-NOT: tail call i8* @objc_retain
44 %t2 = tail call i8* @objc_retain(i8* %t1)
45 ; CHECK: tail call i8* @objc_retainBlock
46 %t3 = tail call i8* @objc_retainBlock(i8* %t1), !clang.arc.copy_on_escape !0
47 %t4 = bitcast i8* %storage to void (...)**
48 %t5 = bitcast i8* %t3 to void (...)*
49 store void (...)* %t5, void (...)** %t4, align 8
50 ; CHECK-NOT: call void @objc_release
51 call void @objc_release(i8* %t1), !clang.imprecise_release !0
56 define void @geptest(void (...)** %storage_array, void (...)* %block) {
57 ; CHECK: define void @geptest
59 %t1 = bitcast void (...)* %block to i8*
60 ; CHECK: tail call i8* @objc_retain
61 %t2 = tail call i8* @objc_retain(i8* %t1)
62 ; CHECK: tail call i8* @objc_retainBlock
63 %t3 = tail call i8* @objc_retainBlock(i8* %t1), !clang.arc.copy_on_escape !0
64 %t4 = bitcast i8* %t3 to void (...)*
66 %storage = getelementptr inbounds void (...)** %storage_array, i64 0
68 store void (...)* %t4, void (...)** %storage, align 8
69 ; CHECK: call void @objc_release
70 call void @objc_release(i8* %t1)
75 define void @geptest_a(void (...)** %storage_array, void (...)* %block) {
76 ; CHECK: define void @geptest_a
78 %t1 = bitcast void (...)* %block to i8*
79 ; CHECK-NOT: tail call i8* @objc_retain
80 %t2 = tail call i8* @objc_retain(i8* %t1)
81 ; CHECK: tail call i8* @objc_retainBlock
82 %t3 = tail call i8* @objc_retainBlock(i8* %t1), !clang.arc.copy_on_escape !0
83 %t4 = bitcast i8* %t3 to void (...)*
85 %storage = getelementptr inbounds void (...)** %storage_array, i64 0
87 store void (...)* %t4, void (...)** %storage, align 8
88 ; CHECK-NOT: call void @objc_release
89 call void @objc_release(i8* %t1), !clang.imprecise_release !0
94 define void @selecttest(void (...)** %store1, void (...)** %store2,
96 ; CHECK: define void @selecttest
98 %t1 = bitcast void (...)* %block to i8*
99 ; CHECK: tail call i8* @objc_retain
100 %t2 = tail call i8* @objc_retain(i8* %t1)
101 ; CHECK: tail call i8* @objc_retainBlock
102 %t3 = tail call i8* @objc_retainBlock(i8* %t1), !clang.arc.copy_on_escape !0
103 %t4 = bitcast i8* %t3 to void (...)*
104 %store = select i1 undef, void (...)** %store1, void (...)** %store2
105 store void (...)* %t4, void (...)** %store, align 8
106 ; CHECK: call void @objc_release
107 call void @objc_release(i8* %t1)
112 define void @selecttest_a(void (...)** %store1, void (...)** %store2,
113 void (...)* %block) {
114 ; CHECK: define void @selecttest_a
116 %t1 = bitcast void (...)* %block to i8*
117 ; CHECK-NOT: tail call i8* @objc_retain
118 %t2 = tail call i8* @objc_retain(i8* %t1)
119 ; CHECK: tail call i8* @objc_retainBlock
120 %t3 = tail call i8* @objc_retainBlock(i8* %t1), !clang.arc.copy_on_escape !0
121 %t4 = bitcast i8* %t3 to void (...)*
122 %store = select i1 undef, void (...)** %store1, void (...)** %store2
123 store void (...)* %t4, void (...)** %store, align 8
124 ; CHECK-NOT: call void @objc_release
125 call void @objc_release(i8* %t1), !clang.imprecise_release !0
130 define void @phinodetest(void (...)** %storage1,
131 void (...)** %storage2,
132 void (...)* %block) {
133 ; CHECK: define void @phinodetest
135 %t1 = bitcast void (...)* %block to i8*
136 ; CHECK: tail call i8* @objc_retain
137 %t2 = tail call i8* @objc_retain(i8* %t1)
138 ; CHECK: tail call i8* @objc_retainBlock
139 %t3 = tail call i8* @objc_retainBlock(i8* %t1), !clang.arc.copy_on_escape !0
140 %t4 = bitcast i8* %t3 to void (...)*
141 br i1 undef, label %store1_set, label %store2_set
152 %storage = phi void (...)** [ %storage1, %store1_set ], [ %storage2, %store2_set]
153 store void (...)* %t4, void (...)** %storage, align 8
154 ; CHECK: call void @objc_release
155 call void @objc_release(i8* %t1)
160 define void @phinodetest_a(void (...)** %storage1,
161 void (...)** %storage2,
162 void (...)* %block) {
163 ; CHECK: define void @phinodetest_a
165 %t1 = bitcast void (...)* %block to i8*
166 ; CHECK-NOT: tail call i8* @objc_retain
167 %t2 = tail call i8* @objc_retain(i8* %t1)
168 ; CHECK: tail call i8* @objc_retainBlock
169 %t3 = tail call i8* @objc_retainBlock(i8* %t1), !clang.arc.copy_on_escape !0
170 %t4 = bitcast i8* %t3 to void (...)*
171 br i1 undef, label %store1_set, label %store2_set
180 %storage = phi void (...)** [ %storage1, %store1_set ], [ %storage2, %store2_set]
181 store void (...)* %t4, void (...)** %storage, align 8
182 ; CHECK-NOT: call void @objc_release
183 call void @objc_release(i8* %t1), !clang.imprecise_release !0
188 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
189 ; This test makes sure that we do not hang clang when visiting a use ;
190 ; cycle caused by phi nodes during objc-arc analysis. *NOTE* This ;
191 ; test case looks a little convoluted since it was produced by ;
196 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
198 define void @phinode_use_cycle(i8* %block) uwtable optsize ssp {
199 ; CHECK: define void @phinode_use_cycle(i8* %block)
203 for.body: ; preds = %if.then, %for.body, %entry
204 %block.05 = phi void (...)* [ null, %entry ], [ %1, %if.then ], [ %block.05, %for.body ]
205 br i1 undef, label %for.body, label %if.then
207 if.then: ; preds = %for.body
208 %0 = call i8* @objc_retainBlock(i8* %block), !clang.arc.copy_on_escape !0
209 %1 = bitcast i8* %0 to void (...)*
210 %2 = bitcast void (...)* %block.05 to i8*
211 call void @objc_release(i8* %2) nounwind, !clang.imprecise_release !0