1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -indvars -S -indvars-predicate-loops=0 < %s | FileCheck %s
3
4target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
5target triple = "x86_64-unknown-linux-gnu"
6
7; General case: without extra knowledge, trunc cannot be eliminated.
8define void @test_00(i64 %start, i32 %n) {
9;
10; CHECK-LABEL: @test_00(
11; CHECK-NEXT:  entry:
12; CHECK-NEXT:    br label [[LOOP:%.*]]
13; CHECK:       loop:
14; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
15; CHECK-NEXT:    [[IV_NEXT]] = add i64 [[IV]], 1
16; CHECK-NEXT:    [[NARROW_IV:%.*]] = trunc i64 [[IV]] to i32
17; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[NARROW_IV]], [[N:%.*]]
18; CHECK-NEXT:    br i1 [[CMP]], label [[LOOP]], label [[EXIT:%.*]]
19; CHECK:       exit:
20; CHECK-NEXT:    ret void
21;
22entry:
23  br label %loop
24loop:
25  %iv = phi i64 [ %start, %entry ], [ %iv.next, %loop ]
26  %iv.next = add i64 %iv, 1
27  %narrow.iv = trunc i64 %iv to i32
28  %cmp = icmp slt i32 %narrow.iv, %n
29  br i1 %cmp, label %loop, label %exit
30exit:
31  ret void
32}
33
34
35define void @test_01(i32 %n) {
36;
37; CHECK-LABEL: @test_01(
38; CHECK-NEXT:  entry:
39; CHECK-NEXT:    [[TMP0:%.*]] = icmp sgt i32 [[N:%.*]], 0
40; CHECK-NEXT:    [[SMAX:%.*]] = select i1 [[TMP0]], i32 [[N]], i32 0
41; CHECK-NEXT:    [[TMP1:%.*]] = add nuw i32 [[SMAX]], 1
42; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[TMP1]] to i64
43; CHECK-NEXT:    br label [[LOOP:%.*]]
44; CHECK:       loop:
45; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
46; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
47; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[IV_NEXT]], [[WIDE_TRIP_COUNT]]
48; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
49; CHECK:       exit:
50; CHECK-NEXT:    ret void
51;
52entry:
53  br label %loop
54loop:
55  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
56  %iv.next = add i64 %iv, 1
57  %narrow.iv = trunc i64 %iv to i32
58  %cmp = icmp slt i32 %narrow.iv, %n
59  br i1 %cmp, label %loop, label %exit
60exit:
61  ret void
62}
63
64; Max value at which we can eliminate trunc: SINT_MAX - 1.
65define void @test_02(i32 %n) {
66;
67; CHECK-LABEL: @test_02(
68; CHECK-NEXT:  entry:
69; CHECK-NEXT:    [[TMP0:%.*]] = icmp sgt i32 [[N:%.*]], 2147483646
70; CHECK-NEXT:    [[SMAX:%.*]] = select i1 [[TMP0]], i32 [[N]], i32 2147483646
71; CHECK-NEXT:    [[TMP1:%.*]] = add nuw i32 [[SMAX]], 1
72; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[TMP1]] to i64
73; CHECK-NEXT:    br label [[LOOP:%.*]]
74; CHECK:       loop:
75; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 2147483646, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
76; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
77; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[IV_NEXT]], [[WIDE_TRIP_COUNT]]
78; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
79; CHECK:       exit:
80; CHECK-NEXT:    ret void
81;
82entry:
83  br label %loop
84loop:
85  %iv = phi i64 [ 2147483646, %entry ], [ %iv.next, %loop ]
86  %iv.next = add i64 %iv, 1
87  %narrow.iv = trunc i64 %iv to i32
88  %cmp = icmp slt i32 %narrow.iv, %n
89  br i1 %cmp, label %loop, label %exit
90exit:
91  ret void
92}
93
94; If we start from SINT_MAX then the predicate is always false.
95define void @test_03(i32 %n) {
96;
97; CHECK-LABEL: @test_03(
98; CHECK-NEXT:  entry:
99; CHECK-NEXT:    br label [[LOOP:%.*]]
100; CHECK:       loop:
101; CHECK-NEXT:    br i1 false, label [[LOOP]], label [[EXIT:%.*]]
102; CHECK:       exit:
103; CHECK-NEXT:    ret void
104;
105entry:
106  br label %loop
107loop:
108  %iv = phi i64 [2147483647, %entry], [%iv.next, %loop]
109  %iv.next = add i64 %iv, 1
110  %narrow.iv = trunc i64 %iv to i32
111  %cmp = icmp slt i32 %narrow.iv, %n
112  br i1 %cmp, label %loop, label %exit
113exit:
114  ret void
115}
116
117; Minimum value at which we can apply the transform: SINT_MIN + 1.
118define void @test_04(i32 %n) {
119;
120; CHECK-LABEL: @test_04(
121; CHECK-NEXT:  entry:
122; CHECK-NEXT:    [[TMP0:%.*]] = icmp sgt i32 [[N:%.*]], -2147483647
123; CHECK-NEXT:    [[SMAX:%.*]] = select i1 [[TMP0]], i32 [[N]], i32 -2147483647
124; CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[SMAX]], 1
125; CHECK-NEXT:    br label [[LOOP:%.*]]
126; CHECK:       loop:
127; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ -2147483647, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
128; CHECK-NEXT:    [[IV_NEXT]] = add nsw i64 [[IV]], 1
129; CHECK-NEXT:    [[LFTR_WIDEIV:%.*]] = trunc i64 [[IV_NEXT]] to i32
130; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[LFTR_WIDEIV]], [[TMP1]]
131; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
132; CHECK:       exit:
133; CHECK-NEXT:    ret void
134;
135entry:
136  br label %loop
137loop:
138  %iv = phi i64 [ -2147483647, %entry ], [ %iv.next, %loop ]
139  %iv.next = add i64 %iv, 1
140  %narrow.iv = trunc i64 %iv to i32
141  %cmp = icmp slt i32 %narrow.iv, %n
142  br i1 %cmp, label %loop, label %exit
143exit:
144  ret void
145}
146
147; FIXME: Harmful LFTR should be thrown away.
148define void @test_05(i32 %n) {
149;
150; CHECK-LABEL: @test_05(
151; CHECK-NEXT:  entry:
152; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[N:%.*]], 1
153; CHECK-NEXT:    br label [[LOOP:%.*]]
154; CHECK:       loop:
155; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ -2147483648, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
156; CHECK-NEXT:    [[IV_NEXT]] = add nsw i64 [[IV]], 1
157; CHECK-NEXT:    [[LFTR_WIDEIV:%.*]] = trunc i64 [[IV_NEXT]] to i32
158; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[LFTR_WIDEIV]], [[TMP0]]
159; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
160; CHECK:       exit:
161; CHECK-NEXT:    ret void
162;
163entry:
164  br label %loop
165loop:
166  %iv = phi i64 [ -2147483648, %entry ], [ %iv.next, %loop ]
167  %iv.next = add i64 %iv, 1
168  %narrow.iv = trunc i64 %iv to i32
169  %cmp = icmp slt i32 %narrow.iv, %n
170  br i1 %cmp, label %loop, label %exit
171exit:
172  ret void
173}
174
175; Trunc changes the actual value of the IV, so it is invalid to remove it: SINT_MIN - 1.
176define void @test_06(i32 %n) {
177;
178; CHECK-LABEL: @test_06(
179; CHECK-NEXT:  entry:
180; CHECK-NEXT:    br label [[LOOP:%.*]]
181; CHECK:       loop:
182; CHECK-NEXT:    br i1 false, label [[LOOP]], label [[EXIT:%.*]]
183; CHECK:       exit:
184; CHECK-NEXT:    ret void
185;
186entry:
187  br label %loop
188loop:
189  %iv = phi i64 [ -2147483649, %entry ], [ %iv.next, %loop ]
190  %iv.next = add i64 %iv, 1
191  %narrow.iv = trunc i64 %iv to i32
192  %cmp = icmp slt i32 %narrow.iv, %n
193  br i1 %cmp, label %loop, label %exit
194exit:
195  ret void
196}
197
198; General case: without extra knowledge, trunc cannot be eliminated.
199define void @test_00_unsigned(i64 %start, i32 %n) {
200; CHECK-LABEL: @test_00_unsigned(
201; CHECK-NEXT:  entry:
202; CHECK-NEXT:    br label [[LOOP:%.*]]
203; CHECK:       loop:
204; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
205; CHECK-NEXT:    [[IV_NEXT]] = add i64 [[IV]], 1
206; CHECK-NEXT:    [[NARROW_IV:%.*]] = trunc i64 [[IV]] to i32
207; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[NARROW_IV]], [[N:%.*]]
208; CHECK-NEXT:    br i1 [[CMP]], label [[LOOP]], label [[EXIT:%.*]]
209; CHECK:       exit:
210; CHECK-NEXT:    ret void
211;
212entry:
213  br label %loop
214loop:
215  %iv = phi i64 [ %start, %entry ], [ %iv.next, %loop ]
216  %iv.next = add i64 %iv, 1
217  %narrow.iv = trunc i64 %iv to i32
218  %cmp = icmp ult i32 %narrow.iv, %n
219  br i1 %cmp, label %loop, label %exit
220exit:
221  ret void
222}
223
224; FIXME: Harmful LFTR should be thrown away.
225define void @test_01_unsigned(i32 %n) {
226; CHECK-LABEL: @test_01_unsigned(
227; CHECK-NEXT:  entry:
228; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[N:%.*]], 1
229; CHECK-NEXT:    br label [[LOOP:%.*]]
230; CHECK:       loop:
231; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
232; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
233; CHECK-NEXT:    [[LFTR_WIDEIV:%.*]] = trunc i64 [[IV_NEXT]] to i32
234; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[LFTR_WIDEIV]], [[TMP0]]
235; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
236; CHECK:       exit:
237; CHECK-NEXT:    ret void
238;
239entry:
240  br label %loop
241loop:
242  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
243  %iv.next = add i64 %iv, 1
244  %narrow.iv = trunc i64 %iv to i32
245  %cmp = icmp ult i32 %narrow.iv, %n
246  br i1 %cmp, label %loop, label %exit
247exit:
248  ret void
249}
250
251; Max value at which we can eliminate trunc: UINT_MAX - 1.
252define void @test_02_unsigned(i32 %n) {
253; CHECK-LABEL: @test_02_unsigned(
254; CHECK-NEXT:  entry:
255; CHECK-NEXT:    [[TMP0:%.*]] = icmp ugt i32 [[N:%.*]], -2
256; CHECK-NEXT:    [[UMAX:%.*]] = select i1 [[TMP0]], i32 [[N]], i32 -2
257; CHECK-NEXT:    [[TMP1:%.*]] = add nsw i32 [[UMAX]], 1
258; CHECK-NEXT:    br label [[LOOP:%.*]]
259; CHECK:       loop:
260; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 4294967294, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
261; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
262; CHECK-NEXT:    [[LFTR_WIDEIV:%.*]] = trunc i64 [[IV_NEXT]] to i32
263; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[LFTR_WIDEIV]], [[TMP1]]
264; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
265; CHECK:       exit:
266; CHECK-NEXT:    ret void
267;
268entry:
269  br label %loop
270loop:
271  %iv = phi i64 [ 4294967294, %entry ], [ %iv.next, %loop ]
272  %iv.next = add i64 %iv, 1
273  %narrow.iv = trunc i64 %iv to i32
274  %cmp = icmp ult i32 %narrow.iv, %n
275  br i1 %cmp, label %loop, label %exit
276exit:
277  ret void
278}
279
280; If we start from UINT_MAX then the predicate is always false.
281define void @test_03_unsigned(i32 %n) {
282; CHECK-LABEL: @test_03_unsigned(
283; CHECK-NEXT:  entry:
284; CHECK-NEXT:    br label [[LOOP:%.*]]
285; CHECK:       loop:
286; CHECK-NEXT:    br i1 false, label [[LOOP]], label [[EXIT:%.*]]
287; CHECK:       exit:
288; CHECK-NEXT:    ret void
289;
290entry:
291  br label %loop
292loop:
293  %iv = phi i64 [ 4294967295, %entry ], [ %iv.next, %loop ]
294  %iv.next = add i64 %iv, 1
295  %narrow.iv = trunc i64 %iv to i32
296  %cmp = icmp ult i32 %narrow.iv, %n
297  br i1 %cmp, label %loop, label %exit
298exit:
299  ret void
300}
301
302; Minimum value at which we can apply the transform: UINT_MIN.
303define void @test_04_unsigned(i32 %n) {
304; CHECK-LABEL: @test_04_unsigned(
305; CHECK-NEXT:  entry:
306; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[N:%.*]], 1
307; CHECK-NEXT:    br label [[LOOP:%.*]]
308; CHECK:       loop:
309; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
310; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
311; CHECK-NEXT:    [[LFTR_WIDEIV:%.*]] = trunc i64 [[IV_NEXT]] to i32
312; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[LFTR_WIDEIV]], [[TMP0]]
313; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
314; CHECK:       exit:
315; CHECK-NEXT:    ret void
316;
317entry:
318  br label %loop
319loop:
320  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
321  %iv.next = add i64 %iv, 1
322  %narrow.iv = trunc i64 %iv to i32
323  %cmp = icmp ult i32 %narrow.iv, %n
324  br i1 %cmp, label %loop, label %exit
325exit:
326  ret void
327}
328
329; Start from 1.
330define void @test_05_unsigned(i32 %n) {
331; CHECK-LABEL: @test_05_unsigned(
332; CHECK-NEXT:  entry:
333; CHECK-NEXT:    [[TMP0:%.*]] = icmp ugt i32 [[N:%.*]], 1
334; CHECK-NEXT:    [[UMAX:%.*]] = select i1 [[TMP0]], i32 [[N]], i32 1
335; CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[UMAX]], 1
336; CHECK-NEXT:    br label [[LOOP:%.*]]
337; CHECK:       loop:
338; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 1, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
339; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
340; CHECK-NEXT:    [[LFTR_WIDEIV:%.*]] = trunc i64 [[IV_NEXT]] to i32
341; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[LFTR_WIDEIV]], [[TMP1]]
342; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
343; CHECK:       exit:
344; CHECK-NEXT:    ret void
345;
346entry:
347  br label %loop
348loop:
349  %iv = phi i64 [ 1, %entry ], [ %iv.next, %loop ]
350  %iv.next = add i64 %iv, 1
351  %narrow.iv = trunc i64 %iv to i32
352  %cmp = icmp ult i32 %narrow.iv, %n
353  br i1 %cmp, label %loop, label %exit
354exit:
355  ret void
356}
357
358; Trunc changes the actual value of the IV, so it is invalid to remove it: UINT_MIN - 1.
359define void @test_06_unsigned(i32 %n) {
360; CHECK-LABEL: @test_06_unsigned(
361; CHECK-NEXT:  entry:
362; CHECK-NEXT:    br label [[LOOP:%.*]]
363; CHECK:       loop:
364; CHECK-NEXT:    br i1 false, label [[LOOP]], label [[EXIT:%.*]]
365; CHECK:       exit:
366; CHECK-NEXT:    ret void
367;
368entry:
369  br label %loop
370loop:
371  %iv = phi i64 [ -1, %entry ], [ %iv.next, %loop ]
372  %iv.next = add i64 %iv, 1
373  %narrow.iv = trunc i64 %iv to i32
374  %cmp = icmp ult i32 %narrow.iv, %n
375  br i1 %cmp, label %loop, label %exit
376exit:
377  ret void
378}
379
380; Do not eliminate trunc if it is used by something different from icmp.
381define void @test_07(i32* %p, i32 %n) {
382; CHECK-LABEL: @test_07(
383; CHECK-NEXT:  entry:
384; CHECK-NEXT:    [[TMP0:%.*]] = icmp sgt i32 [[N:%.*]], 0
385; CHECK-NEXT:    [[SMAX:%.*]] = select i1 [[TMP0]], i32 [[N]], i32 0
386; CHECK-NEXT:    [[TMP1:%.*]] = add nuw i32 [[SMAX]], 1
387; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[TMP1]] to i64
388; CHECK-NEXT:    br label [[LOOP:%.*]]
389; CHECK:       loop:
390; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
391; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
392; CHECK-NEXT:    [[NARROW_IV:%.*]] = trunc i64 [[IV]] to i32
393; CHECK-NEXT:    store i32 [[NARROW_IV]], i32* [[P:%.*]], align 4
394; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[IV_NEXT]], [[WIDE_TRIP_COUNT]]
395; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
396; CHECK:       exit:
397; CHECK-NEXT:    ret void
398;
399entry:
400  br label %loop
401loop:
402  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
403  %iv.next = add i64 %iv, 1
404  %narrow.iv = trunc i64 %iv to i32
405  store i32 %narrow.iv, i32* %p
406  %cmp = icmp slt i32 %narrow.iv, %n
407  br i1 %cmp, label %loop, label %exit
408exit:
409  ret void
410}
411
412; Check that we can eliminate both signed and unsigned compare.
413define void @test_08(i32 %n) {
414; CHECK-LABEL: @test_08(
415; CHECK-NEXT:  entry:
416; CHECK-NEXT:    [[ZEXT:%.*]] = zext i32 [[N:%.*]] to i64
417; CHECK-NEXT:    [[SEXT:%.*]] = sext i32 [[N]] to i64
418; CHECK-NEXT:    br label [[LOOP:%.*]]
419; CHECK:       loop:
420; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 1, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
421; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
422; CHECK-NEXT:    [[TMP0:%.*]] = icmp slt i64 [[IV]], [[SEXT]]
423; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i64 [[IV]], [[ZEXT]]
424; CHECK-NEXT:    [[CMP:%.*]] = and i1 [[TMP0]], [[TMP1]]
425; CHECK-NEXT:    br i1 [[CMP]], label [[LOOP]], label [[EXIT:%.*]]
426; CHECK:       exit:
427; CHECK-NEXT:    ret void
428;
429entry:
430  br label %loop
431loop:
432  %iv = phi i64 [ 1, %entry ], [ %iv.next, %loop ]
433  %iv.next = add i64 %iv, 1
434  %narrow.iv = trunc i64 %iv to i32
435  %cmp1 = icmp slt i32 %narrow.iv, %n
436  %cmp2 = icmp ult i32 %narrow.iv, %n
437  %cmp = and i1 %cmp1, %cmp2
438  br i1 %cmp, label %loop, label %exit
439exit:
440  ret void
441}
442
443; Widen NE as unsigned.
444define void @test_09(i32 %n) {
445; CHECK-LABEL: @test_09(
446; CHECK-NEXT:  entry:
447; CHECK-NEXT:    [[ZEXT:%.*]] = zext i32 [[N:%.*]] to i64
448; CHECK-NEXT:    br label [[LOOP:%.*]]
449; CHECK:       loop:
450; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
451; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
452; CHECK-NEXT:    [[TMP0:%.*]] = icmp ne i64 [[IV]], [[ZEXT]]
453; CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP]], label [[EXIT:%.*]]
454; CHECK:       exit:
455; CHECK-NEXT:    ret void
456;
457entry:
458  br label %loop
459loop:
460  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
461  %iv.next = add i64 %iv, 1
462  %narrow.iv = trunc i64 %iv to i32
463  %cmp = icmp ne i32 %narrow.iv, %n
464  br i1 %cmp, label %loop, label %exit
465exit:
466  ret void
467}
468
469; Widen NE as signed.
470define void @test_10(i32 %n) {
471; CHECK-LABEL: @test_10(
472; CHECK-NEXT:  entry:
473; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[N:%.*]], 100
474; CHECK-NEXT:    [[TMP1:%.*]] = zext i32 [[TMP0]] to i64
475; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i64 [[TMP1]], 90
476; CHECK-NEXT:    [[UMIN:%.*]] = select i1 [[TMP2]], i64 [[TMP1]], i64 90
477; CHECK-NEXT:    [[TMP3:%.*]] = add nuw nsw i64 [[UMIN]], -99
478; CHECK-NEXT:    br label [[LOOP:%.*]]
479; CHECK:       loop:
480; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ -100, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
481; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
482; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[IV_NEXT]], [[TMP3]]
483; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
484; CHECK:       exit:
485; CHECK-NEXT:    ret void
486;
487entry:
488  br label %loop
489loop:
490  %iv = phi i64 [ -100, %entry ], [ %iv.next, %loop ]
491  %iv.next = add i64 %iv, 1
492  %narrow.iv = trunc i64 %iv to i32
493  %trunccmp = icmp ne i32 %narrow.iv, %n
494  %negcmp = icmp slt i64 %iv, -10
495  %cmp = and i1 %trunccmp, %negcmp
496  br i1 %cmp, label %loop, label %exit
497exit:
498  ret void
499}
500
501define void @test_11() {
502; CHECK-LABEL: @test_11(
503; CHECK-NEXT:    br label [[BB1:%.*]]
504; CHECK:       bb1:
505; CHECK-NEXT:    br i1 undef, label [[BB2:%.*]], label [[BB6:%.*]]
506; CHECK:       bb2:
507; CHECK-NEXT:    br i1 undef, label [[BB3:%.*]], label [[BB4:%.*]]
508; CHECK:       bb3:
509; CHECK-NEXT:    br label [[BB4]]
510; CHECK:       bb4:
511; CHECK-NEXT:    br label [[BB6]]
512; CHECK:       bb5:
513; CHECK-NEXT:    [[_TMP24:%.*]] = icmp slt i16 undef, 0
514; CHECK-NEXT:    br i1 [[_TMP24]], label [[BB5:%.*]], label [[BB5]]
515; CHECK:       bb6:
516; CHECK-NEXT:    br i1 false, label [[BB1]], label [[BB7:%.*]]
517; CHECK:       bb7:
518; CHECK-NEXT:    ret void
519;
520  br label %bb1
521
522bb1:                                              ; preds = %bb6, %0
523  %e.5.0 = phi i32 [ 0, %0 ], [ %_tmp32, %bb6 ]
524  br i1 undef, label %bb2, label %bb6
525
526bb2:                                              ; preds = %bb1
527  %_tmp15 = trunc i32 %e.5.0 to i16
528  br i1 undef, label %bb3, label %bb4
529
530bb3:                                              ; preds = %bb2
531  br label %bb4
532
533bb4:                                              ; preds = %bb3, %bb2
534  br label %bb6
535
536bb5:                                              ; preds = %bb5, %bb5
537  %_tmp24 = icmp slt i16 %_tmp15, 0
538  br i1 %_tmp24, label %bb5, label %bb5
539
540bb6:                                              ; preds = %bb4, %bb1
541  %_tmp32 = add nuw nsw i32 %e.5.0, 1
542  br i1 false, label %bb1, label %bb7
543
544bb7:                                             ; preds = %bb6
545  ret void
546}
547
548; Show that we can turn signed comparison to unsigned and use zext while
549; comparing non-negative values.
550define void @test_12(i32* %p) {
551; CHECK-LABEL: @test_12(
552; CHECK-NEXT:  entry:
553; CHECK-NEXT:    [[N:%.*]] = load i32, i32* [[P:%.*]], align 4, [[RNG0:!range !.*]]
554; CHECK-NEXT:    [[TMP0:%.*]] = icmp sgt i32 [[N]], 1
555; CHECK-NEXT:    [[SMAX:%.*]] = select i1 [[TMP0]], i32 [[N]], i32 1
556; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64
557; CHECK-NEXT:    br label [[LOOP:%.*]]
558; CHECK:       loop:
559; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
560; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
561; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[IV_NEXT]], [[WIDE_TRIP_COUNT]]
562; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
563; CHECK:       exit:
564; CHECK-NEXT:    ret void
565;
566entry:
567  %n = load i32, i32* %p, !range !0
568  br label %loop
569loop:
570  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
571  %iv.next = add i64 %iv, 1
572  %narrow.iv = trunc i64 %iv.next to i32
573  %cmp = icmp slt i32 %narrow.iv, %n
574  br i1 %cmp, label %loop, label %exit
575exit:
576  ret void
577}
578
579define void @test_13a(i32 %n) {
580;
581; CHECK-LABEL: @test_13a(
582; CHECK-NEXT:  entry:
583; CHECK-NEXT:    [[ZEXT:%.*]] = zext i32 1024 to i64
584; CHECK-NEXT:    br label [[LOOP:%.*]]
585; CHECK:       loop:
586; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
587; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 2
588; CHECK-NEXT:    [[TMP0:%.*]] = icmp ne i64 [[IV]], [[ZEXT]]
589; CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP]], label [[EXIT:%.*]]
590; CHECK:       exit:
591; CHECK-NEXT:    ret void
592;
593entry:
594  br label %loop
595loop:
596  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
597  %iv.next = add nsw nuw i64 %iv, 2
598  %narrow.iv = trunc i64 %iv to i32
599  %cmp = icmp ne i32 1024, %narrow.iv
600  br i1 %cmp, label %loop, label %exit
601exit:
602  ret void
603}
604
605define void @test_13b(i32 %n) {
606;
607; CHECK-LABEL: @test_13b(
608; CHECK-NEXT:  entry:
609; CHECK-NEXT:    [[ZEXT:%.*]] = zext i32 1024 to i64
610; CHECK-NEXT:    br label [[LOOP:%.*]]
611; CHECK:       loop:
612; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
613; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 2
614; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i64 [[IV]], [[ZEXT]]
615; CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP]], label [[EXIT:%.*]]
616; CHECK:       exit:
617; CHECK-NEXT:    ret void
618;
619entry:
620  br label %loop
621loop:
622  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
623  %iv.next = add nsw nuw i64 %iv, 2
624  %narrow.iv = trunc i64 %iv to i32
625  %cmp = icmp ugt i32 1024, %narrow.iv
626  br i1 %cmp, label %loop, label %exit
627exit:
628  ret void
629}
630
631define void @test_13c(i32 %n) {
632;
633; CHECK-LABEL: @test_13c(
634; CHECK-NEXT:  entry:
635; CHECK-NEXT:    [[ZEXT:%.*]] = zext i32 1024 to i64
636; CHECK-NEXT:    br label [[LOOP:%.*]]
637; CHECK:       loop:
638; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
639; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 2
640; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i64 [[IV]], [[ZEXT]]
641; CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP]], label [[EXIT:%.*]]
642; CHECK:       exit:
643; CHECK-NEXT:    ret void
644;
645entry:
646  br label %loop
647loop:
648  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
649  %iv.next = add nsw nuw i64 %iv, 2
650  %narrow.iv = trunc i64 %iv to i32
651  %cmp = icmp sgt i32 1024, %narrow.iv
652  br i1 %cmp, label %loop, label %exit
653exit:
654  ret void
655}
656
657define void @test_13d(i32 %n) {
658;
659; CHECK-LABEL: @test_13d(
660; CHECK-NEXT:  entry:
661; CHECK-NEXT:    [[SEXT:%.*]] = sext i32 1024 to i64
662; CHECK-NEXT:    br label [[LOOP:%.*]]
663; CHECK:       loop:
664; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ -20, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
665; CHECK-NEXT:    [[IV_NEXT]] = add nsw i64 [[IV]], 2
666; CHECK-NEXT:    [[TMP0:%.*]] = icmp slt i64 [[IV]], [[SEXT]]
667; CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP]], label [[EXIT:%.*]]
668; CHECK:       exit:
669; CHECK-NEXT:    ret void
670;
671entry:
672  br label %loop
673loop:
674  %iv = phi i64 [ -20, %entry ], [ %iv.next, %loop ]
675  %iv.next = add nsw i64 %iv, 2
676  %narrow.iv = trunc i64 %iv to i32
677  %cmp = icmp sgt i32 1024, %narrow.iv
678  br i1 %cmp, label %loop, label %exit
679exit:
680  ret void
681}
682
683!0 = !{i32 0, i32 1000}
684