[InstCombine] Signed saturation tests. NFC
[llvm-complete.git] / test / Transforms / LoopIdiom / bcmp-negative-tests.ll
blobe35821bfb0122ed306cf3e00c3a25e367a508eb6
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(
10 ; CHECK-NEXT:  entry:
11 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
12 ; CHECK:       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]]
26 ; CHECK:       for.cond:
27 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i64 [[INC]], 8
28 ; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY_BACKEDGE]], label [[CLEANUP]]
29 ; CHECK:       cleanup:
30 ; CHECK-NEXT:    [[RES:%.*]] = phi i1 [ false, [[FOR_BODY]] ], [ true, [[FOR_COND]] ]
31 ; CHECK-NEXT:    ret i1 [[RES]]
33 entry:
34   br label %for.body
36 for.body:
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
46 for.passthrough:
47   br i1 true, label %for.cond, label %for.body
49 for.cond:
50   %cmp = icmp ult i64 %inc, 8
51   br i1 %cmp, label %for.body, label %cleanup
53 cleanup:
54   %res = phi i1 [ false, %for.body ], [ true, %for.cond ]
55   ret i1 %res
58 define i1 @three_blocks_in_loop(i8* %ptr0, i8* %ptr1) {
59 ; CHECK-LABEL: @three_blocks_in_loop(
60 ; CHECK-NEXT:  entry:
61 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
62 ; CHECK:       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]]
73 ; CHECK:       for.cond:
74 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i64 [[INC]], 8
75 ; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[CLEANUP]]
76 ; CHECK:       cleanup:
77 ; CHECK-NEXT:    [[RES:%.*]] = phi i1 [ false, [[FOR_BODY]] ], [ true, [[FOR_COND]] ]
78 ; CHECK-NEXT:    ret i1 [[RES]]
80 entry:
81   br label %for.body
83 for.body:
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
93 for.passthrough:
94   br label %for.cond
96 for.cond:
97   %cmp = icmp ult i64 %inc, 8
98   br i1 %cmp, label %for.body, label %cleanup
100 cleanup:
101   %res = phi i1 [ false, %for.body ], [ true, %for.cond ]
102   ret i1 %res
105 define i1 @body_cmp_is_not_equality(i8* %ptr0, i8* %ptr1) {
106 ; CHECK-LABEL: @body_cmp_is_not_equality(
107 ; CHECK-NEXT:  entry:
108 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
109 ; CHECK:       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:%.*]]
118 ; CHECK:       for.cond:
119 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i64 [[INC]], 8
120 ; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[CLEANUP]]
121 ; CHECK:       cleanup:
122 ; CHECK-NEXT:    [[RES:%.*]] = phi i1 [ false, [[FOR_BODY]] ], [ true, [[FOR_COND]] ]
123 ; CHECK-NEXT:    ret i1 [[RES]]
125 entry:
126   br label %for.body
128 for.body:
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
138 for.cond:
139   %cmp = icmp ult i64 %inc, 8
140   br i1 %cmp, label %for.body, label %cleanup
142 cleanup:
143   %res = phi i1 [ false, %for.body ], [ true, %for.cond ]
144   ret i1 %res
147 define i1 @only_one_load(i8* %ptr0, i8* %ptr1) {
148 ; CHECK-LABEL: @only_one_load(
149 ; CHECK-NEXT:  entry:
150 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
151 ; CHECK:       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:%.*]]
158 ; CHECK:       for.cond:
159 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i64 [[INC]], 8
160 ; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[CLEANUP]]
161 ; CHECK:       cleanup:
162 ; CHECK-NEXT:    [[RES:%.*]] = phi i1 [ false, [[FOR_BODY]] ], [ true, [[FOR_COND]] ]
163 ; CHECK-NEXT:    ret i1 [[RES]]
165 entry:
166   br label %for.body
168 for.body:
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
176 for.cond:
177   %cmp = icmp ult i64 %inc, 8
178   br i1 %cmp, label %for.body, label %cleanup
180 cleanup:
181   %res = phi i1 [ false, %for.body ], [ true, %for.cond ]
182   ret i1 %res
185 define i1 @loads_of_less_than_byte(i7* %ptr0, i7* %ptr1) {
186 ; CHECK-LABEL: @loads_of_less_than_byte(
187 ; CHECK-NEXT:  entry:
188 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
189 ; CHECK:       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:%.*]]
198 ; CHECK:       for.cond:
199 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i64 [[INC]], 8
200 ; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[CLEANUP]]
201 ; CHECK:       cleanup:
202 ; CHECK-NEXT:    [[RES:%.*]] = phi i1 [ false, [[FOR_BODY]] ], [ true, [[FOR_COND]] ]
203 ; CHECK-NEXT:    ret i1 [[RES]]
205 entry:
206   br label %for.body
208 for.body:
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
218 for.cond:
219   %cmp = icmp ult i64 %inc, 8
220   br i1 %cmp, label %for.body, label %cleanup
222 cleanup:
223   %res = phi i1 [ false, %for.body ], [ true, %for.cond ]
224   ret i1 %res
227 define i1 @loads_of_not_multiple_of_a_byte(i9* %ptr0, i9* %ptr1) {
228 ; CHECK-LABEL: @loads_of_not_multiple_of_a_byte(
229 ; CHECK-NEXT:  entry:
230 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
231 ; CHECK:       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:%.*]]
240 ; CHECK:       for.cond:
241 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i64 [[INC]], 8
242 ; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[CLEANUP]]
243 ; CHECK:       cleanup:
244 ; CHECK-NEXT:    [[RES:%.*]] = phi i1 [ false, [[FOR_BODY]] ], [ true, [[FOR_COND]] ]
245 ; CHECK-NEXT:    ret i1 [[RES]]
247 entry:
248   br label %for.body
250 for.body:
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
260 for.cond:
261   %cmp = icmp ult i64 %inc, 8
262   br i1 %cmp, label %for.body, label %cleanup
264 cleanup:
265   %res = phi i1 [ false, %for.body ], [ true, %for.cond ]
266   ret i1 %res
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(
271 ; CHECK-NEXT:  entry:
272 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
273 ; CHECK:       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:%.*]]
282 ; CHECK:       for.cond:
283 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i64 [[INC]], 8
284 ; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[CLEANUP]]
285 ; CHECK:       cleanup:
286 ; CHECK-NEXT:    [[RES:%.*]] = phi i1 [ [[CMP3]], [[FOR_BODY]] ], [ true, [[FOR_COND]] ]
287 ; CHECK-NEXT:    ret i1 [[RES]]
289 entry:
290   br label %for.body
292 for.body:
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
302 for.cond:
303   %cmp = icmp ult i64 %inc, 8
304   br i1 %cmp, label %for.body, label %cleanup
306 cleanup:
307   %res = phi i1 [ %cmp3, %for.body ], [ true, %for.cond ]
308   ret i1 %res
311 define i1 @loop_has_write(i8* %ptr0, i8* %ptr1, i32* %write) {
312 ; CHECK-LABEL: @loop_has_write(
313 ; CHECK-NEXT:  entry:
314 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
315 ; CHECK:       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:%.*]]
324 ; CHECK:       for.cond:
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]]
328 ; CHECK:       cleanup:
329 ; CHECK-NEXT:    [[RES:%.*]] = phi i1 [ false, [[FOR_BODY]] ], [ true, [[FOR_COND]] ]
330 ; CHECK-NEXT:    ret i1 [[RES]]
332 entry:
333   br label %for.body
335 for.body:
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
345 for.cond:
346   %cmp = icmp ult i64 %inc, 8
347   store i32 0, i32* %write
348   br i1 %cmp, label %for.body, label %cleanup
350 cleanup:
351   %res = phi i1 [ false, %for.body ], [ true, %for.cond ]
352   ret i1 %res
355 declare void @sink()
356 define i1 @loop_has_call(i8* %ptr0, i8* %ptr1, i32* %load) {
357 ; CHECK-LABEL: @loop_has_call(
358 ; CHECK-NEXT:  entry:
359 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
360 ; CHECK:       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:%.*]]
369 ; CHECK:       for.cond:
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]]
373 ; CHECK:       cleanup:
374 ; CHECK-NEXT:    [[RES:%.*]] = phi i1 [ false, [[FOR_BODY]] ], [ true, [[FOR_COND]] ]
375 ; CHECK-NEXT:    ret i1 [[RES]]
377 entry:
378   br label %for.body
380 for.body:
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
390 for.cond:
391   %cmp = icmp ult i64 %inc, 8
392   tail call void @sink()
393   br i1 %cmp, label %for.body, label %cleanup
395 cleanup:
396   %res = phi i1 [ false, %for.body ], [ true, %for.cond ]
397   ret i1 %res
400 define i1 @loop_has_atomic_load(i8* %ptr0, i8* %ptr1, i32* %load) {
401 ; CHECK-LABEL: @loop_has_atomic_load(
402 ; CHECK-NEXT:  entry:
403 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
404 ; CHECK:       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:%.*]]
413 ; CHECK:       for.cond:
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]]
417 ; CHECK:       cleanup:
418 ; CHECK-NEXT:    [[RES:%.*]] = phi i1 [ false, [[FOR_BODY]] ], [ true, [[FOR_COND]] ]
419 ; CHECK-NEXT:    ret i1 [[RES]]
421 entry:
422   br label %for.body
424 for.body:
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
434 for.cond:
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
439 cleanup:
440   %res = phi i1 [ false, %for.body ], [ true, %for.cond ]
441   ret i1 %res
444 define i1 @different_load_step(i8* %ptr) {
445 ; CHECK-LABEL: @different_load_step(
446 ; CHECK-NEXT:  entry:
447 ; CHECK-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i8, i8* [[PTR:%.*]], i64 8
448 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
449 ; CHECK:       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:%.*]]
457 ; CHECK:       for.inc:
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]]
463 ; CHECK:       cleanup:
464 ; CHECK-NEXT:    [[RES:%.*]] = phi i1 [ false, [[FOR_BODY]] ], [ true, [[FOR_INC]] ]
465 ; CHECK-NEXT:    ret i1 [[RES]]
467 entry:
468   %add.ptr = getelementptr inbounds i8, i8* %ptr, i64 8
469   br label %for.body
471 for.body:
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
480 for.inc:
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
487 cleanup:
488   %res = phi i1 [ false, %for.body ], [ true, %for.inc ]
489   ret i1 %res
492 define i1 @step_is_variable(i8* %ptr, i64 %step) {
493 ; CHECK-LABEL: @step_is_variable(
494 ; CHECK-NEXT:  entry:
495 ; CHECK-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i8, i8* [[PTR:%.*]], i64 8
496 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
497 ; CHECK:       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:%.*]]
505 ; CHECK:       for.inc:
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]]
511 ; CHECK:       cleanup:
512 ; CHECK-NEXT:    [[RES:%.*]] = phi i1 [ false, [[FOR_BODY]] ], [ true, [[FOR_INC]] ]
513 ; CHECK-NEXT:    ret i1 [[RES]]
515 entry:
516   %add.ptr = getelementptr inbounds i8, i8* %ptr, i64 8
517   br label %for.body
519 for.body:
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
528 for.inc:
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
535 cleanup:
536   %res = phi i1 [ false, %for.body ], [ true, %for.inc ]
537   ret i1 %res
540 define i1 @load_step_is_variable(i8* %ptr, i64 %step) {
541 ; CHECK-LABEL: @load_step_is_variable(
542 ; CHECK-NEXT:  entry:
543 ; CHECK-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i8, i8* [[PTR:%.*]], i64 8
544 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
545 ; CHECK:       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:%.*]]
553 ; CHECK:       for.inc:
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]]
559 ; CHECK:       cleanup:
560 ; CHECK-NEXT:    [[RES:%.*]] = phi i1 [ false, [[FOR_BODY]] ], [ true, [[FOR_INC]] ]
561 ; CHECK-NEXT:    ret i1 [[RES]]
563 entry:
564   %add.ptr = getelementptr inbounds i8, i8* %ptr, i64 8
565   br label %for.body
567 for.body:
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
576 for.inc:
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
583 cleanup:
584   %res = phi i1 [ false, %for.body ], [ true, %for.inc ]
585   ret i1 %res
588 define i1 @step_and_load_step_is_variable(i8* %ptr, i64 %step) {
589 ; CHECK-LABEL: @step_and_load_step_is_variable(
590 ; CHECK-NEXT:  entry:
591 ; CHECK-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i8, i8* [[PTR:%.*]], i64 8
592 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
593 ; CHECK:       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:%.*]]
601 ; CHECK:       for.inc:
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]]
607 ; CHECK:       cleanup:
608 ; CHECK-NEXT:    [[RES:%.*]] = phi i1 [ false, [[FOR_BODY]] ], [ true, [[FOR_INC]] ]
609 ; CHECK-NEXT:    ret i1 [[RES]]
611 entry:
612   %add.ptr = getelementptr inbounds i8, i8* %ptr, i64 8
613   br label %for.body
615 for.body:
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
624 for.inc:
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
631 cleanup:
632   %res = phi i1 [ false, %for.body ], [ true, %for.inc ]
633   ret i1 %res
636 define i1 @load_step_not_affine(i8* %ptr) {
637 ; CHECK-LABEL: @load_step_not_affine(
638 ; CHECK-NEXT:  entry:
639 ; CHECK-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i8, i8* [[PTR:%.*]], i64 8
640 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
641 ; CHECK:       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:%.*]]
649 ; CHECK:       for.inc:
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]]
655 ; CHECK:       cleanup:
656 ; CHECK-NEXT:    [[RES:%.*]] = phi i1 [ false, [[FOR_BODY]] ], [ true, [[FOR_INC]] ]
657 ; CHECK-NEXT:    ret i1 [[RES]]
659 entry:
660   %add.ptr = getelementptr inbounds i8, i8* %ptr, i64 8
661   br label %for.body
663 for.body:
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
672 for.inc:
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
679 cleanup:
680   %res = phi i1 [ false, %for.body ], [ true, %for.inc ]
681   ret i1 %res
684 define i1 @no_overlap_between_loads(i8* %ptr) {
685 ; CHECK-LABEL: @no_overlap_between_loads(
686 ; CHECK-NEXT:  entry:
687 ; CHECK-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i8, i8* [[PTR:%.*]], i64 8
688 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
689 ; CHECK:       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:%.*]]
697 ; CHECK:       for.inc:
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]]
703 ; CHECK:       cleanup:
704 ; CHECK-NEXT:    [[RES:%.*]] = phi i1 [ false, [[FOR_BODY]] ], [ true, [[FOR_INC]] ]
705 ; CHECK-NEXT:    ret i1 [[RES]]
707 entry:
708   %add.ptr = getelementptr inbounds i8, i8* %ptr, i64 8
709   br label %for.body
711 for.body:
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
720 for.inc:
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
727 cleanup:
728   %res = phi i1 [ false, %for.body ], [ true, %for.inc ]
729   ret i1 %res
732 define i1 @volatile_loads(i8* %ptr) {
733 ; CHECK-LABEL: @volatile_loads(
734 ; CHECK-NEXT:  entry:
735 ; CHECK-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i8, i8* [[PTR:%.*]], i64 8
736 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
737 ; CHECK:       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:%.*]]
745 ; CHECK:       for.inc:
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]]
751 ; CHECK:       cleanup:
752 ; CHECK-NEXT:    [[RES:%.*]] = phi i1 [ false, [[FOR_BODY]] ], [ true, [[FOR_INC]] ]
753 ; CHECK-NEXT:    ret i1 [[RES]]
755 entry:
756   %add.ptr = getelementptr inbounds i8, i8* %ptr, i64 8
757   br label %for.body
759 for.body:
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
768 for.inc:
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
775 cleanup:
776   %res = phi i1 [ false, %for.body ], [ true, %for.inc ]
777   ret i1 %res
780 define i1 @atomic_loads(i8* %ptr) {
781 ; CHECK-LABEL: @atomic_loads(
782 ; CHECK-NEXT:  entry:
783 ; CHECK-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i8, i8* [[PTR:%.*]], i64 8
784 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
785 ; CHECK:       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:%.*]]
793 ; CHECK:       for.inc:
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]]
799 ; CHECK:       cleanup:
800 ; CHECK-NEXT:    [[RES:%.*]] = phi i1 [ false, [[FOR_BODY]] ], [ true, [[FOR_INC]] ]
801 ; CHECK-NEXT:    ret i1 [[RES]]
803 entry:
804   %add.ptr = getelementptr inbounds i8, i8* %ptr, i64 8
805   br label %for.body
807 for.body:
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
816 for.inc:
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
823 cleanup:
824   %res = phi i1 [ false, %for.body ], [ true, %for.inc ]
825   ret i1 %res
828 define i1 @address_space(i8 addrspace(1)* %ptr) {
829 ; CHECK-LABEL: @address_space(
830 ; CHECK-NEXT:  entry:
831 ; CHECK-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i8, i8 addrspace(1)* [[PTR:%.*]], i64 8
832 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
833 ; CHECK:       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:%.*]]
841 ; CHECK:       for.inc:
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]]
847 ; CHECK:       cleanup:
848 ; CHECK-NEXT:    [[RES:%.*]] = phi i1 [ false, [[FOR_BODY]] ], [ true, [[FOR_INC]] ]
849 ; CHECK-NEXT:    ret i1 [[RES]]
851 entry:
852   %add.ptr = getelementptr inbounds i8, i8 addrspace(1)* %ptr, i64 8
853   br label %for.body
855 for.body:
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
864 for.inc:
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
871 cleanup:
872   %res = phi i1 [ false, %for.body ], [ true, %for.inc ]
873   ret i1 %res
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])
882 ;           return 1;
883 ;   return 0;
884 ; }
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(
889 ; CHECK-NEXT:  entry:
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]]
923 ; CHECK:       cleanup12:
924 ; CHECK-NEXT:    [[V3:%.*]] = phi i1 [ false, [[ENTRY:%.*]] ], [ true, [[CLEANUP12_LOOPEXIT]] ], [ false, [[CLEANUP12_LOOPEXIT1]] ]
925 ; CHECK-NEXT:    ret i1 [[V3]]
927 entry:
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 ]
965   ret i1 %v3
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(
971 ; CHECK-NEXT:  entry:
972 ; CHECK-NEXT:    br label [[BODY:%.*]]
973 ; CHECK:       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]]
978 ; CHECK:       latch:
979 ; CHECK-NEXT:    [[SHOULD_CONTINUE:%.*]] = icmp slt i32 undef, 79
980 ; CHECK-NEXT:    br i1 [[SHOULD_CONTINUE]], label [[BODY]], label [[END:%.*]]
981 ; CHECK:       end:
982 ; CHECK-NEXT:    ret void
984 entry:
985   br label %body
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
998   ret void