1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -loop-idiom -verify -verify-each -verify-dom-info -verify-loop-info < %s -S | FileCheck %s --implicit-check-not=bcmp --implicit-check-not=memcmp
4 ; CHECK: source_filename
6 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
8 define i1 @three_blocks_and_two_latches_in_loop(i8* %ptr0, i8* %ptr1) {
9 ; CHECK-LABEL: @three_blocks_and_two_latches_in_loop(
11 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
13 ; CHECK-NEXT: [[I_08:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[I_08_BE:%.*]], [[FOR_BODY_BACKEDGE:%.*]] ]
14 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, i8* [[PTR0:%.*]], i64 [[I_08]]
15 ; CHECK-NEXT: [[V0:%.*]] = load i8, i8* [[ARRAYIDX]]
16 ; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, i8* [[PTR1:%.*]], i64 [[I_08]]
17 ; CHECK-NEXT: [[V1:%.*]] = load i8, i8* [[ARRAYIDX1]]
18 ; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i8 [[V0]], [[V1]]
19 ; CHECK-NEXT: [[INC:%.*]] = add nuw nsw i64 [[I_08]], 1
20 ; CHECK-NEXT: br i1 [[CMP3]], label [[FOR_PASSTHROUGH:%.*]], label [[CLEANUP:%.*]]
21 ; CHECK: for.passthrough:
22 ; CHECK-NEXT: br i1 true, label [[FOR_COND:%.*]], label [[FOR_BODY_BACKEDGE]]
23 ; CHECK: for.body.backedge:
24 ; CHECK-NEXT: [[I_08_BE]] = phi i64 [ [[INC]], [[FOR_COND]] ], [ 0, [[FOR_PASSTHROUGH]] ]
25 ; CHECK-NEXT: br label [[FOR_BODY]]
27 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[INC]], 8
28 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY_BACKEDGE]], label [[CLEANUP]]
30 ; CHECK-NEXT: [[RES:%.*]] = phi i1 [ false, [[FOR_BODY]] ], [ true, [[FOR_COND]] ]
31 ; CHECK-NEXT: ret i1 [[RES]]
37 %i.08 = phi i64 [ 0, %entry ], [ %inc, %for.cond ], [ 0, %for.passthrough ]
38 %arrayidx = getelementptr inbounds i8, i8* %ptr0, i64 %i.08
39 %v0 = load i8, i8* %arrayidx
40 %arrayidx1 = getelementptr inbounds i8, i8* %ptr1, i64 %i.08
41 %v1 = load i8, i8* %arrayidx1
42 %cmp3 = icmp eq i8 %v0, %v1
43 %inc = add nuw nsw i64 %i.08, 1
44 br i1 %cmp3, label %for.passthrough, label %cleanup
47 br i1 true, label %for.cond, label %for.body
50 %cmp = icmp ult i64 %inc, 8
51 br i1 %cmp, label %for.body, label %cleanup
54 %res = phi i1 [ false, %for.body ], [ true, %for.cond ]
58 define i1 @three_blocks_in_loop(i8* %ptr0, i8* %ptr1) {
59 ; CHECK-LABEL: @three_blocks_in_loop(
61 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
63 ; CHECK-NEXT: [[I_08:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_COND:%.*]] ]
64 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, i8* [[PTR0:%.*]], i64 [[I_08]]
65 ; CHECK-NEXT: [[V0:%.*]] = load i8, i8* [[ARRAYIDX]]
66 ; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, i8* [[PTR1:%.*]], i64 [[I_08]]
67 ; CHECK-NEXT: [[V1:%.*]] = load i8, i8* [[ARRAYIDX1]]
68 ; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i8 [[V0]], [[V1]]
69 ; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[I_08]], 1
70 ; CHECK-NEXT: br i1 [[CMP3]], label [[FOR_PASSTHROUGH:%.*]], label [[CLEANUP:%.*]]
71 ; CHECK: for.passthrough:
72 ; CHECK-NEXT: br label [[FOR_COND]]
74 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[INC]], 8
75 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[CLEANUP]]
77 ; CHECK-NEXT: [[RES:%.*]] = phi i1 [ false, [[FOR_BODY]] ], [ true, [[FOR_COND]] ]
78 ; CHECK-NEXT: ret i1 [[RES]]
84 %i.08 = phi i64 [ 0, %entry ], [ %inc, %for.cond ]
85 %arrayidx = getelementptr inbounds i8, i8* %ptr0, i64 %i.08
86 %v0 = load i8, i8* %arrayidx
87 %arrayidx1 = getelementptr inbounds i8, i8* %ptr1, i64 %i.08
88 %v1 = load i8, i8* %arrayidx1
89 %cmp3 = icmp eq i8 %v0, %v1
90 %inc = add nuw nsw i64 %i.08, 1
91 br i1 %cmp3, label %for.passthrough, label %cleanup
97 %cmp = icmp ult i64 %inc, 8
98 br i1 %cmp, label %for.body, label %cleanup
101 %res = phi i1 [ false, %for.body ], [ true, %for.cond ]
105 define i1 @body_cmp_is_not_equality(i8* %ptr0, i8* %ptr1) {
106 ; CHECK-LABEL: @body_cmp_is_not_equality(
108 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
110 ; CHECK-NEXT: [[I_08:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_COND:%.*]] ]
111 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, i8* [[PTR0:%.*]], i64 [[I_08]]
112 ; CHECK-NEXT: [[V0:%.*]] = load i8, i8* [[ARRAYIDX]]
113 ; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, i8* [[PTR1:%.*]], i64 [[I_08]]
114 ; CHECK-NEXT: [[V1:%.*]] = load i8, i8* [[ARRAYIDX1]]
115 ; CHECK-NEXT: [[CMP3:%.*]] = icmp ult i8 [[V0]], [[V1]]
116 ; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[I_08]], 1
117 ; CHECK-NEXT: br i1 [[CMP3]], label [[FOR_COND]], label [[CLEANUP:%.*]]
119 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[INC]], 8
120 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[CLEANUP]]
122 ; CHECK-NEXT: [[RES:%.*]] = phi i1 [ false, [[FOR_BODY]] ], [ true, [[FOR_COND]] ]
123 ; CHECK-NEXT: ret i1 [[RES]]
129 %i.08 = phi i64 [ 0, %entry ], [ %inc, %for.cond ]
130 %arrayidx = getelementptr inbounds i8, i8* %ptr0, i64 %i.08
131 %v0 = load i8, i8* %arrayidx
132 %arrayidx1 = getelementptr inbounds i8, i8* %ptr1, i64 %i.08
133 %v1 = load i8, i8* %arrayidx1
134 %cmp3 = icmp ult i8 %v0, %v1
135 %inc = add nuw nsw i64 %i.08, 1
136 br i1 %cmp3, label %for.cond, label %cleanup
139 %cmp = icmp ult i64 %inc, 8
140 br i1 %cmp, label %for.body, label %cleanup
143 %res = phi i1 [ false, %for.body ], [ true, %for.cond ]
147 define i1 @only_one_load(i8* %ptr0, i8* %ptr1) {
148 ; CHECK-LABEL: @only_one_load(
150 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
152 ; CHECK-NEXT: [[I_08:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_COND:%.*]] ]
153 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, i8* [[PTR0:%.*]], i64 [[I_08]]
154 ; CHECK-NEXT: [[V0:%.*]] = load i8, i8* [[ARRAYIDX]]
155 ; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i8 [[V0]], 0
156 ; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[I_08]], 1
157 ; CHECK-NEXT: br i1 [[CMP3]], label [[FOR_COND]], label [[CLEANUP:%.*]]
159 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[INC]], 8
160 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[CLEANUP]]
162 ; CHECK-NEXT: [[RES:%.*]] = phi i1 [ false, [[FOR_BODY]] ], [ true, [[FOR_COND]] ]
163 ; CHECK-NEXT: ret i1 [[RES]]
169 %i.08 = phi i64 [ 0, %entry ], [ %inc, %for.cond ]
170 %arrayidx = getelementptr inbounds i8, i8* %ptr0, i64 %i.08
171 %v0 = load i8, i8* %arrayidx
172 %cmp3 = icmp eq i8 %v0, 0
173 %inc = add nuw nsw i64 %i.08, 1
174 br i1 %cmp3, label %for.cond, label %cleanup
177 %cmp = icmp ult i64 %inc, 8
178 br i1 %cmp, label %for.body, label %cleanup
181 %res = phi i1 [ false, %for.body ], [ true, %for.cond ]
185 define i1 @loads_of_less_than_byte(i7* %ptr0, i7* %ptr1) {
186 ; CHECK-LABEL: @loads_of_less_than_byte(
188 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
190 ; CHECK-NEXT: [[I_08:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_COND:%.*]] ]
191 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i7, i7* [[PTR0:%.*]], i64 [[I_08]]
192 ; CHECK-NEXT: [[V0:%.*]] = load i7, i7* [[ARRAYIDX]]
193 ; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i7, i7* [[PTR1:%.*]], i64 [[I_08]]
194 ; CHECK-NEXT: [[V1:%.*]] = load i7, i7* [[ARRAYIDX1]]
195 ; CHECK-NEXT: [[CMP3:%.*]] = icmp ult i7 [[V0]], [[V1]]
196 ; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[I_08]], 1
197 ; CHECK-NEXT: br i1 [[CMP3]], label [[FOR_COND]], label [[CLEANUP:%.*]]
199 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[INC]], 8
200 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[CLEANUP]]
202 ; CHECK-NEXT: [[RES:%.*]] = phi i1 [ false, [[FOR_BODY]] ], [ true, [[FOR_COND]] ]
203 ; CHECK-NEXT: ret i1 [[RES]]
209 %i.08 = phi i64 [ 0, %entry ], [ %inc, %for.cond ]
210 %arrayidx = getelementptr inbounds i7, i7* %ptr0, i64 %i.08
211 %v0 = load i7, i7* %arrayidx
212 %arrayidx1 = getelementptr inbounds i7, i7* %ptr1, i64 %i.08
213 %v1 = load i7, i7* %arrayidx1
214 %cmp3 = icmp ult i7 %v0, %v1
215 %inc = add nuw nsw i64 %i.08, 1
216 br i1 %cmp3, label %for.cond, label %cleanup
219 %cmp = icmp ult i64 %inc, 8
220 br i1 %cmp, label %for.body, label %cleanup
223 %res = phi i1 [ false, %for.body ], [ true, %for.cond ]
227 define i1 @loads_of_not_multiple_of_a_byte(i9* %ptr0, i9* %ptr1) {
228 ; CHECK-LABEL: @loads_of_not_multiple_of_a_byte(
230 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
232 ; CHECK-NEXT: [[I_08:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_COND:%.*]] ]
233 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i9, i9* [[PTR0:%.*]], i64 [[I_08]]
234 ; CHECK-NEXT: [[V0:%.*]] = load i9, i9* [[ARRAYIDX]]
235 ; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i9, i9* [[PTR1:%.*]], i64 [[I_08]]
236 ; CHECK-NEXT: [[V1:%.*]] = load i9, i9* [[ARRAYIDX1]]
237 ; CHECK-NEXT: [[CMP3:%.*]] = icmp ult i9 [[V0]], [[V1]]
238 ; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[I_08]], 1
239 ; CHECK-NEXT: br i1 [[CMP3]], label [[FOR_COND]], label [[CLEANUP:%.*]]
241 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[INC]], 8
242 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[CLEANUP]]
244 ; CHECK-NEXT: [[RES:%.*]] = phi i1 [ false, [[FOR_BODY]] ], [ true, [[FOR_COND]] ]
245 ; CHECK-NEXT: ret i1 [[RES]]
251 %i.08 = phi i64 [ 0, %entry ], [ %inc, %for.cond ]
252 %arrayidx = getelementptr inbounds i9, i9* %ptr0, i64 %i.08
253 %v0 = load i9, i9* %arrayidx
254 %arrayidx1 = getelementptr inbounds i9, i9* %ptr1, i64 %i.08
255 %v1 = load i9, i9* %arrayidx1
256 %cmp3 = icmp ult i9 %v0, %v1
257 %inc = add nuw nsw i64 %i.08, 1
258 br i1 %cmp3, label %for.cond, label %cleanup
261 %cmp = icmp ult i64 %inc, 8
262 br i1 %cmp, label %for.body, label %cleanup
265 %res = phi i1 [ false, %for.body ], [ true, %for.cond ]
269 define i1 @loop_instruction_used_in_phi_node_outside_loop(i8* %ptr0, i8* %ptr1) {
270 ; CHECK-LABEL: @loop_instruction_used_in_phi_node_outside_loop(
272 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
274 ; CHECK-NEXT: [[I_08:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_COND:%.*]] ]
275 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, i8* [[PTR0:%.*]], i64 [[I_08]]
276 ; CHECK-NEXT: [[V0:%.*]] = load i8, i8* [[ARRAYIDX]]
277 ; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, i8* [[PTR1:%.*]], i64 [[I_08]]
278 ; CHECK-NEXT: [[V1:%.*]] = load i8, i8* [[ARRAYIDX1]]
279 ; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i8 [[V0]], [[V1]]
280 ; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[I_08]], 1
281 ; CHECK-NEXT: br i1 [[CMP3]], label [[FOR_COND]], label [[CLEANUP:%.*]]
283 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[INC]], 8
284 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[CLEANUP]]
286 ; CHECK-NEXT: [[RES:%.*]] = phi i1 [ [[CMP3]], [[FOR_BODY]] ], [ true, [[FOR_COND]] ]
287 ; CHECK-NEXT: ret i1 [[RES]]
293 %i.08 = phi i64 [ 0, %entry ], [ %inc, %for.cond ]
294 %arrayidx = getelementptr inbounds i8, i8* %ptr0, i64 %i.08
295 %v0 = load i8, i8* %arrayidx
296 %arrayidx1 = getelementptr inbounds i8, i8* %ptr1, i64 %i.08
297 %v1 = load i8, i8* %arrayidx1
298 %cmp3 = icmp eq i8 %v0, %v1
299 %inc = add nuw nsw i64 %i.08, 1
300 br i1 %cmp3, label %for.cond, label %cleanup
303 %cmp = icmp ult i64 %inc, 8
304 br i1 %cmp, label %for.body, label %cleanup
307 %res = phi i1 [ %cmp3, %for.body ], [ true, %for.cond ]
311 define i1 @loop_has_write(i8* %ptr0, i8* %ptr1, i32* %write) {
312 ; CHECK-LABEL: @loop_has_write(
314 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
316 ; CHECK-NEXT: [[I_08:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_COND:%.*]] ]
317 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, i8* [[PTR0:%.*]], i64 [[I_08]]
318 ; CHECK-NEXT: [[V0:%.*]] = load i8, i8* [[ARRAYIDX]]
319 ; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, i8* [[PTR1:%.*]], i64 [[I_08]]
320 ; CHECK-NEXT: [[V1:%.*]] = load i8, i8* [[ARRAYIDX1]]
321 ; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i8 [[V0]], [[V1]]
322 ; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[I_08]], 1
323 ; CHECK-NEXT: br i1 [[CMP3]], label [[FOR_COND]], label [[CLEANUP:%.*]]
325 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[INC]], 8
326 ; CHECK-NEXT: store i32 0, i32* [[WRITE:%.*]]
327 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[CLEANUP]]
329 ; CHECK-NEXT: [[RES:%.*]] = phi i1 [ false, [[FOR_BODY]] ], [ true, [[FOR_COND]] ]
330 ; CHECK-NEXT: ret i1 [[RES]]
336 %i.08 = phi i64 [ 0, %entry ], [ %inc, %for.cond ]
337 %arrayidx = getelementptr inbounds i8, i8* %ptr0, i64 %i.08
338 %v0 = load i8, i8* %arrayidx
339 %arrayidx1 = getelementptr inbounds i8, i8* %ptr1, i64 %i.08
340 %v1 = load i8, i8* %arrayidx1
341 %cmp3 = icmp eq i8 %v0, %v1
342 %inc = add nuw nsw i64 %i.08, 1
343 br i1 %cmp3, label %for.cond, label %cleanup
346 %cmp = icmp ult i64 %inc, 8
347 store i32 0, i32* %write
348 br i1 %cmp, label %for.body, label %cleanup
351 %res = phi i1 [ false, %for.body ], [ true, %for.cond ]
356 define i1 @loop_has_call(i8* %ptr0, i8* %ptr1, i32* %load) {
357 ; CHECK-LABEL: @loop_has_call(
359 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
361 ; CHECK-NEXT: [[I_08:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_COND:%.*]] ]
362 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, i8* [[PTR0:%.*]], i64 [[I_08]]
363 ; CHECK-NEXT: [[V0:%.*]] = load i8, i8* [[ARRAYIDX]]
364 ; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, i8* [[PTR1:%.*]], i64 [[I_08]]
365 ; CHECK-NEXT: [[V1:%.*]] = load i8, i8* [[ARRAYIDX1]]
366 ; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i8 [[V0]], [[V1]]
367 ; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[I_08]], 1
368 ; CHECK-NEXT: br i1 [[CMP3]], label [[FOR_COND]], label [[CLEANUP:%.*]]
370 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[INC]], 8
371 ; CHECK-NEXT: tail call void @sink()
372 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[CLEANUP]]
374 ; CHECK-NEXT: [[RES:%.*]] = phi i1 [ false, [[FOR_BODY]] ], [ true, [[FOR_COND]] ]
375 ; CHECK-NEXT: ret i1 [[RES]]
381 %i.08 = phi i64 [ 0, %entry ], [ %inc, %for.cond ]
382 %arrayidx = getelementptr inbounds i8, i8* %ptr0, i64 %i.08
383 %v0 = load i8, i8* %arrayidx
384 %arrayidx1 = getelementptr inbounds i8, i8* %ptr1, i64 %i.08
385 %v1 = load i8, i8* %arrayidx1
386 %cmp3 = icmp eq i8 %v0, %v1
387 %inc = add nuw nsw i64 %i.08, 1
388 br i1 %cmp3, label %for.cond, label %cleanup
391 %cmp = icmp ult i64 %inc, 8
392 tail call void @sink()
393 br i1 %cmp, label %for.body, label %cleanup
396 %res = phi i1 [ false, %for.body ], [ true, %for.cond ]
400 define i1 @loop_has_atomic_load(i8* %ptr0, i8* %ptr1, i32* %load) {
401 ; CHECK-LABEL: @loop_has_atomic_load(
403 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
405 ; CHECK-NEXT: [[I_08:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_COND:%.*]] ]
406 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, i8* [[PTR0:%.*]], i64 [[I_08]]
407 ; CHECK-NEXT: [[V0:%.*]] = load i8, i8* [[ARRAYIDX]]
408 ; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, i8* [[PTR1:%.*]], i64 [[I_08]]
409 ; CHECK-NEXT: [[V1:%.*]] = load i8, i8* [[ARRAYIDX1]]
410 ; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i8 [[V0]], [[V1]]
411 ; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[I_08]], 1
412 ; CHECK-NEXT: br i1 [[CMP3]], label [[FOR_COND]], label [[CLEANUP:%.*]]
414 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[INC]], 8
415 ; CHECK-NEXT: [[TMP:%.*]] = load atomic i32, i32* [[LOAD:%.*]] unordered, align 1
416 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[CLEANUP]]
418 ; CHECK-NEXT: [[RES:%.*]] = phi i1 [ false, [[FOR_BODY]] ], [ true, [[FOR_COND]] ]
419 ; CHECK-NEXT: ret i1 [[RES]]
425 %i.08 = phi i64 [ 0, %entry ], [ %inc, %for.cond ]
426 %arrayidx = getelementptr inbounds i8, i8* %ptr0, i64 %i.08
427 %v0 = load i8, i8* %arrayidx
428 %arrayidx1 = getelementptr inbounds i8, i8* %ptr1, i64 %i.08
429 %v1 = load i8, i8* %arrayidx1
430 %cmp3 = icmp eq i8 %v0, %v1
431 %inc = add nuw nsw i64 %i.08, 1
432 br i1 %cmp3, label %for.cond, label %cleanup
435 %cmp = icmp ult i64 %inc, 8
436 %tmp = load atomic i32, i32* %load unordered, align 1
437 br i1 %cmp, label %for.body, label %cleanup
440 %res = phi i1 [ false, %for.body ], [ true, %for.cond ]
444 define i1 @different_load_step(i8* %ptr) {
445 ; CHECK-LABEL: @different_load_step(
447 ; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, i8* [[PTR:%.*]], i64 8
448 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
450 ; CHECK-NEXT: [[I_015:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
451 ; CHECK-NEXT: [[PTR1_014:%.*]] = phi i8* [ [[ADD_PTR]], [[ENTRY]] ], [ [[ADD_PTR3:%.*]], [[FOR_INC]] ]
452 ; CHECK-NEXT: [[PTR0_013:%.*]] = phi i8* [ [[PTR]], [[ENTRY]] ], [ [[INCDEC_PTR:%.*]], [[FOR_INC]] ]
453 ; CHECK-NEXT: [[V0:%.*]] = load i8, i8* [[PTR0_013]]
454 ; CHECK-NEXT: [[V1:%.*]] = load i8, i8* [[PTR1_014]]
455 ; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i8 [[V0]], [[V1]]
456 ; CHECK-NEXT: br i1 [[CMP2]], label [[FOR_INC]], label [[CLEANUP:%.*]]
458 ; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[I_015]], 1
459 ; CHECK-NEXT: [[INCDEC_PTR]] = getelementptr inbounds i8, i8* [[PTR0_013]], i64 1
460 ; CHECK-NEXT: [[ADD_PTR3]] = getelementptr inbounds i8, i8* [[PTR1_014]], i64 2
461 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[INC]], 16
462 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[CLEANUP]]
464 ; CHECK-NEXT: [[RES:%.*]] = phi i1 [ false, [[FOR_BODY]] ], [ true, [[FOR_INC]] ]
465 ; CHECK-NEXT: ret i1 [[RES]]
468 %add.ptr = getelementptr inbounds i8, i8* %ptr, i64 8
472 %i.015 = phi i64 [ 0, %entry ], [ %inc, %for.inc ]
473 %ptr1.014 = phi i8* [ %add.ptr, %entry ], [ %add.ptr3, %for.inc ]
474 %ptr0.013 = phi i8* [ %ptr, %entry ], [ %incdec.ptr, %for.inc ]
475 %v0 = load i8, i8* %ptr0.013
476 %v1 = load i8, i8* %ptr1.014
477 %cmp2 = icmp eq i8 %v0, %v1
478 br i1 %cmp2, label %for.inc, label %cleanup
481 %inc = add nuw nsw i64 %i.015, 1
482 %incdec.ptr = getelementptr inbounds i8, i8* %ptr0.013, i64 1
483 %add.ptr3 = getelementptr inbounds i8, i8* %ptr1.014, i64 2
484 %cmp = icmp ult i64 %inc, 16
485 br i1 %cmp, label %for.body, label %cleanup
488 %res = phi i1 [ false, %for.body ], [ true, %for.inc ]
492 define i1 @step_is_variable(i8* %ptr, i64 %step) {
493 ; CHECK-LABEL: @step_is_variable(
495 ; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, i8* [[PTR:%.*]], i64 8
496 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
498 ; CHECK-NEXT: [[I_015:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
499 ; CHECK-NEXT: [[PTR1_014:%.*]] = phi i8* [ [[ADD_PTR]], [[ENTRY]] ], [ [[ADD_PTR3:%.*]], [[FOR_INC]] ]
500 ; CHECK-NEXT: [[PTR0_013:%.*]] = phi i8* [ [[PTR]], [[ENTRY]] ], [ [[INCDEC_PTR:%.*]], [[FOR_INC]] ]
501 ; CHECK-NEXT: [[V0:%.*]] = load i8, i8* [[PTR0_013]]
502 ; CHECK-NEXT: [[V1:%.*]] = load i8, i8* [[PTR1_014]]
503 ; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i8 [[V0]], [[V1]]
504 ; CHECK-NEXT: br i1 [[CMP2]], label [[FOR_INC]], label [[CLEANUP:%.*]]
506 ; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[I_015]], [[STEP:%.*]]
507 ; CHECK-NEXT: [[INCDEC_PTR]] = getelementptr inbounds i8, i8* [[PTR0_013]], i64 1
508 ; CHECK-NEXT: [[ADD_PTR3]] = getelementptr inbounds i8, i8* [[PTR1_014]], i64 1
509 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[INC]], 16
510 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[CLEANUP]]
512 ; CHECK-NEXT: [[RES:%.*]] = phi i1 [ false, [[FOR_BODY]] ], [ true, [[FOR_INC]] ]
513 ; CHECK-NEXT: ret i1 [[RES]]
516 %add.ptr = getelementptr inbounds i8, i8* %ptr, i64 8
520 %i.015 = phi i64 [ 0, %entry ], [ %inc, %for.inc ]
521 %ptr1.014 = phi i8* [ %add.ptr, %entry ], [ %add.ptr3, %for.inc ]
522 %ptr0.013 = phi i8* [ %ptr, %entry ], [ %incdec.ptr, %for.inc ]
523 %v0 = load i8, i8* %ptr0.013
524 %v1 = load i8, i8* %ptr1.014
525 %cmp2 = icmp eq i8 %v0, %v1
526 br i1 %cmp2, label %for.inc, label %cleanup
529 %inc = add nuw nsw i64 %i.015, %step
530 %incdec.ptr = getelementptr inbounds i8, i8* %ptr0.013, i64 1
531 %add.ptr3 = getelementptr inbounds i8, i8* %ptr1.014, i64 1
532 %cmp = icmp ult i64 %inc, 16
533 br i1 %cmp, label %for.body, label %cleanup
536 %res = phi i1 [ false, %for.body ], [ true, %for.inc ]
540 define i1 @load_step_is_variable(i8* %ptr, i64 %step) {
541 ; CHECK-LABEL: @load_step_is_variable(
543 ; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, i8* [[PTR:%.*]], i64 8
544 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
546 ; CHECK-NEXT: [[I_015:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
547 ; CHECK-NEXT: [[PTR1_014:%.*]] = phi i8* [ [[ADD_PTR]], [[ENTRY]] ], [ [[ADD_PTR3:%.*]], [[FOR_INC]] ]
548 ; CHECK-NEXT: [[PTR0_013:%.*]] = phi i8* [ [[PTR]], [[ENTRY]] ], [ [[INCDEC_PTR:%.*]], [[FOR_INC]] ]
549 ; CHECK-NEXT: [[V0:%.*]] = load i8, i8* [[PTR0_013]]
550 ; CHECK-NEXT: [[V1:%.*]] = load i8, i8* [[PTR1_014]]
551 ; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i8 [[V0]], [[V1]]
552 ; CHECK-NEXT: br i1 [[CMP2]], label [[FOR_INC]], label [[CLEANUP:%.*]]
554 ; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[I_015]], 1
555 ; CHECK-NEXT: [[INCDEC_PTR]] = getelementptr inbounds i8, i8* [[PTR0_013]], i64 [[STEP:%.*]]
556 ; CHECK-NEXT: [[ADD_PTR3]] = getelementptr inbounds i8, i8* [[PTR1_014]], i64 [[STEP]]
557 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[INC]], 16
558 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[CLEANUP]]
560 ; CHECK-NEXT: [[RES:%.*]] = phi i1 [ false, [[FOR_BODY]] ], [ true, [[FOR_INC]] ]
561 ; CHECK-NEXT: ret i1 [[RES]]
564 %add.ptr = getelementptr inbounds i8, i8* %ptr, i64 8
568 %i.015 = phi i64 [ 0, %entry ], [ %inc, %for.inc ]
569 %ptr1.014 = phi i8* [ %add.ptr, %entry ], [ %add.ptr3, %for.inc ]
570 %ptr0.013 = phi i8* [ %ptr, %entry ], [ %incdec.ptr, %for.inc ]
571 %v0 = load i8, i8* %ptr0.013
572 %v1 = load i8, i8* %ptr1.014
573 %cmp2 = icmp eq i8 %v0, %v1
574 br i1 %cmp2, label %for.inc, label %cleanup
577 %inc = add nuw nsw i64 %i.015, 1
578 %incdec.ptr = getelementptr inbounds i8, i8* %ptr0.013, i64 %step
579 %add.ptr3 = getelementptr inbounds i8, i8* %ptr1.014, i64 %step
580 %cmp = icmp ult i64 %inc, 16
581 br i1 %cmp, label %for.body, label %cleanup
584 %res = phi i1 [ false, %for.body ], [ true, %for.inc ]
588 define i1 @step_and_load_step_is_variable(i8* %ptr, i64 %step) {
589 ; CHECK-LABEL: @step_and_load_step_is_variable(
591 ; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, i8* [[PTR:%.*]], i64 8
592 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
594 ; CHECK-NEXT: [[I_015:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
595 ; CHECK-NEXT: [[PTR1_014:%.*]] = phi i8* [ [[ADD_PTR]], [[ENTRY]] ], [ [[ADD_PTR3:%.*]], [[FOR_INC]] ]
596 ; CHECK-NEXT: [[PTR0_013:%.*]] = phi i8* [ [[PTR]], [[ENTRY]] ], [ [[INCDEC_PTR:%.*]], [[FOR_INC]] ]
597 ; CHECK-NEXT: [[V0:%.*]] = load i8, i8* [[PTR0_013]]
598 ; CHECK-NEXT: [[V1:%.*]] = load i8, i8* [[PTR1_014]]
599 ; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i8 [[V0]], [[V1]]
600 ; CHECK-NEXT: br i1 [[CMP2]], label [[FOR_INC]], label [[CLEANUP:%.*]]
602 ; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[I_015]], [[STEP:%.*]]
603 ; CHECK-NEXT: [[INCDEC_PTR]] = getelementptr inbounds i8, i8* [[PTR0_013]], i64 [[STEP]]
604 ; CHECK-NEXT: [[ADD_PTR3]] = getelementptr inbounds i8, i8* [[PTR1_014]], i64 [[STEP]]
605 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[INC]], 16
606 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[CLEANUP]]
608 ; CHECK-NEXT: [[RES:%.*]] = phi i1 [ false, [[FOR_BODY]] ], [ true, [[FOR_INC]] ]
609 ; CHECK-NEXT: ret i1 [[RES]]
612 %add.ptr = getelementptr inbounds i8, i8* %ptr, i64 8
616 %i.015 = phi i64 [ 0, %entry ], [ %inc, %for.inc ]
617 %ptr1.014 = phi i8* [ %add.ptr, %entry ], [ %add.ptr3, %for.inc ]
618 %ptr0.013 = phi i8* [ %ptr, %entry ], [ %incdec.ptr, %for.inc ]
619 %v0 = load i8, i8* %ptr0.013
620 %v1 = load i8, i8* %ptr1.014
621 %cmp2 = icmp eq i8 %v0, %v1
622 br i1 %cmp2, label %for.inc, label %cleanup
625 %inc = add nuw nsw i64 %i.015, %step
626 %incdec.ptr = getelementptr inbounds i8, i8* %ptr0.013, i64 %step
627 %add.ptr3 = getelementptr inbounds i8, i8* %ptr1.014, i64 %step
628 %cmp = icmp ult i64 %inc, 16
629 br i1 %cmp, label %for.body, label %cleanup
632 %res = phi i1 [ false, %for.body ], [ true, %for.inc ]
636 define i1 @load_step_not_affine(i8* %ptr) {
637 ; CHECK-LABEL: @load_step_not_affine(
639 ; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, i8* [[PTR:%.*]], i64 8
640 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
642 ; CHECK-NEXT: [[I_018:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
643 ; CHECK-NEXT: [[PTR1_017:%.*]] = phi i8* [ [[ADD_PTR]], [[ENTRY]] ], [ [[ADD_PTR4:%.*]], [[FOR_INC]] ]
644 ; CHECK-NEXT: [[PTR0_016:%.*]] = phi i8* [ [[PTR]], [[ENTRY]] ], [ [[ADD_PTR3:%.*]], [[FOR_INC]] ]
645 ; CHECK-NEXT: [[V0:%.*]] = load i8, i8* [[PTR0_016]]
646 ; CHECK-NEXT: [[V1:%.*]] = load i8, i8* [[PTR1_017]]
647 ; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i8 [[V0]], [[V1]]
648 ; CHECK-NEXT: br i1 [[CMP2]], label [[FOR_INC]], label [[CLEANUP:%.*]]
650 ; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[I_018]], 1
651 ; CHECK-NEXT: [[ADD_PTR3]] = getelementptr inbounds i8, i8* [[PTR0_016]], i64 [[INC]]
652 ; CHECK-NEXT: [[ADD_PTR4]] = getelementptr inbounds i8, i8* [[PTR1_017]], i64 [[INC]]
653 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[INC]], 16
654 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[CLEANUP]]
656 ; CHECK-NEXT: [[RES:%.*]] = phi i1 [ false, [[FOR_BODY]] ], [ true, [[FOR_INC]] ]
657 ; CHECK-NEXT: ret i1 [[RES]]
660 %add.ptr = getelementptr inbounds i8, i8* %ptr, i64 8
664 %i.018 = phi i64 [ 0, %entry ], [ %inc, %for.inc ]
665 %ptr1.017 = phi i8* [ %add.ptr, %entry ], [ %add.ptr4, %for.inc ]
666 %ptr0.016 = phi i8* [ %ptr, %entry ], [ %add.ptr3, %for.inc ]
667 %v0 = load i8, i8* %ptr0.016
668 %v1 = load i8, i8* %ptr1.017
669 %cmp2 = icmp eq i8 %v0, %v1
670 br i1 %cmp2, label %for.inc, label %cleanup
673 %inc = add nuw nsw i64 %i.018, 1
674 %add.ptr3 = getelementptr inbounds i8, i8* %ptr0.016, i64 %inc
675 %add.ptr4 = getelementptr inbounds i8, i8* %ptr1.017, i64 %inc
676 %cmp = icmp ult i64 %inc, 16
677 br i1 %cmp, label %for.body, label %cleanup
680 %res = phi i1 [ false, %for.body ], [ true, %for.inc ]
684 define i1 @no_overlap_between_loads(i8* %ptr) {
685 ; CHECK-LABEL: @no_overlap_between_loads(
687 ; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, i8* [[PTR:%.*]], i64 8
688 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
690 ; CHECK-NEXT: [[I_016:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
691 ; CHECK-NEXT: [[PTR1_015:%.*]] = phi i8* [ [[ADD_PTR]], [[ENTRY]] ], [ [[ADD_PTR4:%.*]], [[FOR_INC]] ]
692 ; CHECK-NEXT: [[PTR0_014:%.*]] = phi i8* [ [[PTR]], [[ENTRY]] ], [ [[ADD_PTR3:%.*]], [[FOR_INC]] ]
693 ; CHECK-NEXT: [[V0:%.*]] = load i8, i8* [[PTR0_014]]
694 ; CHECK-NEXT: [[V1:%.*]] = load i8, i8* [[PTR1_015]]
695 ; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i8 [[V0]], [[V1]]
696 ; CHECK-NEXT: br i1 [[CMP2]], label [[FOR_INC]], label [[CLEANUP:%.*]]
698 ; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[I_016]], 1
699 ; CHECK-NEXT: [[ADD_PTR3]] = getelementptr inbounds i8, i8* [[PTR0_014]], i64 2
700 ; CHECK-NEXT: [[ADD_PTR4]] = getelementptr inbounds i8, i8* [[PTR1_015]], i64 2
701 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[INC]], 16
702 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[CLEANUP]]
704 ; CHECK-NEXT: [[RES:%.*]] = phi i1 [ false, [[FOR_BODY]] ], [ true, [[FOR_INC]] ]
705 ; CHECK-NEXT: ret i1 [[RES]]
708 %add.ptr = getelementptr inbounds i8, i8* %ptr, i64 8
712 %i.016 = phi i64 [ 0, %entry ], [ %inc, %for.inc ]
713 %ptr1.015 = phi i8* [ %add.ptr, %entry ], [ %add.ptr4, %for.inc ]
714 %ptr0.014 = phi i8* [ %ptr, %entry ], [ %add.ptr3, %for.inc ]
715 %v0 = load i8, i8* %ptr0.014
716 %v1 = load i8, i8* %ptr1.015
717 %cmp2 = icmp eq i8 %v0, %v1
718 br i1 %cmp2, label %for.inc, label %cleanup
721 %inc = add nuw nsw i64 %i.016, 1
722 %add.ptr3 = getelementptr inbounds i8, i8* %ptr0.014, i64 2
723 %add.ptr4 = getelementptr inbounds i8, i8* %ptr1.015, i64 2
724 %cmp = icmp ult i64 %inc, 16
725 br i1 %cmp, label %for.body, label %cleanup
728 %res = phi i1 [ false, %for.body ], [ true, %for.inc ]
732 define i1 @volatile_loads(i8* %ptr) {
733 ; CHECK-LABEL: @volatile_loads(
735 ; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, i8* [[PTR:%.*]], i64 8
736 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
738 ; CHECK-NEXT: [[I_016:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
739 ; CHECK-NEXT: [[PTR1_015:%.*]] = phi i8* [ [[ADD_PTR]], [[ENTRY]] ], [ [[ADD_PTR4:%.*]], [[FOR_INC]] ]
740 ; CHECK-NEXT: [[PTR0_014:%.*]] = phi i8* [ [[PTR]], [[ENTRY]] ], [ [[ADD_PTR3:%.*]], [[FOR_INC]] ]
741 ; CHECK-NEXT: [[V0:%.*]] = load volatile i8, i8* [[PTR0_014]]
742 ; CHECK-NEXT: [[V1:%.*]] = load volatile i8, i8* [[PTR1_015]]
743 ; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i8 [[V0]], [[V1]]
744 ; CHECK-NEXT: br i1 [[CMP2]], label [[FOR_INC]], label [[CLEANUP:%.*]]
746 ; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[I_016]], 1
747 ; CHECK-NEXT: [[ADD_PTR3]] = getelementptr inbounds i8, i8* [[PTR0_014]], i64 1
748 ; CHECK-NEXT: [[ADD_PTR4]] = getelementptr inbounds i8, i8* [[PTR1_015]], i64 1
749 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[INC]], 16
750 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[CLEANUP]]
752 ; CHECK-NEXT: [[RES:%.*]] = phi i1 [ false, [[FOR_BODY]] ], [ true, [[FOR_INC]] ]
753 ; CHECK-NEXT: ret i1 [[RES]]
756 %add.ptr = getelementptr inbounds i8, i8* %ptr, i64 8
760 %i.016 = phi i64 [ 0, %entry ], [ %inc, %for.inc ]
761 %ptr1.015 = phi i8* [ %add.ptr, %entry ], [ %add.ptr4, %for.inc ]
762 %ptr0.014 = phi i8* [ %ptr, %entry ], [ %add.ptr3, %for.inc ]
763 %v0 = load volatile i8, i8* %ptr0.014
764 %v1 = load volatile i8, i8* %ptr1.015
765 %cmp2 = icmp eq i8 %v0, %v1
766 br i1 %cmp2, label %for.inc, label %cleanup
769 %inc = add nuw nsw i64 %i.016, 1
770 %add.ptr3 = getelementptr inbounds i8, i8* %ptr0.014, i64 1
771 %add.ptr4 = getelementptr inbounds i8, i8* %ptr1.015, i64 1
772 %cmp = icmp ult i64 %inc, 16
773 br i1 %cmp, label %for.body, label %cleanup
776 %res = phi i1 [ false, %for.body ], [ true, %for.inc ]
780 define i1 @atomic_loads(i8* %ptr) {
781 ; CHECK-LABEL: @atomic_loads(
783 ; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, i8* [[PTR:%.*]], i64 8
784 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
786 ; CHECK-NEXT: [[I_016:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
787 ; CHECK-NEXT: [[PTR1_015:%.*]] = phi i8* [ [[ADD_PTR]], [[ENTRY]] ], [ [[ADD_PTR4:%.*]], [[FOR_INC]] ]
788 ; CHECK-NEXT: [[PTR0_014:%.*]] = phi i8* [ [[PTR]], [[ENTRY]] ], [ [[ADD_PTR3:%.*]], [[FOR_INC]] ]
789 ; CHECK-NEXT: [[V0:%.*]] = load atomic i8, i8* [[PTR0_014]] unordered, align 1
790 ; CHECK-NEXT: [[V1:%.*]] = load atomic i8, i8* [[PTR1_015]] unordered, align 1
791 ; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i8 [[V0]], [[V1]]
792 ; CHECK-NEXT: br i1 [[CMP2]], label [[FOR_INC]], label [[CLEANUP:%.*]]
794 ; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[I_016]], 1
795 ; CHECK-NEXT: [[ADD_PTR3]] = getelementptr inbounds i8, i8* [[PTR0_014]], i64 1
796 ; CHECK-NEXT: [[ADD_PTR4]] = getelementptr inbounds i8, i8* [[PTR1_015]], i64 1
797 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[INC]], 16
798 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[CLEANUP]]
800 ; CHECK-NEXT: [[RES:%.*]] = phi i1 [ false, [[FOR_BODY]] ], [ true, [[FOR_INC]] ]
801 ; CHECK-NEXT: ret i1 [[RES]]
804 %add.ptr = getelementptr inbounds i8, i8* %ptr, i64 8
808 %i.016 = phi i64 [ 0, %entry ], [ %inc, %for.inc ]
809 %ptr1.015 = phi i8* [ %add.ptr, %entry ], [ %add.ptr4, %for.inc ]
810 %ptr0.014 = phi i8* [ %ptr, %entry ], [ %add.ptr3, %for.inc ]
811 %v0 = load atomic i8, i8* %ptr0.014 unordered, align 1
812 %v1 = load atomic i8, i8* %ptr1.015 unordered, align 1
813 %cmp2 = icmp eq i8 %v0, %v1
814 br i1 %cmp2, label %for.inc, label %cleanup
817 %inc = add nuw nsw i64 %i.016, 1
818 %add.ptr3 = getelementptr inbounds i8, i8* %ptr0.014, i64 1
819 %add.ptr4 = getelementptr inbounds i8, i8* %ptr1.015, i64 1
820 %cmp = icmp ult i64 %inc, 16
821 br i1 %cmp, label %for.body, label %cleanup
824 %res = phi i1 [ false, %for.body ], [ true, %for.inc ]
828 define i1 @address_space(i8 addrspace(1)* %ptr) {
829 ; CHECK-LABEL: @address_space(
831 ; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, i8 addrspace(1)* [[PTR:%.*]], i64 8
832 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
834 ; CHECK-NEXT: [[I_016:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
835 ; CHECK-NEXT: [[PTR1_015:%.*]] = phi i8 addrspace(1)* [ [[ADD_PTR]], [[ENTRY]] ], [ [[ADD_PTR4:%.*]], [[FOR_INC]] ]
836 ; CHECK-NEXT: [[PTR0_014:%.*]] = phi i8 addrspace(1)* [ [[PTR]], [[ENTRY]] ], [ [[ADD_PTR3:%.*]], [[FOR_INC]] ]
837 ; CHECK-NEXT: [[V0:%.*]] = load i8, i8 addrspace(1)* [[PTR0_014]]
838 ; CHECK-NEXT: [[V1:%.*]] = load i8, i8 addrspace(1)* [[PTR1_015]]
839 ; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i8 [[V0]], [[V1]]
840 ; CHECK-NEXT: br i1 [[CMP2]], label [[FOR_INC]], label [[CLEANUP:%.*]]
842 ; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[I_016]], 1
843 ; CHECK-NEXT: [[ADD_PTR3]] = getelementptr inbounds i8, i8 addrspace(1)* [[PTR0_014]], i64 1
844 ; CHECK-NEXT: [[ADD_PTR4]] = getelementptr inbounds i8, i8 addrspace(1)* [[PTR1_015]], i64 1
845 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[INC]], 16
846 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[CLEANUP]]
848 ; CHECK-NEXT: [[RES:%.*]] = phi i1 [ false, [[FOR_BODY]] ], [ true, [[FOR_INC]] ]
849 ; CHECK-NEXT: ret i1 [[RES]]
852 %add.ptr = getelementptr inbounds i8, i8 addrspace(1)* %ptr, i64 8
856 %i.016 = phi i64 [ 0, %entry ], [ %inc, %for.inc ]
857 %ptr1.015 = phi i8 addrspace(1)* [ %add.ptr, %entry ], [ %add.ptr4, %for.inc ]
858 %ptr0.014 = phi i8 addrspace(1)* [ %ptr, %entry ], [ %add.ptr3, %for.inc ]
859 %v0 = load i8, i8 addrspace(1)* %ptr0.014
860 %v1 = load i8, i8 addrspace(1)* %ptr1.015
861 %cmp2 = icmp eq i8 %v0, %v1
862 br i1 %cmp2, label %for.inc, label %cleanup
865 %inc = add nuw nsw i64 %i.016, 1
866 %add.ptr3 = getelementptr inbounds i8, i8 addrspace(1)* %ptr0.014, i64 1
867 %add.ptr4 = getelementptr inbounds i8, i8 addrspace(1)* %ptr1.015, i64 1
868 %cmp = icmp ult i64 %inc, 16
869 br i1 %cmp, label %for.body, label %cleanup
872 %res = phi i1 [ false, %for.body ], [ true, %for.inc ]
876 ; See https://bugs.llvm.org/show_bug.cgi?id=43206 for original reduced (but runnable) test:
878 ; bool do_check(int i_max, int j_max, int**bptr, int* fillch) {
879 ; for (int i = 0; i < i_max; i++)
880 ; for (int j = 0; j < j_max; j++)
881 ; if (bptr[i][j] != fillch[i])
885 ; The loads proceed differently here - fillch[i] changes once per outer loop,
886 ; while bptr[i][j] changes both in inner loop, and in outer loop.
887 define i1 @pr43206_different_loops(i32 %i_max, i32 %j_max, i32** %bptr, i32* %fillch) {
888 ; CHECK-LABEL: @pr43206_different_loops(
890 ; CHECK-NEXT: [[CMP31:%.*]] = icmp sgt i32 [[I_MAX:%.*]], 0
891 ; CHECK-NEXT: [[CMP229:%.*]] = icmp sgt i32 [[J_MAX:%.*]], 0
892 ; CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[CMP31]], [[CMP229]]
893 ; CHECK-NEXT: br i1 [[OR_COND]], label [[FOR_COND1_PREHEADER_US_PREHEADER:%.*]], label [[CLEANUP12:%.*]]
894 ; CHECK: for.cond1.preheader.us.preheader:
895 ; CHECK-NEXT: [[WIDE_TRIP_COUNT38:%.*]] = zext i32 [[I_MAX]] to i64
896 ; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[J_MAX]] to i64
897 ; CHECK-NEXT: br label [[FOR_COND1_PREHEADER_US:%.*]]
898 ; CHECK: for.cond1.preheader.us:
899 ; CHECK-NEXT: [[INDVARS_IV36:%.*]] = phi i64 [ 0, [[FOR_COND1_PREHEADER_US_PREHEADER]] ], [ [[INDVARS_IV_NEXT37:%.*]], [[FOR_COND1_FOR_INC10_CRIT_EDGE_US:%.*]] ]
900 ; CHECK-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32*, i32** [[BPTR:%.*]], i64 [[INDVARS_IV36]]
901 ; CHECK-NEXT: [[V0:%.*]] = load i32*, i32** [[ARRAYIDX_US]], align 8
902 ; CHECK-NEXT: [[ARRAYIDX8_US:%.*]] = getelementptr inbounds i32, i32* [[FILLCH:%.*]], i64 [[INDVARS_IV36]]
903 ; CHECK-NEXT: [[V1:%.*]] = load i32, i32* [[ARRAYIDX8_US]], align 4
904 ; CHECK-NEXT: br label [[FOR_BODY4_US:%.*]]
905 ; CHECK: for.cond1.us:
906 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT:%.*]], [[WIDE_TRIP_COUNT]]
907 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND1_FOR_INC10_CRIT_EDGE_US]], label [[FOR_BODY4_US]]
908 ; CHECK: for.body4.us:
909 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[FOR_COND1_PREHEADER_US]] ], [ [[INDVARS_IV_NEXT]], [[FOR_COND1_US:%.*]] ]
910 ; CHECK-NEXT: [[ARRAYIDX6_US:%.*]] = getelementptr inbounds i32, i32* [[V0]], i64 [[INDVARS_IV]]
911 ; CHECK-NEXT: [[V2:%.*]] = load i32, i32* [[ARRAYIDX6_US]], align 4
912 ; CHECK-NEXT: [[CMP9_US:%.*]] = icmp eq i32 [[V2]], [[V1]]
913 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
914 ; CHECK-NEXT: br i1 [[CMP9_US]], label [[FOR_COND1_US]], label [[CLEANUP12_LOOPEXIT:%.*]]
915 ; CHECK: for.cond1.for.inc10_crit_edge.us:
916 ; CHECK-NEXT: [[INDVARS_IV_NEXT37]] = add nuw nsw i64 [[INDVARS_IV36]], 1
917 ; CHECK-NEXT: [[EXITCOND39:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT37]], [[WIDE_TRIP_COUNT38]]
918 ; CHECK-NEXT: br i1 [[EXITCOND39]], label [[CLEANUP12_LOOPEXIT1:%.*]], label [[FOR_COND1_PREHEADER_US]]
919 ; CHECK: cleanup12.loopexit:
920 ; CHECK-NEXT: br label [[CLEANUP12]]
921 ; CHECK: cleanup12.loopexit1:
922 ; CHECK-NEXT: br label [[CLEANUP12]]
924 ; CHECK-NEXT: [[V3:%.*]] = phi i1 [ false, [[ENTRY:%.*]] ], [ true, [[CLEANUP12_LOOPEXIT]] ], [ false, [[CLEANUP12_LOOPEXIT1]] ]
925 ; CHECK-NEXT: ret i1 [[V3]]
928 %cmp31 = icmp sgt i32 %i_max, 0
929 %cmp229 = icmp sgt i32 %j_max, 0
930 %or.cond = and i1 %cmp31, %cmp229
931 br i1 %or.cond, label %for.cond1.preheader.us.preheader, label %cleanup12
933 for.cond1.preheader.us.preheader: ; preds = %entry
934 %wide.trip.count38 = zext i32 %i_max to i64
935 %wide.trip.count = zext i32 %j_max to i64
936 br label %for.cond1.preheader.us
938 for.cond1.preheader.us: ; preds = %for.cond1.for.inc10_crit_edge.us, %for.cond1.preheader.us.preheader
939 %indvars.iv36 = phi i64 [ 0, %for.cond1.preheader.us.preheader ], [ %indvars.iv.next37, %for.cond1.for.inc10_crit_edge.us ]
940 %arrayidx.us = getelementptr inbounds i32*, i32** %bptr, i64 %indvars.iv36
941 %v0 = load i32*, i32** %arrayidx.us, align 8
942 %arrayidx8.us = getelementptr inbounds i32, i32* %fillch, i64 %indvars.iv36
943 %v1 = load i32, i32* %arrayidx8.us, align 4
944 br label %for.body4.us
946 for.cond1.us: ; preds = %for.body4.us
947 %exitcond = icmp eq i64 %indvars.iv.next, %wide.trip.count
948 br i1 %exitcond, label %for.cond1.for.inc10_crit_edge.us, label %for.body4.us
950 for.body4.us: ; preds = %for.cond1.us, %for.cond1.preheader.us
951 %indvars.iv = phi i64 [ 0, %for.cond1.preheader.us ], [ %indvars.iv.next, %for.cond1.us ]
952 %arrayidx6.us = getelementptr inbounds i32, i32* %v0, i64 %indvars.iv
953 %v2 = load i32, i32* %arrayidx6.us, align 4
954 %cmp9.us = icmp eq i32 %v2, %v1
955 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
956 br i1 %cmp9.us, label %for.cond1.us, label %cleanup12
958 for.cond1.for.inc10_crit_edge.us: ; preds = %for.cond1.us
959 %indvars.iv.next37 = add nuw nsw i64 %indvars.iv36, 1
960 %exitcond39 = icmp eq i64 %indvars.iv.next37, %wide.trip.count38
961 br i1 %exitcond39, label %cleanup12, label %for.cond1.preheader.us
963 cleanup12: ; preds = %for.cond1.for.inc10_crit_edge.us, %for.body4.us, %entry
964 %v3 = phi i1 [ false, %entry ], [ true, %for.body4.us ], [ false, %for.cond1.for.inc10_crit_edge.us ]
968 ; From https://bugs.llvm.org/show_bug.cgi?id=43687
969 define void @body_always_branches_to_latch(i16* %a, i16* %b, i32) {
970 ; CHECK-LABEL: @body_always_branches_to_latch(
972 ; CHECK-NEXT: br label [[BODY:%.*]]
974 ; CHECK-NEXT: [[A_DATA:%.*]] = load i16, i16* [[A:%.*]]
975 ; CHECK-NEXT: [[B_DATA:%.*]] = load i16, i16* [[B:%.*]]
976 ; CHECK-NEXT: [[COMPARED_EQUAL:%.*]] = icmp eq i16 [[A_DATA]], [[B_DATA]]
977 ; CHECK-NEXT: br i1 [[COMPARED_EQUAL]], label [[LATCH:%.*]], label [[LATCH]]
979 ; CHECK-NEXT: [[SHOULD_CONTINUE:%.*]] = icmp slt i32 undef, 79
980 ; CHECK-NEXT: br i1 [[SHOULD_CONTINUE]], label [[BODY]], label [[END:%.*]]
982 ; CHECK-NEXT: ret void
987 body: ; preds = %latch, %for.end1317
988 %a_data = load i16, i16* %a
989 %b_data = load i16, i16* %b
990 %compared_equal = icmp eq i16 %a_data, %b_data
991 br i1 %compared_equal, label %latch, label %latch
993 latch: ; preds = %body, %body
994 %should_continue = icmp slt i32 undef, 79
995 br i1 %should_continue, label %body, label %end
997 end: ; preds = %latch