[InstCombine] Signed saturation tests. NFC
[llvm-complete.git] / test / Transforms / IndVarSimplify / eliminate-trunc.ll
blob74e422b797bf9175550da38e85dc32faa9079eb4
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -indvars -S < %s | FileCheck %s
4 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
5 target triple = "x86_64-unknown-linux-gnu"
7 ; General case: without extra knowledge, trunc cannot be eliminated.
8 define void @test_00(i64 %start, i32 %n) {
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
22 entry:
23   br label %loop
24 loop:
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
30 exit:
31   ret void
35 define void @test_01(i32 %n) {
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
49 entry:
50   br label %loop
51 loop:
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
57 exit:
58   ret void
61 ; Max value at which we can eliminate trunc: SINT_MAX - 1.
62 define void @test_02(i32 %n) {
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
76 entry:
77   br label %loop
78 loop:
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
84 exit:
85   ret void
88 ; If we start from SINT_MAX then the predicate is always false.
89 define void @test_03(i32 %n) {
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
99 entry:
100   br label %loop
101 loop:
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
107 exit:
108   ret void
111 ; Minimum value at which we can apply the transform: SINT_MIN + 1.
112 define void @test_04(i32 %n) {
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
126 entry:
127   br label %loop
128 loop:
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
134 exit:
135   ret void
138 ; FIXME: Harmful LFTR should be thrown away.
139 define void @test_05(i32 %n) {
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
154 entry:
155   br label %loop
156 loop:
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
162 exit:
163   ret void
166 ; Trunc changes the actual value of the IV, so it is invalid to remove it: SINT_MIN - 1.
167 define void @test_06(i32 %n) {
169 ; CHECK-LABEL: @test_06(
170 ; CHECK-NEXT:  entry:
171 ; CHECK-NEXT:    br label [[LOOP:%.*]]
172 ; CHECK:       loop:
173 ; CHECK-NEXT:    br i1 false, label [[LOOP]], label [[EXIT:%.*]]
174 ; CHECK:       exit:
175 ; CHECK-NEXT:    ret void
177 entry:
178   br label %loop
179 loop:
180   %iv = phi i64 [ -2147483649, %entry ], [ %iv.next, %loop ]
181   %iv.next = add i64 %iv, 1
182   %narrow.iv = trunc i64 %iv to i32
183   %cmp = icmp slt i32 %narrow.iv, %n
184   br i1 %cmp, label %loop, label %exit
185 exit:
186   ret void
189 ; General case: without extra knowledge, trunc cannot be eliminated.
190 define void @test_00_unsigned(i64 %start, i32 %n) {
191 ; CHECK-LABEL: @test_00_unsigned(
192 ; CHECK-NEXT:  entry:
193 ; CHECK-NEXT:    br label [[LOOP:%.*]]
194 ; CHECK:       loop:
195 ; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
196 ; CHECK-NEXT:    [[IV_NEXT]] = add i64 [[IV]], 1
197 ; CHECK-NEXT:    [[NARROW_IV:%.*]] = trunc i64 [[IV]] to i32
198 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[NARROW_IV]], [[N:%.*]]
199 ; CHECK-NEXT:    br i1 [[CMP]], label [[LOOP]], label [[EXIT:%.*]]
200 ; CHECK:       exit:
201 ; CHECK-NEXT:    ret void
203 entry:
204   br label %loop
205 loop:
206   %iv = phi i64 [ %start, %entry ], [ %iv.next, %loop ]
207   %iv.next = add i64 %iv, 1
208   %narrow.iv = trunc i64 %iv to i32
209   %cmp = icmp ult i32 %narrow.iv, %n
210   br i1 %cmp, label %loop, label %exit
211 exit:
212   ret void
215 ; FIXME: Harmful LFTR should be thrown away.
216 define void @test_01_unsigned(i32 %n) {
217 ; CHECK-LABEL: @test_01_unsigned(
218 ; CHECK-NEXT:  entry:
219 ; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[N:%.*]], 1
220 ; CHECK-NEXT:    br label [[LOOP:%.*]]
221 ; CHECK:       loop:
222 ; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
223 ; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
224 ; CHECK-NEXT:    [[LFTR_WIDEIV:%.*]] = trunc i64 [[IV_NEXT]] to i32
225 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[LFTR_WIDEIV]], [[TMP0]]
226 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
227 ; CHECK:       exit:
228 ; CHECK-NEXT:    ret void
230 entry:
231   br label %loop
232 loop:
233   %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
234   %iv.next = add i64 %iv, 1
235   %narrow.iv = trunc i64 %iv to i32
236   %cmp = icmp ult i32 %narrow.iv, %n
237   br i1 %cmp, label %loop, label %exit
238 exit:
239   ret void
242 ; Max value at which we can eliminate trunc: UINT_MAX - 1.
243 define void @test_02_unsigned(i32 %n) {
244 ; CHECK-LABEL: @test_02_unsigned(
245 ; CHECK-NEXT:  entry:
246 ; CHECK-NEXT:    [[ZEXT:%.*]] = zext i32 [[N:%.*]] to i64
247 ; CHECK-NEXT:    br label [[LOOP:%.*]]
248 ; CHECK:       loop:
249 ; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 4294967294, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
250 ; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
251 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i64 [[IV]], [[ZEXT]]
252 ; CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP]], label [[EXIT:%.*]]
253 ; CHECK:       exit:
254 ; CHECK-NEXT:    ret void
256 entry:
257   br label %loop
258 loop:
259   %iv = phi i64 [ 4294967294, %entry ], [ %iv.next, %loop ]
260   %iv.next = add i64 %iv, 1
261   %narrow.iv = trunc i64 %iv to i32
262   %cmp = icmp ult i32 %narrow.iv, %n
263   br i1 %cmp, label %loop, label %exit
264 exit:
265   ret void
268 ; If we start from UINT_MAX then the predicate is always false.
269 define void @test_03_unsigned(i32 %n) {
270 ; CHECK-LABEL: @test_03_unsigned(
271 ; CHECK-NEXT:  entry:
272 ; CHECK-NEXT:    br label [[LOOP:%.*]]
273 ; CHECK:       loop:
274 ; CHECK-NEXT:    br i1 false, label [[LOOP]], label [[EXIT:%.*]]
275 ; CHECK:       exit:
276 ; CHECK-NEXT:    ret void
278 entry:
279   br label %loop
280 loop:
281   %iv = phi i64 [ 4294967295, %entry ], [ %iv.next, %loop ]
282   %iv.next = add i64 %iv, 1
283   %narrow.iv = trunc i64 %iv to i32
284   %cmp = icmp ult i32 %narrow.iv, %n
285   br i1 %cmp, label %loop, label %exit
286 exit:
287   ret void
290 ; Minimum value at which we can apply the transform: UINT_MIN.
291 define void @test_04_unsigned(i32 %n) {
292 ; CHECK-LABEL: @test_04_unsigned(
293 ; CHECK-NEXT:  entry:
294 ; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[N:%.*]], 1
295 ; CHECK-NEXT:    br label [[LOOP:%.*]]
296 ; CHECK:       loop:
297 ; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
298 ; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
299 ; CHECK-NEXT:    [[LFTR_WIDEIV:%.*]] = trunc i64 [[IV_NEXT]] to i32
300 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[LFTR_WIDEIV]], [[TMP0]]
301 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
302 ; CHECK:       exit:
303 ; CHECK-NEXT:    ret void
305 entry:
306   br label %loop
307 loop:
308   %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
309   %iv.next = add i64 %iv, 1
310   %narrow.iv = trunc i64 %iv to i32
311   %cmp = icmp ult i32 %narrow.iv, %n
312   br i1 %cmp, label %loop, label %exit
313 exit:
314   ret void
317 ; Start from 1.
318 define void @test_05_unsigned(i32 %n) {
319 ; CHECK-LABEL: @test_05_unsigned(
320 ; CHECK-NEXT:  entry:
321 ; CHECK-NEXT:    [[ZEXT:%.*]] = zext i32 [[N:%.*]] to i64
322 ; CHECK-NEXT:    br label [[LOOP:%.*]]
323 ; CHECK:       loop:
324 ; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 1, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
325 ; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
326 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i64 [[IV]], [[ZEXT]]
327 ; CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP]], label [[EXIT:%.*]]
328 ; CHECK:       exit:
329 ; CHECK-NEXT:    ret void
331 entry:
332   br label %loop
333 loop:
334   %iv = phi i64 [ 1, %entry ], [ %iv.next, %loop ]
335   %iv.next = add i64 %iv, 1
336   %narrow.iv = trunc i64 %iv to i32
337   %cmp = icmp ult i32 %narrow.iv, %n
338   br i1 %cmp, label %loop, label %exit
339 exit:
340   ret void
343 ; Trunc changes the actual value of the IV, so it is invalid to remove it: UINT_MIN - 1.
344 define void @test_06_unsigned(i32 %n) {
345 ; CHECK-LABEL: @test_06_unsigned(
346 ; CHECK-NEXT:  entry:
347 ; CHECK-NEXT:    br label [[LOOP:%.*]]
348 ; CHECK:       loop:
349 ; CHECK-NEXT:    br i1 false, label [[LOOP]], label [[EXIT:%.*]]
350 ; CHECK:       exit:
351 ; CHECK-NEXT:    ret void
353 entry:
354   br label %loop
355 loop:
356   %iv = phi i64 [ -1, %entry ], [ %iv.next, %loop ]
357   %iv.next = add i64 %iv, 1
358   %narrow.iv = trunc i64 %iv to i32
359   %cmp = icmp ult i32 %narrow.iv, %n
360   br i1 %cmp, label %loop, label %exit
361 exit:
362   ret void
365 ; Do not eliminate trunc if it is used by something different from icmp.
366 define void @test_07(i32* %p, i32 %n) {
367 ; CHECK-LABEL: @test_07(
368 ; CHECK-NEXT:  entry:
369 ; CHECK-NEXT:    br label [[LOOP:%.*]]
370 ; CHECK:       loop:
371 ; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
372 ; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
373 ; CHECK-NEXT:    [[NARROW_IV:%.*]] = trunc i64 [[IV]] to i32
374 ; CHECK-NEXT:    store i32 [[NARROW_IV]], i32* [[P:%.*]]
375 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[NARROW_IV]], [[N:%.*]]
376 ; CHECK-NEXT:    br i1 [[CMP]], label [[LOOP]], label [[EXIT:%.*]]
377 ; CHECK:       exit:
378 ; CHECK-NEXT:    ret void
380 entry:
381   br label %loop
382 loop:
383   %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
384   %iv.next = add i64 %iv, 1
385   %narrow.iv = trunc i64 %iv to i32
386   store i32 %narrow.iv, i32* %p
387   %cmp = icmp slt i32 %narrow.iv, %n
388   br i1 %cmp, label %loop, label %exit
389 exit:
390   ret void
393 ; Check that we can eliminate both signed and unsigned compare.
394 define void @test_08(i32 %n) {
395 ; CHECK-LABEL: @test_08(
396 ; CHECK-NEXT:  entry:
397 ; CHECK-NEXT:    [[ZEXT:%.*]] = zext i32 [[N:%.*]] to i64
398 ; CHECK-NEXT:    [[SEXT:%.*]] = sext i32 [[N]] to i64
399 ; CHECK-NEXT:    br label [[LOOP:%.*]]
400 ; CHECK:       loop:
401 ; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 1, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
402 ; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
403 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp slt i64 [[IV]], [[SEXT]]
404 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i64 [[IV]], [[ZEXT]]
405 ; CHECK-NEXT:    [[CMP:%.*]] = and i1 [[TMP0]], [[TMP1]]
406 ; CHECK-NEXT:    br i1 [[CMP]], label [[LOOP]], label [[EXIT:%.*]]
407 ; CHECK:       exit:
408 ; CHECK-NEXT:    ret void
410 entry:
411   br label %loop
412 loop:
413   %iv = phi i64 [ 1, %entry ], [ %iv.next, %loop ]
414   %iv.next = add i64 %iv, 1
415   %narrow.iv = trunc i64 %iv to i32
416   %cmp1 = icmp slt i32 %narrow.iv, %n
417   %cmp2 = icmp ult i32 %narrow.iv, %n
418   %cmp = and i1 %cmp1, %cmp2
419   br i1 %cmp, label %loop, label %exit
420 exit:
421   ret void
424 ; Widen NE as unsigned.
425 define void @test_09(i32 %n) {
426 ; CHECK-LABEL: @test_09(
427 ; CHECK-NEXT:  entry:
428 ; CHECK-NEXT:    [[ZEXT:%.*]] = zext i32 [[N:%.*]] to i64
429 ; CHECK-NEXT:    br label [[LOOP:%.*]]
430 ; CHECK:       loop:
431 ; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
432 ; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
433 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp ne i64 [[IV]], [[ZEXT]]
434 ; CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP]], label [[EXIT:%.*]]
435 ; CHECK:       exit:
436 ; CHECK-NEXT:    ret void
438 entry:
439   br label %loop
440 loop:
441   %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
442   %iv.next = add i64 %iv, 1
443   %narrow.iv = trunc i64 %iv to i32
444   %cmp = icmp ne i32 %narrow.iv, %n
445   br i1 %cmp, label %loop, label %exit
446 exit:
447   ret void
450 ; Widen NE as signed.
451 define void @test_10(i32 %n) {
452 ; CHECK-LABEL: @test_10(
453 ; CHECK-NEXT:  entry:
454 ; CHECK-NEXT:    [[SEXT:%.*]] = sext i32 [[N:%.*]] to i64
455 ; CHECK-NEXT:    br label [[LOOP:%.*]]
456 ; CHECK:       loop:
457 ; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ -100, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
458 ; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
459 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp ne i64 [[IV]], [[SEXT]]
460 ; CHECK-NEXT:    [[NEGCMP:%.*]] = icmp slt i64 [[IV]], -10
461 ; CHECK-NEXT:    [[CMP:%.*]] = and i1 [[TMP0]], [[NEGCMP]]
462 ; CHECK-NEXT:    br i1 [[CMP]], label [[LOOP]], label [[EXIT:%.*]]
463 ; CHECK:       exit:
464 ; CHECK-NEXT:    ret void
466 entry:
467   br label %loop
468 loop:
469   %iv = phi i64 [ -100, %entry ], [ %iv.next, %loop ]
470   %iv.next = add i64 %iv, 1
471   %narrow.iv = trunc i64 %iv to i32
472   %trunccmp = icmp ne i32 %narrow.iv, %n
473   %negcmp = icmp slt i64 %iv, -10
474   %cmp = and i1 %trunccmp, %negcmp
475   br i1 %cmp, label %loop, label %exit
476 exit:
477   ret void
480 define void @test_11() {
481 ; CHECK-LABEL: @test_11(
482 ; CHECK-NEXT:    br label [[BB1:%.*]]
483 ; CHECK:       bb1:
484 ; CHECK-NEXT:    br i1 undef, label [[BB2:%.*]], label [[BB6:%.*]]
485 ; CHECK:       bb2:
486 ; CHECK-NEXT:    br i1 undef, label [[BB3:%.*]], label [[BB4:%.*]]
487 ; CHECK:       bb3:
488 ; CHECK-NEXT:    br label [[BB4]]
489 ; CHECK:       bb4:
490 ; CHECK-NEXT:    br label [[BB6]]
491 ; CHECK:       bb5:
492 ; CHECK-NEXT:    [[_TMP24:%.*]] = icmp slt i16 undef, 0
493 ; CHECK-NEXT:    br i1 [[_TMP24]], label [[BB5:%.*]], label [[BB5]]
494 ; CHECK:       bb6:
495 ; CHECK-NEXT:    br i1 false, label [[BB1]], label [[BB7:%.*]]
496 ; CHECK:       bb7:
497 ; CHECK-NEXT:    ret void
499   br label %bb1
501 bb1:                                              ; preds = %bb6, %0
502   %e.5.0 = phi i32 [ 0, %0 ], [ %_tmp32, %bb6 ]
503   br i1 undef, label %bb2, label %bb6
505 bb2:                                              ; preds = %bb1
506   %_tmp15 = trunc i32 %e.5.0 to i16
507   br i1 undef, label %bb3, label %bb4
509 bb3:                                              ; preds = %bb2
510   br label %bb4
512 bb4:                                              ; preds = %bb3, %bb2
513   br label %bb6
515 bb5:                                              ; preds = %bb5, %bb5
516   %_tmp24 = icmp slt i16 %_tmp15, 0
517   br i1 %_tmp24, label %bb5, label %bb5
519 bb6:                                              ; preds = %bb4, %bb1
520   %_tmp32 = add nuw nsw i32 %e.5.0, 1
521   br i1 false, label %bb1, label %bb7
523 bb7:                                             ; preds = %bb6
524   ret void
527 ; Show that we can turn signed comparison to unsigned and use zext while
528 ; comparing non-negative values.
529 define void @test_12(i32* %p) {
530 ; CHECK-LABEL: @test_12(
531 ; CHECK-NEXT:  entry:
532 ; CHECK-NEXT:    [[N:%.*]] = load i32, i32* [[P:%.*]], !range !0
533 ; CHECK-NEXT:    [[ZEXT:%.*]] = zext i32 [[N]] to i64
534 ; CHECK-NEXT:    br label [[LOOP:%.*]]
535 ; CHECK:       loop:
536 ; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
537 ; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
538 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i64 [[IV_NEXT]], [[ZEXT]]
539 ; CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP]], label [[EXIT:%.*]]
540 ; CHECK:       exit:
541 ; CHECK-NEXT:    ret void
543 entry:
544   %n = load i32, i32* %p, !range !0
545   br label %loop
546 loop:
547   %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
548   %iv.next = add i64 %iv, 1
549   %narrow.iv = trunc i64 %iv.next to i32
550   %cmp = icmp slt i32 %narrow.iv, %n
551   br i1 %cmp, label %loop, label %exit
552 exit:
553   ret void
556 define void @test_13a(i32 %n) {
558 ; CHECK-LABEL: @test_13a(
559 ; CHECK-NEXT:  entry:
560 ; CHECK-NEXT:    [[ZEXT:%.*]] = zext i32 1024 to i64
561 ; CHECK-NEXT:    br label [[LOOP:%.*]]
562 ; CHECK:       loop:
563 ; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
564 ; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 2
565 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp ne i64 [[IV]], [[ZEXT]]
566 ; CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP]], label [[EXIT:%.*]]
567 ; CHECK:       exit:
568 ; CHECK-NEXT:    ret void
570 entry:
571   br label %loop
572 loop:
573   %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
574   %iv.next = add nsw nuw i64 %iv, 2
575   %narrow.iv = trunc i64 %iv to i32
576   %cmp = icmp ne i32 1024, %narrow.iv
577   br i1 %cmp, label %loop, label %exit
578 exit:
579   ret void
582 define void @test_13b(i32 %n) {
584 ; CHECK-LABEL: @test_13b(
585 ; CHECK-NEXT:  entry:
586 ; CHECK-NEXT:    [[ZEXT:%.*]] = zext i32 1024 to i64
587 ; CHECK-NEXT:    br label [[LOOP:%.*]]
588 ; CHECK:       loop:
589 ; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
590 ; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 2
591 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i64 [[IV]], [[ZEXT]]
592 ; CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP]], label [[EXIT:%.*]]
593 ; CHECK:       exit:
594 ; CHECK-NEXT:    ret void
596 entry:
597   br label %loop
598 loop:
599   %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
600   %iv.next = add nsw nuw i64 %iv, 2
601   %narrow.iv = trunc i64 %iv to i32
602   %cmp = icmp ugt i32 1024, %narrow.iv
603   br i1 %cmp, label %loop, label %exit
604 exit:
605   ret void
608 define void @test_13c(i32 %n) {
610 ; CHECK-LABEL: @test_13c(
611 ; CHECK-NEXT:  entry:
612 ; CHECK-NEXT:    [[ZEXT:%.*]] = zext i32 1024 to i64
613 ; CHECK-NEXT:    br label [[LOOP:%.*]]
614 ; CHECK:       loop:
615 ; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
616 ; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 2
617 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i64 [[IV]], [[ZEXT]]
618 ; CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP]], label [[EXIT:%.*]]
619 ; CHECK:       exit:
620 ; CHECK-NEXT:    ret void
622 entry:
623   br label %loop
624 loop:
625   %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
626   %iv.next = add nsw nuw i64 %iv, 2
627   %narrow.iv = trunc i64 %iv to i32
628   %cmp = icmp sgt i32 1024, %narrow.iv
629   br i1 %cmp, label %loop, label %exit
630 exit:
631   ret void
634 define void @test_13d(i32 %n) {
636 ; CHECK-LABEL: @test_13d(
637 ; CHECK-NEXT:  entry:
638 ; CHECK-NEXT:    [[SEXT:%.*]] = sext i32 1024 to i64
639 ; CHECK-NEXT:    br label [[LOOP:%.*]]
640 ; CHECK:       loop:
641 ; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ -20, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
642 ; CHECK-NEXT:    [[IV_NEXT]] = add nsw i64 [[IV]], 2
643 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp slt i64 [[IV]], [[SEXT]]
644 ; CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP]], label [[EXIT:%.*]]
645 ; CHECK:       exit:
646 ; CHECK-NEXT:    ret void
648 entry:
649   br label %loop
650 loop:
651   %iv = phi i64 [ -20, %entry ], [ %iv.next, %loop ]
652   %iv.next = add nsw i64 %iv, 2
653   %narrow.iv = trunc i64 %iv to i32
654   %cmp = icmp sgt i32 1024, %narrow.iv
655   br i1 %cmp, label %loop, label %exit
656 exit:
657   ret void
660 !0 = !{i32 0, i32 1000}