[test] Pre-commit llvm.experimental.memset.pattern tests prior to MemoryLocation...
[llvm-project.git] / llvm / test / Transforms / IndVarSimplify / X86 / eliminate-trunc.ll
blob565ac5c8743d475e7cdf15fa44727e828d56da20
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -passes=indvars -S -indvars-predicate-loops=0 < %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:    [[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
51 entry:
52   br label %loop
53 loop:
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
59 exit:
60   ret void
63 ; Max value at which we can eliminate trunc: SINT_MAX - 1.
64 define void @test_02(i32 %n) {
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
80 entry:
81   br label %loop
82 loop:
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
88 exit:
89   ret void
92 ; If we start from SINT_MAX then the predicate is always false.
93 define void @test_03(i32 %n) {
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
103 entry:
104   br label %loop
105 loop:
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
111 exit:
112   ret void
115 ; Minimum value at which we can apply the transform: SINT_MIN + 1.
116 define void @test_04(i32 %n) {
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
132 entry:
133   br label %loop
134 loop:
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
140 exit:
141   ret void
144 ; FIXME: Harmful LFTR should be thrown away.
145 define void @test_05(i32 %n) {
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
160 entry:
161   br label %loop
162 loop:
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
168 exit:
169   ret void
172 ; Trunc changes the actual value of the IV, so it is invalid to remove it: SINT_MIN - 1.
173 define void @test_06(i32 %n) {
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
183 entry:
184   br label %loop
185 loop:
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
191 exit:
192   ret void
195 ; General case: without extra knowledge, trunc cannot be eliminated.
196 define 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
209 entry:
210   br label %loop
211 loop:
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
217 exit:
218   ret void
221 ; FIXME: Harmful LFTR should be thrown away.
222 define 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
236 entry:
237   br label %loop
238 loop:
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
244 exit:
245   ret void
248 ; Max value at which we can eliminate trunc: UINT_MAX - 1.
249 define 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
264 entry:
265   br label %loop
266 loop:
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
272 exit:
273   ret void
276 ; If we start from UINT_MAX then the predicate is always false.
277 define 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
286 entry:
287   br label %loop
288 loop:
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
294 exit:
295   ret void
298 ; Minimum value at which we can apply the transform: UINT_MIN.
299 define 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
313 entry:
314   br label %loop
315 loop:
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
321 exit:
322   ret void
325 ; Start from 1.
326 define 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
341 entry:
342   br label %loop
343 loop:
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
349 exit:
350   ret void
353 ; Trunc changes the actual value of the IV, so it is invalid to remove it: UINT_MIN - 1.
354 define 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
363 entry:
364   br label %loop
365 loop:
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
371 exit:
372   ret void
375 ; Do not eliminate trunc if it is used by something different from icmp.
376 define void @test_07(ptr %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]], ptr [[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
393 entry:
394   br label %loop
395 loop:
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, ptr %p
400   %cmp = icmp slt i32 %narrow.iv, %n
401   br i1 %cmp, label %loop, label %exit
402 exit:
403   ret void
406 ; Check that we can eliminate both signed and unsigned compare.
407 define 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
423 entry:
424   br label %loop
425 loop:
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
433 exit:
434   ret void
437 ; Widen NE as unsigned.
438 define 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
451 entry:
452   br label %loop
453 loop:
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
459 exit:
460   ret void
463 ; Widen NE as signed.
464 define 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
480 entry:
481   br label %loop
482 loop:
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
490 exit:
491   ret void
494 define void @test_11(i1 %arg) {
495 ; CHECK-LABEL: @test_11(
496 ; CHECK-NEXT:    br label [[BB1:%.*]]
497 ; CHECK:       bb1:
498 ; CHECK-NEXT:    br i1 [[ARG:%.*]], label [[BB2:%.*]], label [[BB6:%.*]]
499 ; CHECK:       bb2:
500 ; CHECK-NEXT:    br i1 [[ARG]], 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:    br i1 poison, label [[BB5:%.*]], label [[BB5]]
507 ; CHECK:       bb6:
508 ; CHECK-NEXT:    br i1 false, label [[BB1]], label [[BB7:%.*]]
509 ; CHECK:       bb7:
510 ; CHECK-NEXT:    ret void
512   br label %bb1
514 bb1:                                              ; preds = %bb6, %0
515   %e.5.0 = phi i32 [ 0, %0 ], [ %_tmp32, %bb6 ]
516   br i1 %arg, label %bb2, label %bb6
518 bb2:                                              ; preds = %bb1
519   %_tmp15 = trunc i32 %e.5.0 to i16
520   br i1 %arg, label %bb3, label %bb4
522 bb3:                                              ; preds = %bb2
523   br label %bb4
525 bb4:                                              ; preds = %bb3, %bb2
526   br label %bb6
528 bb5:                                              ; preds = %bb5, %bb5
529   %_tmp24 = icmp slt i16 %_tmp15, 0
530   br i1 %_tmp24, label %bb5, label %bb5
532 bb6:                                              ; preds = %bb4, %bb1
533   %_tmp32 = add nuw nsw i32 %e.5.0, 1
534   br i1 false, label %bb1, label %bb7
536 bb7:                                             ; preds = %bb6
537   ret void
540 ; Show that we can turn signed comparison to unsigned and use zext while
541 ; comparing non-negative values.
542 define void @test_12(ptr %p) {
543 ; CHECK-LABEL: @test_12(
544 ; CHECK-NEXT:  entry:
545 ; CHECK-NEXT:    [[N:%.*]] = load i32, ptr [[P:%.*]], align 4, !range [[RNG0:![0-9]+]]
546 ; CHECK-NEXT:    [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[N]], i32 1)
547 ; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64
548 ; CHECK-NEXT:    br label [[LOOP:%.*]]
549 ; CHECK:       loop:
550 ; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
551 ; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
552 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[IV_NEXT]], [[WIDE_TRIP_COUNT]]
553 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
554 ; CHECK:       exit:
555 ; CHECK-NEXT:    ret void
557 entry:
558   %n = load i32, ptr %p, !range !0
559   br label %loop
560 loop:
561   %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
562   %iv.next = add i64 %iv, 1
563   %narrow.iv = trunc i64 %iv.next to i32
564   %cmp = icmp slt i32 %narrow.iv, %n
565   br i1 %cmp, label %loop, label %exit
566 exit:
567   ret void
570 define void @test_13a(i32 %n) {
572 ; CHECK-LABEL: @test_13a(
573 ; CHECK-NEXT:  entry:
574 ; CHECK-NEXT:    br label [[LOOP:%.*]]
575 ; CHECK:       loop:
576 ; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
577 ; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 2
578 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp ne i64 [[IV]], 1024
579 ; CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP]], label [[EXIT:%.*]]
580 ; CHECK:       exit:
581 ; CHECK-NEXT:    ret void
583 entry:
584   br label %loop
585 loop:
586   %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
587   %iv.next = add nsw nuw i64 %iv, 2
588   %narrow.iv = trunc i64 %iv to i32
589   %cmp = icmp ne i32 1024, %narrow.iv
590   br i1 %cmp, label %loop, label %exit
591 exit:
592   ret void
595 define void @test_13b(i32 %n) {
597 ; CHECK-LABEL: @test_13b(
598 ; CHECK-NEXT:  entry:
599 ; CHECK-NEXT:    br label [[LOOP:%.*]]
600 ; CHECK:       loop:
601 ; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
602 ; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 2
603 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i64 [[IV]], 1024
604 ; CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP]], label [[EXIT:%.*]]
605 ; CHECK:       exit:
606 ; CHECK-NEXT:    ret void
608 entry:
609   br label %loop
610 loop:
611   %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
612   %iv.next = add nsw nuw i64 %iv, 2
613   %narrow.iv = trunc i64 %iv to i32
614   %cmp = icmp ugt i32 1024, %narrow.iv
615   br i1 %cmp, label %loop, label %exit
616 exit:
617   ret void
620 define void @test_13c(i32 %n) {
622 ; CHECK-LABEL: @test_13c(
623 ; CHECK-NEXT:  entry:
624 ; CHECK-NEXT:    br label [[LOOP:%.*]]
625 ; CHECK:       loop:
626 ; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
627 ; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 2
628 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i64 [[IV]], 1024
629 ; CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP]], label [[EXIT:%.*]]
630 ; CHECK:       exit:
631 ; CHECK-NEXT:    ret void
633 entry:
634   br label %loop
635 loop:
636   %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
637   %iv.next = add nsw nuw i64 %iv, 2
638   %narrow.iv = trunc i64 %iv to i32
639   %cmp = icmp sgt i32 1024, %narrow.iv
640   br i1 %cmp, label %loop, label %exit
641 exit:
642   ret void
645 define void @test_13d(i32 %n) {
647 ; CHECK-LABEL: @test_13d(
648 ; CHECK-NEXT:  entry:
649 ; CHECK-NEXT:    br label [[LOOP:%.*]]
650 ; CHECK:       loop:
651 ; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ -20, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
652 ; CHECK-NEXT:    [[IV_NEXT]] = add nsw i64 [[IV]], 2
653 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp slt i64 [[IV]], 1024
654 ; CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP]], label [[EXIT:%.*]]
655 ; CHECK:       exit:
656 ; CHECK-NEXT:    ret void
658 entry:
659   br label %loop
660 loop:
661   %iv = phi i64 [ -20, %entry ], [ %iv.next, %loop ]
662   %iv.next = add nsw i64 %iv, 2
663   %narrow.iv = trunc i64 %iv to i32
664   %cmp = icmp sgt i32 1024, %narrow.iv
665   br i1 %cmp, label %loop, label %exit
666 exit:
667   ret void
670 !0 = !{i32 0, i32 1000}