xref: /llvm-project/llvm/test/Transforms/InstCombine/dependent-ivs.ll (revision 462cb3cd6cecd0511ecaf0e3ebcaba455ece587d)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
2; RUN: opt -S -passes=instcombine < %s | FileCheck %s
3
4define void @int_iv_nuw(i64 %base, i64 %end) {
5; CHECK-LABEL: define void @int_iv_nuw(
6; CHECK-SAME: i64 [[BASE:%.*]], i64 [[END:%.*]]) {
7; CHECK-NEXT:  entry:
8; CHECK-NEXT:    br label [[LOOP:%.*]]
9; CHECK:       loop:
10; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ]
11; CHECK-NEXT:    [[IV2:%.*]] = add nuw i64 [[IV]], [[BASE]]
12; CHECK-NEXT:    call void @use.i64(i64 [[IV2]])
13; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 4
14; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[IV_NEXT]], [[END]]
15; CHECK-NEXT:    br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]]
16; CHECK:       exit:
17; CHECK-NEXT:    ret void
18;
19entry:
20  br label %loop
21
22loop:
23  %iv2 = phi i64 [ %iv2.next, %loop ], [ %base, %entry ]
24  %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ]
25  call void @use.i64(i64 %iv2)
26  %iv.next = add nuw nsw i64 %iv, 4
27  %iv2.next = add nuw i64 %iv.next, %base
28  %cmp = icmp eq i64 %iv.next, %end
29  br i1 %cmp, label %exit, label %loop
30
31exit:
32  ret void
33}
34
35define void @int_iv_nsw(i64 %base, i64 %end) {
36; CHECK-LABEL: define void @int_iv_nsw(
37; CHECK-SAME: i64 [[BASE:%.*]], i64 [[END:%.*]]) {
38; CHECK-NEXT:  entry:
39; CHECK-NEXT:    br label [[LOOP:%.*]]
40; CHECK:       loop:
41; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ]
42; CHECK-NEXT:    [[IV2:%.*]] = add nsw i64 [[IV]], [[BASE]]
43; CHECK-NEXT:    call void @use.i64(i64 [[IV2]])
44; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 4
45; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[IV_NEXT]], [[END]]
46; CHECK-NEXT:    br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]]
47; CHECK:       exit:
48; CHECK-NEXT:    ret void
49;
50entry:
51  br label %loop
52
53loop:
54  %iv2 = phi i64 [ %iv2.next, %loop ], [ %base, %entry ]
55  %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ]
56  call void @use.i64(i64 %iv2)
57  %iv.next = add nuw nsw i64 %iv, 4
58  %iv2.next = add nsw i64 %iv.next, %base
59  %cmp = icmp eq i64 %iv.next, %end
60  br i1 %cmp, label %exit, label %loop
61
62exit:
63  ret void
64}
65
66define void @int_iv_commuted_add(i64 %base, i64 %end) {
67; CHECK-LABEL: define void @int_iv_commuted_add(
68; CHECK-SAME: i64 [[BASE:%.*]], i64 [[END:%.*]]) {
69; CHECK-NEXT:  entry:
70; CHECK-NEXT:    [[BASE2:%.*]] = mul i64 [[BASE]], 42
71; CHECK-NEXT:    br label [[LOOP:%.*]]
72; CHECK:       loop:
73; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ]
74; CHECK-NEXT:    [[IV2:%.*]] = add i64 [[IV]], [[BASE2]]
75; CHECK-NEXT:    call void @use.i64(i64 [[IV2]])
76; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 4
77; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[IV_NEXT]], [[END]]
78; CHECK-NEXT:    br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]]
79; CHECK:       exit:
80; CHECK-NEXT:    ret void
81;
82entry:
83  %base2 = mul i64 %base, 42 ; thwart complexity-based canonicalization
84  br label %loop
85
86loop:
87  %iv2 = phi i64 [ %iv2.next, %loop ], [ %base2, %entry ]
88  %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ]
89  call void @use.i64(i64 %iv2)
90  %iv.next = add nuw nsw i64 %iv, 4
91  %iv2.next = add i64 %base2, %iv.next
92  %cmp = icmp eq i64 %iv.next, %end
93  br i1 %cmp, label %exit, label %loop
94
95exit:
96  ret void
97}
98
99define void @int_iv_commuted_phi1(i64 %base, i64 %end) {
100; CHECK-LABEL: define void @int_iv_commuted_phi1(
101; CHECK-SAME: i64 [[BASE:%.*]], i64 [[END:%.*]]) {
102; CHECK-NEXT:  entry:
103; CHECK-NEXT:    br label [[LOOP:%.*]]
104; CHECK:       loop:
105; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
106; CHECK-NEXT:    [[IV2:%.*]] = add i64 [[IV]], [[BASE]]
107; CHECK-NEXT:    call void @use.i64(i64 [[IV2]])
108; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 4
109; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[IV_NEXT]], [[END]]
110; CHECK-NEXT:    br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]]
111; CHECK:       exit:
112; CHECK-NEXT:    ret void
113;
114entry:
115  br label %loop
116
117loop:
118  %iv2 = phi i64 [ %base, %entry ], [ %iv2.next, %loop ]
119  %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ]
120  call void @use.i64(i64 %iv2)
121  %iv.next = add nuw nsw i64 %iv, 4
122  %iv2.next = add i64 %iv.next, %base
123  %cmp = icmp eq i64 %iv.next, %end
124  br i1 %cmp, label %exit, label %loop
125
126exit:
127  ret void
128}
129
130define void @int_iv_commuted_phi2(i64 %base, i64 %end) {
131; CHECK-LABEL: define void @int_iv_commuted_phi2(
132; CHECK-SAME: i64 [[BASE:%.*]], i64 [[END:%.*]]) {
133; CHECK-NEXT:  entry:
134; CHECK-NEXT:    br label [[LOOP:%.*]]
135; CHECK:       loop:
136; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ]
137; CHECK-NEXT:    [[IV2:%.*]] = add i64 [[IV]], [[BASE]]
138; CHECK-NEXT:    call void @use.i64(i64 [[IV2]])
139; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 4
140; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[IV_NEXT]], [[END]]
141; CHECK-NEXT:    br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]]
142; CHECK:       exit:
143; CHECK-NEXT:    ret void
144;
145entry:
146  br label %loop
147
148loop:
149  %iv2 = phi i64 [ %iv2.next, %loop ], [ %base, %entry ]
150  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
151  call void @use.i64(i64 %iv2)
152  %iv.next = add nuw nsw i64 %iv, 4
153  %iv2.next = add i64 %iv.next, %base
154  %cmp = icmp eq i64 %iv.next, %end
155  br i1 %cmp, label %exit, label %loop
156
157exit:
158  ret void
159}
160
161define void @int_iv_vector(<2 x i64> %base) {
162; CHECK-LABEL: define void @int_iv_vector(
163; CHECK-SAME: <2 x i64> [[BASE:%.*]]) {
164; CHECK-NEXT:  entry:
165; CHECK-NEXT:    br label [[LOOP:%.*]]
166; CHECK:       loop:
167; CHECK-NEXT:    [[IV:%.*]] = phi <2 x i64> [ [[IV_NEXT:%.*]], [[LOOP]] ], [ zeroinitializer, [[ENTRY:%.*]] ]
168; CHECK-NEXT:    [[IV2:%.*]] = add <2 x i64> [[IV]], [[BASE]]
169; CHECK-NEXT:    call void @use.v2i64(<2 x i64> [[IV2]])
170; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw <2 x i64> [[IV]], splat (i64 4)
171; CHECK-NEXT:    [[CMP:%.*]] = call i1 @get.i1()
172; CHECK-NEXT:    br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]]
173; CHECK:       exit:
174; CHECK-NEXT:    ret void
175;
176entry:
177  br label %loop
178
179loop:
180  %iv2 = phi <2 x i64> [ %iv2.next, %loop ], [ %base, %entry ]
181  %iv = phi <2 x i64> [ %iv.next, %loop ], [ zeroinitializer, %entry ]
182  call void @use.v2i64(<2 x i64> %iv2)
183  %iv.next = add nuw nsw <2 x i64> %iv, <i64 4, i64 4>
184  %iv2.next = add <2 x i64> %iv.next, %base
185  %cmp = call i1 @get.i1()
186  br i1 %cmp, label %exit, label %loop
187
188exit:
189  ret void
190}
191
192define void @int_iv_vector_poison_invalid(<2 x i64> %base) {
193; CHECK-LABEL: define void @int_iv_vector_poison_invalid(
194; CHECK-SAME: <2 x i64> [[BASE:%.*]]) {
195; CHECK-NEXT:  entry:
196; CHECK-NEXT:    br label [[LOOP:%.*]]
197; CHECK:       loop:
198; CHECK-NEXT:    [[IV2:%.*]] = phi <2 x i64> [ [[IV2_NEXT:%.*]], [[LOOP]] ], [ [[BASE]], [[ENTRY:%.*]] ]
199; CHECK-NEXT:    [[IV:%.*]] = phi <2 x i64> [ [[IV_NEXT:%.*]], [[LOOP]] ], [ <i64 0, i64 poison>, [[ENTRY]] ]
200; CHECK-NEXT:    call void @use.v2i64(<2 x i64> [[IV2]])
201; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw <2 x i64> [[IV]], splat (i64 4)
202; CHECK-NEXT:    [[IV2_NEXT]] = add <2 x i64> [[IV_NEXT]], [[BASE]]
203; CHECK-NEXT:    [[CMP:%.*]] = call i1 @get.i1()
204; CHECK-NEXT:    br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]]
205; CHECK:       exit:
206; CHECK-NEXT:    ret void
207;
208entry:
209  br label %loop
210
211loop:
212  %iv2 = phi <2 x i64> [ %iv2.next, %loop ], [ %base, %entry ]
213  %iv = phi <2 x i64> [ %iv.next, %loop ], [ <i64 0, i64 poison>, %entry ]
214  call void @use.v2i64(<2 x i64> %iv2)
215  %iv.next = add nuw nsw <2 x i64> %iv, <i64 4, i64 4>
216  %iv2.next = add <2 x i64> %iv.next, %base
217  %cmp = call i1 @get.i1()
218  br i1 %cmp, label %exit, label %loop
219
220exit:
221  ret void
222}
223
224define void @int_iv_loop_variant_step(i64 %base, i64 %end) {
225; CHECK-LABEL: define void @int_iv_loop_variant_step(
226; CHECK-SAME: i64 [[BASE:%.*]], i64 [[END:%.*]]) {
227; CHECK-NEXT:  entry:
228; CHECK-NEXT:    br label [[LOOP:%.*]]
229; CHECK:       loop:
230; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ]
231; CHECK-NEXT:    [[IV2:%.*]] = add nuw i64 [[IV]], [[BASE]]
232; CHECK-NEXT:    call void @use.i64(i64 [[IV2]])
233; CHECK-NEXT:    [[STEP:%.*]] = call i64 @get.i64()
234; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], [[STEP]]
235; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[IV_NEXT]], [[END]]
236; CHECK-NEXT:    br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]]
237; CHECK:       exit:
238; CHECK-NEXT:    ret void
239;
240entry:
241  br label %loop
242
243loop:
244  %iv2 = phi i64 [ %iv2.next, %loop ], [ %base, %entry ]
245  %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ]
246  call void @use.i64(i64 %iv2)
247  %step = call i64 @get.i64()
248  %iv.next = add nuw nsw i64 %iv, %step
249  %iv2.next = add nuw i64 %iv.next, %base
250  %cmp = icmp eq i64 %iv.next, %end
251  br i1 %cmp, label %exit, label %loop
252
253exit:
254  ret void
255}
256
257define void @int_iv_xor(i64 %base, i64 %end) {
258; CHECK-LABEL: define void @int_iv_xor(
259; CHECK-SAME: i64 [[BASE:%.*]], i64 [[END:%.*]]) {
260; CHECK-NEXT:  entry:
261; CHECK-NEXT:    br label [[LOOP:%.*]]
262; CHECK:       loop:
263; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ]
264; CHECK-NEXT:    [[IV2:%.*]] = xor i64 [[IV]], [[BASE]]
265; CHECK-NEXT:    call void @use.i64(i64 [[IV2]])
266; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 4
267; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[IV_NEXT]], [[END]]
268; CHECK-NEXT:    br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]]
269; CHECK:       exit:
270; CHECK-NEXT:    ret void
271;
272entry:
273  br label %loop
274
275loop:
276  %iv2 = phi i64 [ %iv2.next, %loop ], [ %base, %entry ]
277  %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ]
278  call void @use.i64(i64 %iv2)
279  %iv.next = add nuw nsw i64 %iv, 4
280  %iv2.next = xor i64 %iv.next, %base
281  %cmp = icmp eq i64 %iv.next, %end
282  br i1 %cmp, label %exit, label %loop
283
284exit:
285  ret void
286}
287
288define void @int_iv_or(i64 %base, i64 %end) {
289; CHECK-LABEL: define void @int_iv_or(
290; CHECK-SAME: i64 [[BASE:%.*]], i64 [[END:%.*]]) {
291; CHECK-NEXT:  entry:
292; CHECK-NEXT:    br label [[LOOP:%.*]]
293; CHECK:       loop:
294; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ]
295; CHECK-NEXT:    [[IV2:%.*]] = or i64 [[IV]], [[BASE]]
296; CHECK-NEXT:    call void @use.i64(i64 [[IV2]])
297; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 4
298; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[IV_NEXT]], [[END]]
299; CHECK-NEXT:    br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]]
300; CHECK:       exit:
301; CHECK-NEXT:    ret void
302;
303entry:
304  br label %loop
305
306loop:
307  %iv2 = phi i64 [ %iv2.next, %loop ], [ %base, %entry ]
308  %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ]
309  call void @use.i64(i64 %iv2)
310  %iv.next = add nuw nsw i64 %iv, 4
311  %iv2.next = or i64 %iv.next, %base
312  %cmp = icmp eq i64 %iv.next, %end
313  br i1 %cmp, label %exit, label %loop
314
315exit:
316  ret void
317}
318
319define void @int_iv_or_disjoint(i64 %base, i64 %end) {
320; CHECK-LABEL: define void @int_iv_or_disjoint(
321; CHECK-SAME: i64 [[BASE:%.*]], i64 [[END:%.*]]) {
322; CHECK-NEXT:  entry:
323; CHECK-NEXT:    br label [[LOOP:%.*]]
324; CHECK:       loop:
325; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ]
326; CHECK-NEXT:    [[IV2:%.*]] = or disjoint i64 [[IV]], [[BASE]]
327; CHECK-NEXT:    call void @use.i64(i64 [[IV2]])
328; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 4
329; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[IV_NEXT]], [[END]]
330; CHECK-NEXT:    br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]]
331; CHECK:       exit:
332; CHECK-NEXT:    ret void
333;
334entry:
335  br label %loop
336
337loop:
338  %iv2 = phi i64 [ %iv2.next, %loop ], [ %base, %entry ]
339  %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ]
340  call void @use.i64(i64 %iv2)
341  %iv.next = add nuw nsw i64 %iv, 4
342  %iv2.next = or disjoint i64 %iv.next, %base
343  %cmp = icmp eq i64 %iv.next, %end
344  br i1 %cmp, label %exit, label %loop
345
346exit:
347  ret void
348}
349
350define void @int_iv_and(i64 %base, i64 %end) {
351; CHECK-LABEL: define void @int_iv_and(
352; CHECK-SAME: i64 [[BASE:%.*]], i64 [[END:%.*]]) {
353; CHECK-NEXT:  entry:
354; CHECK-NEXT:    br label [[LOOP:%.*]]
355; CHECK:       loop:
356; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP]] ], [ -1, [[ENTRY:%.*]] ]
357; CHECK-NEXT:    [[IV2:%.*]] = and i64 [[IV]], [[BASE]]
358; CHECK-NEXT:    call void @use.i64(i64 [[IV2]])
359; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 4
360; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[IV_NEXT]], [[END]]
361; CHECK-NEXT:    br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]]
362; CHECK:       exit:
363; CHECK-NEXT:    ret void
364;
365entry:
366  br label %loop
367
368loop:
369  %iv2 = phi i64 [ %iv2.next, %loop ], [ %base, %entry ]
370  %iv = phi i64 [ %iv.next, %loop ], [ -1, %entry ]
371  call void @use.i64(i64 %iv2)
372  %iv.next = add nuw nsw i64 %iv, 4
373  %iv2.next = and i64 %iv.next, %base
374  %cmp = icmp eq i64 %iv.next, %end
375  br i1 %cmp, label %exit, label %loop
376
377exit:
378  ret void
379}
380
381define void @int_iv_sub(i64 %base, i64 %end) {
382; CHECK-LABEL: define void @int_iv_sub(
383; CHECK-SAME: i64 [[BASE:%.*]], i64 [[END:%.*]]) {
384; CHECK-NEXT:  entry:
385; CHECK-NEXT:    br label [[LOOP:%.*]]
386; CHECK:       loop:
387; CHECK-NEXT:    [[IV2:%.*]] = phi i64 [ [[IV2_NEXT:%.*]], [[LOOP]] ], [ [[BASE]], [[ENTRY:%.*]] ]
388; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY]] ]
389; CHECK-NEXT:    call void @use.i64(i64 [[IV2]])
390; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 4
391; CHECK-NEXT:    [[IV2_NEXT]] = sub i64 [[BASE]], [[IV_NEXT]]
392; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[IV_NEXT]], [[END]]
393; CHECK-NEXT:    br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]]
394; CHECK:       exit:
395; CHECK-NEXT:    ret void
396;
397entry:
398  br label %loop
399
400loop:
401  %iv2 = phi i64 [ %iv2.next, %loop ], [ %base, %entry ]
402  %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ]
403  call void @use.i64(i64 %iv2)
404  %iv.next = add nuw nsw i64 %iv, 4
405  %iv2.next = sub i64 %base, %iv.next
406  %cmp = icmp eq i64 %iv.next, %end
407  br i1 %cmp, label %exit, label %loop
408
409exit:
410  ret void
411}
412
413define void @int_iv_sub_invalid_order(i64 %base, i64 %end) {
414; CHECK-LABEL: define void @int_iv_sub_invalid_order(
415; CHECK-SAME: i64 [[BASE:%.*]], i64 [[END:%.*]]) {
416; CHECK-NEXT:  entry:
417; CHECK-NEXT:    br label [[LOOP:%.*]]
418; CHECK:       loop:
419; CHECK-NEXT:    [[IV2:%.*]] = phi i64 [ [[IV2_NEXT:%.*]], [[LOOP]] ], [ [[BASE]], [[ENTRY:%.*]] ]
420; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY]] ]
421; CHECK-NEXT:    call void @use.i64(i64 [[IV2]])
422; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 4
423; CHECK-NEXT:    [[IV2_NEXT]] = sub i64 [[IV_NEXT]], [[BASE]]
424; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[IV_NEXT]], [[END]]
425; CHECK-NEXT:    br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]]
426; CHECK:       exit:
427; CHECK-NEXT:    ret void
428;
429entry:
430  br label %loop
431
432loop:
433  %iv2 = phi i64 [ %iv2.next, %loop ], [ %base, %entry ]
434  %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ]
435  call void @use.i64(i64 %iv2)
436  %iv.next = add nuw nsw i64 %iv, 4
437  %iv2.next = sub i64 %iv.next, %base
438  %cmp = icmp eq i64 %iv.next, %end
439  br i1 %cmp, label %exit, label %loop
440
441exit:
442  ret void
443}
444
445define void @int_iv_add_wrong_start(i64 %base, i64 %end) {
446; CHECK-LABEL: define void @int_iv_add_wrong_start(
447; CHECK-SAME: i64 [[BASE:%.*]], i64 [[END:%.*]]) {
448; CHECK-NEXT:  entry:
449; CHECK-NEXT:    br label [[LOOP:%.*]]
450; CHECK:       loop:
451; CHECK-NEXT:    [[IV2:%.*]] = phi i64 [ [[IV2_NEXT:%.*]], [[LOOP]] ], [ [[BASE]], [[ENTRY:%.*]] ]
452; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP]] ], [ 1, [[ENTRY]] ]
453; CHECK-NEXT:    call void @use.i64(i64 [[IV2]])
454; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 4
455; CHECK-NEXT:    [[IV2_NEXT]] = add i64 [[BASE]], [[IV_NEXT]]
456; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[IV_NEXT]], [[END]]
457; CHECK-NEXT:    br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]]
458; CHECK:       exit:
459; CHECK-NEXT:    ret void
460;
461entry:
462  br label %loop
463
464loop:
465  %iv2 = phi i64 [ %iv2.next, %loop ], [ %base, %entry ]
466  %iv = phi i64 [ %iv.next, %loop ], [ 1, %entry ]
467  call void @use.i64(i64 %iv2)
468  %iv.next = add nuw nsw i64 %iv, 4
469  %iv2.next = add i64 %base, %iv.next
470  %cmp = icmp eq i64 %iv.next, %end
471  br i1 %cmp, label %exit, label %loop
472
473exit:
474  ret void
475}
476
477define void @int_iv_and_wrong_start(i64 %base, i64 %end) {
478; CHECK-LABEL: define void @int_iv_and_wrong_start(
479; CHECK-SAME: i64 [[BASE:%.*]], i64 [[END:%.*]]) {
480; CHECK-NEXT:  entry:
481; CHECK-NEXT:    br label [[LOOP:%.*]]
482; CHECK:       loop:
483; CHECK-NEXT:    [[IV2:%.*]] = phi i64 [ [[IV2_NEXT:%.*]], [[LOOP]] ], [ [[BASE]], [[ENTRY:%.*]] ]
484; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY]] ]
485; CHECK-NEXT:    call void @use.i64(i64 [[IV2]])
486; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 4
487; CHECK-NEXT:    [[IV2_NEXT]] = and i64 [[IV_NEXT]], [[BASE]]
488; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[IV_NEXT]], [[END]]
489; CHECK-NEXT:    br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]]
490; CHECK:       exit:
491; CHECK-NEXT:    ret void
492;
493entry:
494  br label %loop
495
496loop:
497  %iv2 = phi i64 [ %iv2.next, %loop ], [ %base, %entry ]
498  %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ]
499  call void @use.i64(i64 %iv2)
500  %iv.next = add nuw nsw i64 %iv, 4
501  %iv2.next = and i64 %iv.next, %base
502  %cmp = icmp eq i64 %iv.next, %end
503  br i1 %cmp, label %exit, label %loop
504
505exit:
506  ret void
507}
508
509define void @ptr_iv_inbounds(ptr %base, i64 %end) {
510; CHECK-LABEL: define void @ptr_iv_inbounds(
511; CHECK-SAME: ptr [[BASE:%.*]], i64 [[END:%.*]]) {
512; CHECK-NEXT:  entry:
513; CHECK-NEXT:    br label [[LOOP:%.*]]
514; CHECK:       loop:
515; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ]
516; CHECK-NEXT:    [[IV_PTR:%.*]] = getelementptr inbounds nuw i8, ptr [[BASE]], i64 [[IV]]
517; CHECK-NEXT:    call void @use.p0(ptr [[IV_PTR]])
518; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 4
519; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[IV_NEXT]], [[END]]
520; CHECK-NEXT:    br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]]
521; CHECK:       exit:
522; CHECK-NEXT:    ret void
523;
524entry:
525  br label %loop
526
527loop:
528  %iv.ptr = phi ptr [ %iv.ptr.next, %loop ], [ %base, %entry ]
529  %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ]
530  call void @use.p0(ptr %iv.ptr)
531  %iv.next = add nuw nsw i64 %iv, 4
532  %iv.ptr.next = getelementptr inbounds i8, ptr %base, i64 %iv.next
533  %cmp = icmp eq i64 %iv.next, %end
534  br i1 %cmp, label %exit, label %loop
535
536exit:
537  ret void
538}
539
540define void @ptr_iv_nuw(ptr %base, i64 %end) {
541; CHECK-LABEL: define void @ptr_iv_nuw(
542; CHECK-SAME: ptr [[BASE:%.*]], i64 [[END:%.*]]) {
543; CHECK-NEXT:  entry:
544; CHECK-NEXT:    br label [[LOOP:%.*]]
545; CHECK:       loop:
546; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ]
547; CHECK-NEXT:    [[IV_PTR:%.*]] = getelementptr nuw i8, ptr [[BASE]], i64 [[IV]]
548; CHECK-NEXT:    call void @use.p0(ptr [[IV_PTR]])
549; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 4
550; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[IV_NEXT]], [[END]]
551; CHECK-NEXT:    br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]]
552; CHECK:       exit:
553; CHECK-NEXT:    ret void
554;
555entry:
556  br label %loop
557
558loop:
559  %iv.ptr = phi ptr [ %iv.ptr.next, %loop ], [ %base, %entry ]
560  %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ]
561  call void @use.p0(ptr %iv.ptr)
562  %iv.next = add nuw nsw i64 %iv, 4
563  %iv.ptr.next = getelementptr nuw i8, ptr %base, i64 %iv.next
564  %cmp = icmp eq i64 %iv.next, %end
565  br i1 %cmp, label %exit, label %loop
566
567exit:
568  ret void
569}
570
571define void @ptr_iv_no_flags(ptr %base, i64 %end) {
572; CHECK-LABEL: define void @ptr_iv_no_flags(
573; CHECK-SAME: ptr [[BASE:%.*]], i64 [[END:%.*]]) {
574; CHECK-NEXT:  entry:
575; CHECK-NEXT:    br label [[LOOP:%.*]]
576; CHECK:       loop:
577; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ]
578; CHECK-NEXT:    [[IV_PTR:%.*]] = getelementptr i8, ptr [[BASE]], i64 [[IV]]
579; CHECK-NEXT:    call void @use.p0(ptr [[IV_PTR]])
580; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 4
581; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[IV_NEXT]], [[END]]
582; CHECK-NEXT:    br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]]
583; CHECK:       exit:
584; CHECK-NEXT:    ret void
585;
586entry:
587  br label %loop
588
589loop:
590  %iv.ptr = phi ptr [ %iv.ptr.next, %loop ], [ %base, %entry ]
591  %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ]
592  call void @use.p0(ptr %iv.ptr)
593  %iv.next = add nuw nsw i64 %iv, 4
594  %iv.ptr.next = getelementptr i8, ptr %base, i64 %iv.next
595  %cmp = icmp eq i64 %iv.next, %end
596  br i1 %cmp, label %exit, label %loop
597
598exit:
599  ret void
600}
601
602define void @ptr_iv_non_i8_type(ptr %base, i64 %end) {
603; CHECK-LABEL: define void @ptr_iv_non_i8_type(
604; CHECK-SAME: ptr [[BASE:%.*]], i64 [[END:%.*]]) {
605; CHECK-NEXT:  entry:
606; CHECK-NEXT:    br label [[LOOP:%.*]]
607; CHECK:       loop:
608; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ]
609; CHECK-NEXT:    [[IV_PTR:%.*]] = getelementptr i32, ptr [[BASE]], i64 [[IV]]
610; CHECK-NEXT:    call void @use.p0(ptr [[IV_PTR]])
611; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 4
612; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[IV_NEXT]], [[END]]
613; CHECK-NEXT:    br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]]
614; CHECK:       exit:
615; CHECK-NEXT:    ret void
616;
617entry:
618  br label %loop
619
620loop:
621  %iv.ptr = phi ptr [ %iv.ptr.next, %loop ], [ %base, %entry ]
622  %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ]
623  call void @use.p0(ptr %iv.ptr)
624  %iv.next = add nuw nsw i64 %iv, 4
625  %iv.ptr.next = getelementptr i32, ptr %base, i64 %iv.next
626  %cmp = icmp eq i64 %iv.next, %end
627  br i1 %cmp, label %exit, label %loop
628
629exit:
630  ret void
631}
632
633define void @ptr_iv_vector(<2 x ptr> %base, i64 %end) {
634; CHECK-LABEL: define void @ptr_iv_vector(
635; CHECK-SAME: <2 x ptr> [[BASE:%.*]], i64 [[END:%.*]]) {
636; CHECK-NEXT:  entry:
637; CHECK-NEXT:    br label [[LOOP:%.*]]
638; CHECK:       loop:
639; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ]
640; CHECK-NEXT:    [[IV_PTR:%.*]] = getelementptr inbounds i8, <2 x ptr> [[BASE]], i64 [[IV]]
641; CHECK-NEXT:    call void @use.v2p0(<2 x ptr> [[IV_PTR]])
642; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 4
643; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[IV_NEXT]], [[END]]
644; CHECK-NEXT:    br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]]
645; CHECK:       exit:
646; CHECK-NEXT:    ret void
647;
648entry:
649  br label %loop
650
651loop:
652  %iv.ptr = phi <2 x ptr> [ %iv.ptr.next, %loop ], [ %base, %entry ]
653  %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ]
654  call void @use.v2p0(<2 x ptr> %iv.ptr)
655  %iv.next = add nuw nsw i64 %iv, 4
656  %iv.ptr.next = getelementptr inbounds i8, <2 x ptr> %base, i64 %iv.next
657  %cmp = icmp eq i64 %iv.next, %end
658  br i1 %cmp, label %exit, label %loop
659
660exit:
661  ret void
662}
663
664define void @ptr_iv_vector2(<2 x ptr> %base) {
665; CHECK-LABEL: define void @ptr_iv_vector2(
666; CHECK-SAME: <2 x ptr> [[BASE:%.*]]) {
667; CHECK-NEXT:  entry:
668; CHECK-NEXT:    br label [[LOOP:%.*]]
669; CHECK:       loop:
670; CHECK-NEXT:    [[IV:%.*]] = phi <2 x i64> [ [[IV_NEXT:%.*]], [[LOOP]] ], [ zeroinitializer, [[ENTRY:%.*]] ]
671; CHECK-NEXT:    [[IV_PTR:%.*]] = getelementptr i8, <2 x ptr> [[BASE]], <2 x i64> [[IV]]
672; CHECK-NEXT:    call void @use.v2p0(<2 x ptr> [[IV_PTR]])
673; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw <2 x i64> [[IV]], splat (i64 4)
674; CHECK-NEXT:    [[CMP:%.*]] = call i1 @get.i1()
675; CHECK-NEXT:    br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]]
676; CHECK:       exit:
677; CHECK-NEXT:    ret void
678;
679entry:
680  br label %loop
681
682loop:
683  %iv.ptr = phi <2 x ptr> [ %iv.ptr.next, %loop ], [ %base, %entry ]
684  %iv = phi <2 x i64> [ %iv.next, %loop ], [ zeroinitializer, %entry ]
685  call void @use.v2p0(<2 x ptr> %iv.ptr)
686  %iv.next = add nuw nsw <2 x i64> %iv, <i64 4, i64 4>
687  %iv.ptr.next = getelementptr i8, <2 x ptr> %base, <2 x i64> %iv.next
688  %cmp = call i1 @get.i1()
689  br i1 %cmp, label %exit, label %loop
690
691exit:
692  ret void
693}
694
695define void @different_loops(i64 %base) {
696; CHECK-LABEL: define void @different_loops(
697; CHECK-SAME: i64 [[BASE:%.*]]) {
698; CHECK-NEXT:  entry:
699; CHECK-NEXT:    br label [[LOOP1:%.*]]
700; CHECK:       loop1:
701; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP1]] ], [ 0, [[ENTRY:%.*]] ]
702; CHECK-NEXT:    call void @use.i64(i64 [[IV]])
703; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 4
704; CHECK-NEXT:    [[CMP:%.*]] = call i1 @get.i1()
705; CHECK-NEXT:    br i1 [[CMP]], label [[LOOP2:%.*]], label [[LOOP1]]
706; CHECK:       loop2:
707; CHECK-NEXT:    [[IV2:%.*]] = phi i64 [ [[IV2_NEXT:%.*]], [[LOOP2]] ], [ [[BASE]], [[LOOP1]] ]
708; CHECK-NEXT:    call void @use.i64(i64 [[IV2]])
709; CHECK-NEXT:    [[IV2_NEXT]] = add nuw i64 [[BASE]], [[IV_NEXT]]
710; CHECK-NEXT:    [[CMP2:%.*]] = call i1 @get.i1()
711; CHECK-NEXT:    br i1 [[CMP2]], label [[EXIT:%.*]], label [[LOOP2]]
712; CHECK:       exit:
713; CHECK-NEXT:    ret void
714;
715entry:
716  br label %loop1
717
718loop1:
719  %iv = phi i64 [ %iv.next, %loop1 ], [ 0, %entry ]
720  call void @use.i64(i64 %iv)
721  %iv.next = add nuw nsw i64 %iv, 4
722  %cmp = call i1 @get.i1()
723  br i1 %cmp, label %loop2, label %loop1
724
725loop2:
726  %iv2 = phi i64 [ %iv2.next, %loop2 ], [ %base, %loop1 ]
727  call void @use.i64(i64 %iv2)
728  %iv2.next = add nuw i64 %base, %iv.next
729  %cmp2 = call i1 @get.i1()
730  br i1 %cmp2, label %exit, label %loop2
731
732exit:
733  ret void
734}
735
736declare void @use.p0(ptr)
737declare void @use.v2p0(<2 x ptr>)
738declare void @use.i64(i64)
739declare void @use.v2i64(<2 x i64>)
740declare i1 @get.i1()
741declare i64 @get.i64()
742