1 ; RUN: opt -objc-arc -S < %s | FileCheck %s
3 %struct.__objcFastEnumerationState = type { i64, i8**, i64*, [5 x i64] }
5 @"\01L_OBJC_METH_VAR_NAME_" = internal global [43 x i8] c"countByEnumeratingWithState:objects:count:\00", section "__TEXT,__objc_methname,cstring_literals", align 1
6 @"\01L_OBJC_SELECTOR_REFERENCES_" = internal global i8* getelementptr inbounds ([43 x i8]* @"\01L_OBJC_METH_VAR_NAME_", i64 0, i64 0), section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
7 @g = common global i8* null, align 8
8 @"\01L_OBJC_IMAGE_INFO" = internal constant [2 x i32] [i32 0, i32 16], section "__DATA, __objc_imageinfo, regular, no_dead_strip"
10 declare void @callee()
11 declare i8* @returner()
12 declare i8* @objc_retainAutoreleasedReturnValue(i8*)
13 declare i8* @objc_retain(i8*)
14 declare void @objc_enumerationMutation(i8*)
15 declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) nounwind
16 declare i8* @objc_msgSend(i8*, i8*, ...) nonlazybind
17 declare void @use(i8*)
18 declare void @objc_release(i8*)
22 ; Delete a nested retain+release pair.
24 ; CHECK: define void @test0(
25 ; CHECK: call i8* @objc_retain
26 ; CHECK-NOT: @objc_retain
28 define void @test0(i8* %a) nounwind {
30 %state.ptr = alloca %struct.__objcFastEnumerationState, align 8
31 %items.ptr = alloca [16 x i8*], align 8
32 %0 = call i8* @objc_retain(i8* %a) nounwind
33 %tmp = bitcast %struct.__objcFastEnumerationState* %state.ptr to i8*
34 call void @llvm.memset.p0i8.i64(i8* %tmp, i8 0, i64 64, i32 8, i1 false)
35 %1 = call i8* @objc_retain(i8* %0) nounwind
36 %tmp2 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
37 %call = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp2, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
38 %iszero = icmp eq i64 %call, 0
39 br i1 %iszero, label %forcoll.empty, label %forcoll.loopinit
42 %mutationsptr.ptr = getelementptr inbounds %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 2
43 %mutationsptr = load i64** %mutationsptr.ptr, align 8
44 %forcoll.initial-mutations = load i64* %mutationsptr, align 8
45 %stateitems.ptr = getelementptr inbounds %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 1
46 br label %forcoll.loopbody.outer
48 forcoll.loopbody.outer:
49 %forcoll.count.ph = phi i64 [ %call, %forcoll.loopinit ], [ %call6, %forcoll.refetch ]
50 %tmp7 = icmp ugt i64 %forcoll.count.ph, 1
51 %umax = select i1 %tmp7, i64 %forcoll.count.ph, i64 1
52 br label %forcoll.loopbody
55 %forcoll.index = phi i64 [ 0, %forcoll.loopbody.outer ], [ %4, %forcoll.notmutated ]
56 %mutationsptr3 = load i64** %mutationsptr.ptr, align 8
57 %statemutations = load i64* %mutationsptr3, align 8
58 %2 = icmp eq i64 %statemutations, %forcoll.initial-mutations
59 br i1 %2, label %forcoll.notmutated, label %forcoll.mutated
62 call void @objc_enumerationMutation(i8* %1)
63 br label %forcoll.notmutated
66 %stateitems = load i8*** %stateitems.ptr, align 8
67 %currentitem.ptr = getelementptr i8** %stateitems, i64 %forcoll.index
68 %3 = load i8** %currentitem.ptr, align 8
69 call void @use(i8* %3)
70 %4 = add i64 %forcoll.index, 1
71 %exitcond = icmp eq i64 %4, %umax
72 br i1 %exitcond, label %forcoll.refetch, label %forcoll.loopbody
75 %tmp5 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
76 %call6 = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp5, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
77 %5 = icmp eq i64 %call6, 0
78 br i1 %5, label %forcoll.empty, label %forcoll.loopbody.outer
81 call void @objc_release(i8* %1) nounwind
82 call void @objc_release(i8* %0) nounwind, !clang.imprecise_release !0
86 ; Delete a nested retain+release pair.
88 ; CHECK: define void @test2(
89 ; CHECK: call i8* @objc_retain
90 ; CHECK-NOT: @objc_retain
92 define void @test2() nounwind {
94 %state.ptr = alloca %struct.__objcFastEnumerationState, align 8
95 %items.ptr = alloca [16 x i8*], align 8
96 %call = call i8* @returner()
97 %0 = call i8* @objc_retainAutoreleasedReturnValue(i8* %call) nounwind
98 %tmp = bitcast %struct.__objcFastEnumerationState* %state.ptr to i8*
99 call void @llvm.memset.p0i8.i64(i8* %tmp, i8 0, i64 64, i32 8, i1 false)
100 %1 = call i8* @objc_retain(i8* %0) nounwind
101 %tmp2 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
102 %call3 = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp2, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
103 %iszero = icmp eq i64 %call3, 0
104 br i1 %iszero, label %forcoll.empty, label %forcoll.loopinit
107 %mutationsptr.ptr = getelementptr inbounds %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 2
108 %mutationsptr = load i64** %mutationsptr.ptr, align 8
109 %forcoll.initial-mutations = load i64* %mutationsptr, align 8
110 %stateitems.ptr = getelementptr inbounds %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 1
111 br label %forcoll.loopbody.outer
113 forcoll.loopbody.outer:
114 %forcoll.count.ph = phi i64 [ %call3, %forcoll.loopinit ], [ %call7, %forcoll.refetch ]
115 %tmp8 = icmp ugt i64 %forcoll.count.ph, 1
116 %umax = select i1 %tmp8, i64 %forcoll.count.ph, i64 1
117 br label %forcoll.loopbody
120 %forcoll.index = phi i64 [ 0, %forcoll.loopbody.outer ], [ %4, %forcoll.notmutated ]
121 %mutationsptr4 = load i64** %mutationsptr.ptr, align 8
122 %statemutations = load i64* %mutationsptr4, align 8
123 %2 = icmp eq i64 %statemutations, %forcoll.initial-mutations
124 br i1 %2, label %forcoll.notmutated, label %forcoll.mutated
127 call void @objc_enumerationMutation(i8* %1)
128 br label %forcoll.notmutated
131 %stateitems = load i8*** %stateitems.ptr, align 8
132 %currentitem.ptr = getelementptr i8** %stateitems, i64 %forcoll.index
133 %3 = load i8** %currentitem.ptr, align 8
134 call void @use(i8* %3)
135 %4 = add i64 %forcoll.index, 1
136 %exitcond = icmp eq i64 %4, %umax
137 br i1 %exitcond, label %forcoll.refetch, label %forcoll.loopbody
140 %tmp6 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
141 %call7 = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp6, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
142 %5 = icmp eq i64 %call7, 0
143 br i1 %5, label %forcoll.empty, label %forcoll.loopbody.outer
146 call void @objc_release(i8* %1) nounwind
147 call void @objc_release(i8* %0) nounwind, !clang.imprecise_release !0
151 ; Delete a nested retain+release pair.
153 ; CHECK: define void @test4(
154 ; CHECK: call i8* @objc_retain
155 ; CHECK-NOT: @objc_retain
157 define void @test4() nounwind {
159 %state.ptr = alloca %struct.__objcFastEnumerationState, align 8
160 %items.ptr = alloca [16 x i8*], align 8
161 %tmp = load i8** @g, align 8
162 %0 = call i8* @objc_retain(i8* %tmp) nounwind
163 %tmp2 = bitcast %struct.__objcFastEnumerationState* %state.ptr to i8*
164 call void @llvm.memset.p0i8.i64(i8* %tmp2, i8 0, i64 64, i32 8, i1 false)
165 %1 = call i8* @objc_retain(i8* %0) nounwind
166 %tmp4 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
167 %call = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp4, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
168 %iszero = icmp eq i64 %call, 0
169 br i1 %iszero, label %forcoll.empty, label %forcoll.loopinit
172 %mutationsptr.ptr = getelementptr inbounds %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 2
173 %mutationsptr = load i64** %mutationsptr.ptr, align 8
174 %forcoll.initial-mutations = load i64* %mutationsptr, align 8
175 %stateitems.ptr = getelementptr inbounds %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 1
176 br label %forcoll.loopbody.outer
178 forcoll.loopbody.outer:
179 %forcoll.count.ph = phi i64 [ %call, %forcoll.loopinit ], [ %call8, %forcoll.refetch ]
180 %tmp9 = icmp ugt i64 %forcoll.count.ph, 1
181 %umax = select i1 %tmp9, i64 %forcoll.count.ph, i64 1
182 br label %forcoll.loopbody
185 %forcoll.index = phi i64 [ 0, %forcoll.loopbody.outer ], [ %4, %forcoll.notmutated ]
186 %mutationsptr5 = load i64** %mutationsptr.ptr, align 8
187 %statemutations = load i64* %mutationsptr5, align 8
188 %2 = icmp eq i64 %statemutations, %forcoll.initial-mutations
189 br i1 %2, label %forcoll.notmutated, label %forcoll.mutated
192 call void @objc_enumerationMutation(i8* %1)
193 br label %forcoll.notmutated
196 %stateitems = load i8*** %stateitems.ptr, align 8
197 %currentitem.ptr = getelementptr i8** %stateitems, i64 %forcoll.index
198 %3 = load i8** %currentitem.ptr, align 8
199 call void @use(i8* %3)
200 %4 = add i64 %forcoll.index, 1
201 %exitcond = icmp eq i64 %4, %umax
202 br i1 %exitcond, label %forcoll.refetch, label %forcoll.loopbody
205 %tmp7 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
206 %call8 = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp7, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
207 %5 = icmp eq i64 %call8, 0
208 br i1 %5, label %forcoll.empty, label %forcoll.loopbody.outer
211 call void @objc_release(i8* %1) nounwind
212 call void @objc_release(i8* %0) nounwind, !clang.imprecise_release !0
216 ; Delete a nested retain+release pair.
218 ; CHECK: define void @test5(
219 ; CHECK: call i8* @objc_retain
220 ; CHECK-NOT: @objc_retain
222 define void @test5() nounwind {
224 %state.ptr = alloca %struct.__objcFastEnumerationState, align 8
225 %items.ptr = alloca [16 x i8*], align 8
226 %call = call i8* @returner()
227 %0 = call i8* @objc_retainAutoreleasedReturnValue(i8* %call) nounwind
229 %tmp = bitcast %struct.__objcFastEnumerationState* %state.ptr to i8*
230 call void @llvm.memset.p0i8.i64(i8* %tmp, i8 0, i64 64, i32 8, i1 false)
231 %1 = call i8* @objc_retain(i8* %0) nounwind
232 %tmp2 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
233 %call3 = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp2, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
234 %iszero = icmp eq i64 %call3, 0
235 br i1 %iszero, label %forcoll.empty, label %forcoll.loopinit
238 %mutationsptr.ptr = getelementptr inbounds %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 2
239 %mutationsptr = load i64** %mutationsptr.ptr, align 8
240 %forcoll.initial-mutations = load i64* %mutationsptr, align 8
241 %stateitems.ptr = getelementptr inbounds %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 1
242 br label %forcoll.loopbody.outer
244 forcoll.loopbody.outer:
245 %forcoll.count.ph = phi i64 [ %call3, %forcoll.loopinit ], [ %call7, %forcoll.refetch ]
246 %tmp8 = icmp ugt i64 %forcoll.count.ph, 1
247 %umax = select i1 %tmp8, i64 %forcoll.count.ph, i64 1
248 br label %forcoll.loopbody
251 %forcoll.index = phi i64 [ 0, %forcoll.loopbody.outer ], [ %4, %forcoll.notmutated ]
252 %mutationsptr4 = load i64** %mutationsptr.ptr, align 8
253 %statemutations = load i64* %mutationsptr4, align 8
254 %2 = icmp eq i64 %statemutations, %forcoll.initial-mutations
255 br i1 %2, label %forcoll.notmutated, label %forcoll.mutated
258 call void @objc_enumerationMutation(i8* %1)
259 br label %forcoll.notmutated
262 %stateitems = load i8*** %stateitems.ptr, align 8
263 %currentitem.ptr = getelementptr i8** %stateitems, i64 %forcoll.index
264 %3 = load i8** %currentitem.ptr, align 8
265 call void @use(i8* %3)
266 %4 = add i64 %forcoll.index, 1
267 %exitcond = icmp eq i64 %4, %umax
268 br i1 %exitcond, label %forcoll.refetch, label %forcoll.loopbody
271 %tmp6 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
272 %call7 = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp6, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
273 %5 = icmp eq i64 %call7, 0
274 br i1 %5, label %forcoll.empty, label %forcoll.loopbody.outer
277 call void @objc_release(i8* %1) nounwind
278 call void @objc_release(i8* %0) nounwind, !clang.imprecise_release !0
282 ; Delete a nested retain+release pair.
284 ; CHECK: define void @test6(
285 ; CHECK: call i8* @objc_retain
286 ; CHECK-NOT: @objc_retain
288 define void @test6() nounwind {
290 %state.ptr = alloca %struct.__objcFastEnumerationState, align 8
291 %items.ptr = alloca [16 x i8*], align 8
292 %call = call i8* @returner()
293 %0 = call i8* @objc_retainAutoreleasedReturnValue(i8* %call) nounwind
294 %tmp = bitcast %struct.__objcFastEnumerationState* %state.ptr to i8*
295 call void @llvm.memset.p0i8.i64(i8* %tmp, i8 0, i64 64, i32 8, i1 false)
296 %1 = call i8* @objc_retain(i8* %0) nounwind
297 %tmp2 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
298 %call3 = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp2, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
299 %iszero = icmp eq i64 %call3, 0
300 br i1 %iszero, label %forcoll.empty, label %forcoll.loopinit
303 %mutationsptr.ptr = getelementptr inbounds %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 2
304 %mutationsptr = load i64** %mutationsptr.ptr, align 8
305 %forcoll.initial-mutations = load i64* %mutationsptr, align 8
306 %stateitems.ptr = getelementptr inbounds %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 1
307 br label %forcoll.loopbody.outer
309 forcoll.loopbody.outer:
310 %forcoll.count.ph = phi i64 [ %call3, %forcoll.loopinit ], [ %call7, %forcoll.refetch ]
311 %tmp8 = icmp ugt i64 %forcoll.count.ph, 1
312 %umax = select i1 %tmp8, i64 %forcoll.count.ph, i64 1
313 br label %forcoll.loopbody
316 %forcoll.index = phi i64 [ 0, %forcoll.loopbody.outer ], [ %4, %forcoll.notmutated ]
317 %mutationsptr4 = load i64** %mutationsptr.ptr, align 8
318 %statemutations = load i64* %mutationsptr4, align 8
319 %2 = icmp eq i64 %statemutations, %forcoll.initial-mutations
320 br i1 %2, label %forcoll.notmutated, label %forcoll.mutated
323 call void @objc_enumerationMutation(i8* %1)
324 br label %forcoll.notmutated
327 %stateitems = load i8*** %stateitems.ptr, align 8
328 %currentitem.ptr = getelementptr i8** %stateitems, i64 %forcoll.index
329 %3 = load i8** %currentitem.ptr, align 8
330 call void @use(i8* %3)
331 %4 = add i64 %forcoll.index, 1
332 %exitcond = icmp eq i64 %4, %umax
333 br i1 %exitcond, label %forcoll.refetch, label %forcoll.loopbody
336 %tmp6 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
337 %call7 = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp6, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
338 %5 = icmp eq i64 %call7, 0
339 br i1 %5, label %forcoll.empty, label %forcoll.loopbody.outer
342 call void @objc_release(i8* %1) nounwind
344 call void @objc_release(i8* %0) nounwind, !clang.imprecise_release !0
348 ; Delete a nested retain+release pair.
350 ; CHECK: define void @test7(
351 ; CHECK: call i8* @objc_retain
352 ; CHECK-NOT: @objc_retain
354 define void @test7() nounwind {
356 %state.ptr = alloca %struct.__objcFastEnumerationState, align 8
357 %items.ptr = alloca [16 x i8*], align 8
358 %call = call i8* @returner()
359 %0 = call i8* @objc_retainAutoreleasedReturnValue(i8* %call) nounwind
361 %tmp = bitcast %struct.__objcFastEnumerationState* %state.ptr to i8*
362 call void @llvm.memset.p0i8.i64(i8* %tmp, i8 0, i64 64, i32 8, i1 false)
363 %1 = call i8* @objc_retain(i8* %0) nounwind
364 %tmp2 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
365 %call3 = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp2, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
366 %iszero = icmp eq i64 %call3, 0
367 br i1 %iszero, label %forcoll.empty, label %forcoll.loopinit
370 %mutationsptr.ptr = getelementptr inbounds %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 2
371 %mutationsptr = load i64** %mutationsptr.ptr, align 8
372 %forcoll.initial-mutations = load i64* %mutationsptr, align 8
373 %stateitems.ptr = getelementptr inbounds %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 1
374 br label %forcoll.loopbody.outer
376 forcoll.loopbody.outer:
377 %forcoll.count.ph = phi i64 [ %call3, %forcoll.loopinit ], [ %call7, %forcoll.refetch ]
378 %tmp8 = icmp ugt i64 %forcoll.count.ph, 1
379 %umax = select i1 %tmp8, i64 %forcoll.count.ph, i64 1
380 br label %forcoll.loopbody
383 %forcoll.index = phi i64 [ 0, %forcoll.loopbody.outer ], [ %4, %forcoll.notmutated ]
384 %mutationsptr4 = load i64** %mutationsptr.ptr, align 8
385 %statemutations = load i64* %mutationsptr4, align 8
386 %2 = icmp eq i64 %statemutations, %forcoll.initial-mutations
387 br i1 %2, label %forcoll.notmutated, label %forcoll.mutated
390 call void @objc_enumerationMutation(i8* %1)
391 br label %forcoll.notmutated
394 %stateitems = load i8*** %stateitems.ptr, align 8
395 %currentitem.ptr = getelementptr i8** %stateitems, i64 %forcoll.index
396 %3 = load i8** %currentitem.ptr, align 8
397 call void @use(i8* %3)
398 %4 = add i64 %forcoll.index, 1
399 %exitcond = icmp eq i64 %4, %umax
400 br i1 %exitcond, label %forcoll.refetch, label %forcoll.loopbody
403 %tmp6 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
404 %call7 = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp6, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
405 %5 = icmp eq i64 %call7, 0
406 br i1 %5, label %forcoll.empty, label %forcoll.loopbody.outer
409 call void @objc_release(i8* %1) nounwind
411 call void @objc_release(i8* %0) nounwind, !clang.imprecise_release !0
415 ; Delete a nested retain+release pair.
417 ; CHECK: define void @test8(
418 ; CHECK: call i8* @objc_retain
419 ; CHECK-NOT: @objc_retain
421 define void @test8() nounwind {
423 %state.ptr = alloca %struct.__objcFastEnumerationState, align 8
424 %items.ptr = alloca [16 x i8*], align 8
425 %call = call i8* @returner()
426 %0 = call i8* @objc_retainAutoreleasedReturnValue(i8* %call) nounwind
427 %tmp = bitcast %struct.__objcFastEnumerationState* %state.ptr to i8*
428 call void @llvm.memset.p0i8.i64(i8* %tmp, i8 0, i64 64, i32 8, i1 false)
429 %1 = call i8* @objc_retain(i8* %0) nounwind
430 %tmp2 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
431 %call3 = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp2, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
432 %iszero = icmp eq i64 %call3, 0
433 br i1 %iszero, label %forcoll.empty, label %forcoll.loopinit
436 %mutationsptr.ptr = getelementptr inbounds %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 2
437 %mutationsptr = load i64** %mutationsptr.ptr, align 8
438 %forcoll.initial-mutations = load i64* %mutationsptr, align 8
439 %stateitems.ptr = getelementptr inbounds %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 1
440 br label %forcoll.loopbody.outer
442 forcoll.loopbody.outer:
443 %forcoll.count.ph = phi i64 [ %call3, %forcoll.loopinit ], [ %call7, %forcoll.refetch ]
444 %tmp8 = icmp ugt i64 %forcoll.count.ph, 1
445 %umax = select i1 %tmp8, i64 %forcoll.count.ph, i64 1
446 br label %forcoll.loopbody
449 %forcoll.index = phi i64 [ 0, %forcoll.loopbody.outer ], [ %4, %forcoll.next ]
450 %mutationsptr4 = load i64** %mutationsptr.ptr, align 8
451 %statemutations = load i64* %mutationsptr4, align 8
452 %2 = icmp eq i64 %statemutations, %forcoll.initial-mutations
453 br i1 %2, label %forcoll.notmutated, label %forcoll.mutated
456 call void @objc_enumerationMutation(i8* %1)
457 br label %forcoll.notmutated
460 %stateitems = load i8*** %stateitems.ptr, align 8
461 %currentitem.ptr = getelementptr i8** %stateitems, i64 %forcoll.index
462 %3 = load i8** %currentitem.ptr, align 8
463 %tobool = icmp eq i8* %3, null
464 br i1 %tobool, label %forcoll.next, label %if.then
468 br label %forcoll.next
471 %4 = add i64 %forcoll.index, 1
472 %exitcond = icmp eq i64 %4, %umax
473 br i1 %exitcond, label %forcoll.refetch, label %forcoll.loopbody
476 %tmp6 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
477 %call7 = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp6, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
478 %5 = icmp eq i64 %call7, 0
479 br i1 %5, label %forcoll.empty, label %forcoll.loopbody.outer
482 call void @objc_release(i8* %1) nounwind
483 call void @objc_release(i8* %0) nounwind, !clang.imprecise_release !0
487 ; Delete a nested retain+release pair.
489 ; CHECK: define void @test9(
490 ; CHECK: call i8* @objc_retain
491 ; CHECK: call i8* @objc_retain
492 ; CHECK-NOT: @objc_retain
494 define void @test9() nounwind {
496 %state.ptr = alloca %struct.__objcFastEnumerationState, align 8
497 %items.ptr = alloca [16 x i8*], align 8
498 %call = call i8* @returner()
499 %0 = call i8* @objc_retainAutoreleasedReturnValue(i8* %call) nounwind
500 %call1 = call i8* @returner()
501 %1 = call i8* @objc_retainAutoreleasedReturnValue(i8* %call1) nounwind
502 %tmp = bitcast %struct.__objcFastEnumerationState* %state.ptr to i8*
503 call void @llvm.memset.p0i8.i64(i8* %tmp, i8 0, i64 64, i32 8, i1 false)
504 %2 = call i8* @objc_retain(i8* %0) nounwind
505 %tmp3 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
506 %call4 = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %2, i8* %tmp3, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
507 %iszero = icmp eq i64 %call4, 0
508 br i1 %iszero, label %forcoll.empty, label %forcoll.loopinit
511 %mutationsptr.ptr = getelementptr inbounds %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 2
512 %mutationsptr = load i64** %mutationsptr.ptr, align 8
513 %forcoll.initial-mutations = load i64* %mutationsptr, align 8
514 br label %forcoll.loopbody.outer
516 forcoll.loopbody.outer:
517 %forcoll.count.ph = phi i64 [ %call4, %forcoll.loopinit ], [ %call7, %forcoll.refetch ]
518 %tmp9 = icmp ugt i64 %forcoll.count.ph, 1
519 %umax = select i1 %tmp9, i64 %forcoll.count.ph, i64 1
520 br label %forcoll.loopbody
523 %forcoll.index = phi i64 [ %phitmp, %forcoll.notmutated.forcoll.loopbody_crit_edge ], [ 1, %forcoll.loopbody.outer ]
524 %mutationsptr5 = load i64** %mutationsptr.ptr, align 8
525 %statemutations = load i64* %mutationsptr5, align 8
526 %3 = icmp eq i64 %statemutations, %forcoll.initial-mutations
527 br i1 %3, label %forcoll.notmutated, label %forcoll.mutated
530 call void @objc_enumerationMutation(i8* %2)
531 br label %forcoll.notmutated
534 %exitcond = icmp eq i64 %forcoll.index, %umax
535 br i1 %exitcond, label %forcoll.refetch, label %forcoll.notmutated.forcoll.loopbody_crit_edge
537 forcoll.notmutated.forcoll.loopbody_crit_edge:
538 %phitmp = add i64 %forcoll.index, 1
539 br label %forcoll.loopbody
542 %tmp6 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
543 %call7 = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %2, i8* %tmp6, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
544 %4 = icmp eq i64 %call7, 0
545 br i1 %4, label %forcoll.empty, label %forcoll.loopbody.outer
548 call void @objc_release(i8* %2) nounwind
549 call void @objc_release(i8* %1) nounwind, !clang.imprecise_release !0
550 call void @objc_release(i8* %0) nounwind, !clang.imprecise_release !0
554 ; Delete a nested retain+release pair.
556 ; CHECK: define void @test10(
557 ; CHECK: call i8* @objc_retain
558 ; CHECK: call i8* @objc_retain
559 ; CHECK-NOT: @objc_retain
561 define void @test10() nounwind {
563 %state.ptr = alloca %struct.__objcFastEnumerationState, align 8
564 %items.ptr = alloca [16 x i8*], align 8
565 %call = call i8* @returner()
566 %0 = call i8* @objc_retainAutoreleasedReturnValue(i8* %call) nounwind
567 %call1 = call i8* @returner()
568 %1 = call i8* @objc_retainAutoreleasedReturnValue(i8* %call1) nounwind
570 %tmp = bitcast %struct.__objcFastEnumerationState* %state.ptr to i8*
571 call void @llvm.memset.p0i8.i64(i8* %tmp, i8 0, i64 64, i32 8, i1 false)
572 %2 = call i8* @objc_retain(i8* %0) nounwind
573 %tmp3 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
574 %call4 = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %2, i8* %tmp3, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
575 %iszero = icmp eq i64 %call4, 0
576 br i1 %iszero, label %forcoll.empty, label %forcoll.loopinit
579 %mutationsptr.ptr = getelementptr inbounds %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 2
580 %mutationsptr = load i64** %mutationsptr.ptr, align 8
581 %forcoll.initial-mutations = load i64* %mutationsptr, align 8
582 br label %forcoll.loopbody.outer
584 forcoll.loopbody.outer:
585 %forcoll.count.ph = phi i64 [ %call4, %forcoll.loopinit ], [ %call7, %forcoll.refetch ]
586 %tmp9 = icmp ugt i64 %forcoll.count.ph, 1
587 %umax = select i1 %tmp9, i64 %forcoll.count.ph, i64 1
588 br label %forcoll.loopbody
591 %forcoll.index = phi i64 [ %phitmp, %forcoll.notmutated.forcoll.loopbody_crit_edge ], [ 1, %forcoll.loopbody.outer ]
592 %mutationsptr5 = load i64** %mutationsptr.ptr, align 8
593 %statemutations = load i64* %mutationsptr5, align 8
594 %3 = icmp eq i64 %statemutations, %forcoll.initial-mutations
595 br i1 %3, label %forcoll.notmutated, label %forcoll.mutated
598 call void @objc_enumerationMutation(i8* %2)
599 br label %forcoll.notmutated
602 %exitcond = icmp eq i64 %forcoll.index, %umax
603 br i1 %exitcond, label %forcoll.refetch, label %forcoll.notmutated.forcoll.loopbody_crit_edge
605 forcoll.notmutated.forcoll.loopbody_crit_edge:
606 %phitmp = add i64 %forcoll.index, 1
607 br label %forcoll.loopbody
610 %tmp6 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
611 %call7 = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %2, i8* %tmp6, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
612 %4 = icmp eq i64 %call7, 0
613 br i1 %4, label %forcoll.empty, label %forcoll.loopbody.outer
616 call void @objc_release(i8* %2) nounwind
617 call void @objc_release(i8* %1) nounwind, !clang.imprecise_release !0
618 call void @objc_release(i8* %0) nounwind, !clang.imprecise_release !0