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