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