xref: /llvm-project/llvm/test/Transforms/IndVarSimplify/finite-exit-comparisons.ll (revision 40a647fc7dc6048c92e2d580b61f5feca0785980)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -passes=indvars -S < %s -indvars-predicate-loops=0 | FileCheck %s
3
4; A collection of tests which domonstrate cases where we can use properties
5; of the loop (i.e. single exit, finite, mustprogress) to optimize conditions
6; and extends we couldn't otherwise handle.
7
8target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
9
10define void @slt_constant_rhs(i16 %n.raw, i8 %start) mustprogress {
11; CHECK-LABEL: @slt_constant_rhs(
12; CHECK-NEXT:  entry:
13; CHECK-NEXT:    [[TMP0:%.*]] = trunc i16 254 to i8
14; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
15; CHECK:       for.body:
16; CHECK-NEXT:    [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[START:%.*]], [[ENTRY:%.*]] ]
17; CHECK-NEXT:    [[IV_NEXT]] = add i8 [[IV]], 1
18; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i8 [[IV_NEXT]], [[TMP0]]
19; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
20; CHECK:       for.end:
21; CHECK-NEXT:    ret void
22;
23entry:
24  br label %for.body
25
26for.body:                                         ; preds = %entry, %for.body
27  %iv = phi i8 [ %iv.next, %for.body ], [ %start, %entry ]
28  %iv.next = add i8 %iv, 1
29  %zext = zext i8 %iv.next to i16
30  %cmp = icmp slt i16 %zext, 254
31  br i1 %cmp, label %for.body, label %for.end
32
33for.end:                                          ; preds = %for.body, %entry
34  ret void
35}
36
37;; Range logic doesn't depend on must execute
38define void @slt_constant_rhs_maythrow(i16 %n.raw, i8 %start) mustprogress {
39; CHECK-LABEL: @slt_constant_rhs_maythrow(
40; CHECK-NEXT:  entry:
41; CHECK-NEXT:    [[TMP0:%.*]] = trunc i16 254 to i8
42; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
43; CHECK:       for.body:
44; CHECK-NEXT:    [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[START:%.*]], [[ENTRY:%.*]] ]
45; CHECK-NEXT:    [[IV_NEXT]] = add i8 [[IV]], 1
46; CHECK-NEXT:    call void @unknown()
47; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i8 [[IV_NEXT]], [[TMP0]]
48; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
49; CHECK:       for.end:
50; CHECK-NEXT:    ret void
51;
52entry:
53  br label %for.body
54
55for.body:                                         ; preds = %entry, %for.body
56  %iv = phi i8 [ %iv.next, %for.body ], [ %start, %entry ]
57  %iv.next = add i8 %iv, 1
58  call void @unknown()
59  %zext = zext i8 %iv.next to i16
60  %cmp = icmp slt i16 %zext, 254
61  br i1 %cmp, label %for.body, label %for.end
62
63for.end:                                          ; preds = %for.body, %entry
64  ret void
65}
66
67;; Range logic doesn't depend on must execute
68define void @slt_constant_rhs_multiexit(i16 %n.raw, i8 %start, i1 %c) mustprogress {
69; CHECK-LABEL: @slt_constant_rhs_multiexit(
70; CHECK-NEXT:  entry:
71; CHECK-NEXT:    [[TMP0:%.*]] = trunc i16 254 to i8
72; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
73; CHECK:       for.body:
74; CHECK-NEXT:    [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ], [ [[START:%.*]], [[ENTRY:%.*]] ]
75; CHECK-NEXT:    [[IV_NEXT]] = add i8 [[IV]], 1
76; CHECK-NEXT:    br i1 [[C:%.*]], label [[LATCH]], label [[FOR_END:%.*]]
77; CHECK:       latch:
78; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i8 [[IV_NEXT]], [[TMP0]]
79; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END]]
80; CHECK:       for.end:
81; CHECK-NEXT:    ret void
82;
83entry:
84  br label %for.body
85
86for.body:                                         ; preds = %entry, %for.body
87  %iv = phi i8 [ %iv.next, %latch ], [ %start, %entry ]
88  %iv.next = add i8 %iv, 1
89  br i1 %c, label %latch, label %for.end
90
91latch:
92  %zext = zext i8 %iv.next to i16
93  %cmp = icmp slt i16 %zext, 254
94  br i1 %cmp, label %for.body, label %for.end
95
96for.end:                                          ; preds = %for.body, %entry
97  ret void
98}
99
100define void @slt_non_constant_rhs(i16 %n) mustprogress {
101; CHECK-LABEL: @slt_non_constant_rhs(
102; CHECK-NEXT:  entry:
103; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
104; CHECK:       for.body:
105; CHECK-NEXT:    [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
106; CHECK-NEXT:    [[IV_NEXT]] = add i8 [[IV]], 1
107; CHECK-NEXT:    [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16
108; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i16 [[ZEXT]], [[N:%.*]]
109; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
110; CHECK:       for.end:
111; CHECK-NEXT:    ret void
112;
113entry:
114  br label %for.body
115
116for.body:                                         ; preds = %entry, %for.body
117  %iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ]
118  %iv.next = add i8 %iv, 1
119  %zext = zext i8 %iv.next to i16
120  %cmp = icmp slt i16 %zext, %n
121  br i1 %cmp, label %for.body, label %for.end
122
123for.end:                                          ; preds = %for.body, %entry
124  ret void
125}
126
127; Case where we could prove this using range facts, but not must exit reasoning
128define void @slt_non_constant_rhs_no_mustprogress(i16 %n.raw) {
129; CHECK-LABEL: @slt_non_constant_rhs_no_mustprogress(
130; CHECK-NEXT:  entry:
131; CHECK-NEXT:    [[N:%.*]] = and i16 [[N_RAW:%.*]], 255
132; CHECK-NEXT:    [[SMAX:%.*]] = call i16 @llvm.smax.i16(i16 [[N]], i16 1)
133; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
134; CHECK:       for.body:
135; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i16 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
136; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i16 [[INDVARS_IV]], 1
137; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i16 [[INDVARS_IV_NEXT]], [[SMAX]]
138; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_END:%.*]]
139; CHECK:       for.end:
140; CHECK-NEXT:    ret void
141;
142entry:
143  %n = and i16 %n.raw, 255
144  br label %for.body
145
146for.body:                                         ; preds = %entry, %for.body
147  %iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ]
148  %iv.next = add i8 %iv, 1
149  %zext = zext i8 %iv.next to i16
150  %cmp = icmp slt i16 %zext, %n
151  br i1 %cmp, label %for.body, label %for.end
152
153for.end:                                          ; preds = %for.body, %entry
154  ret void
155}
156
157; Fact holds for exiting branch, but not for earlier use
158; We could recognize the unreachable loop here, but don't currently.  Its
159; also not terribly interesting, because EarlyCSE will fold condition.
160define void @slt_neg_multiple_use(i8 %start) mustprogress {
161; CHECK-LABEL: @slt_neg_multiple_use(
162; CHECK-NEXT:  entry:
163; CHECK-NEXT:    [[ZEXT:%.*]] = zext i8 [[START:%.*]] to i16
164; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i16 [[ZEXT]], 254
165; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]]
166; CHECK:       for.body.preheader:
167; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
168; CHECK:       for.body:
169; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]]
170; CHECK:       for.end.loopexit:
171; CHECK-NEXT:    br label [[FOR_END]]
172; CHECK:       for.end:
173; CHECK-NEXT:    ret void
174;
175entry:
176  %zext = zext i8 %start to i16
177  %cmp = icmp slt i16 %zext, 254
178  br i1 %cmp, label %for.body, label %for.end
179
180for.body:                                         ; preds = %entry, %for.body
181  br i1 %cmp, label %for.body, label %for.end
182
183for.end:                                          ; preds = %for.body, %entry
184  ret void
185}
186
187define void @slt_neg_multiple_use2(i8 %start, i16 %n) mustprogress {
188; CHECK-LABEL: @slt_neg_multiple_use2(
189; CHECK-NEXT:  entry:
190; CHECK-NEXT:    [[ZEXT:%.*]] = zext i8 [[START:%.*]] to i16
191; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i16 [[ZEXT]], [[N:%.*]]
192; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]]
193; CHECK:       for.body.preheader:
194; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
195; CHECK:       for.body:
196; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]]
197; CHECK:       for.end.loopexit:
198; CHECK-NEXT:    br label [[FOR_END]]
199; CHECK:       for.end:
200; CHECK-NEXT:    ret void
201;
202entry:
203  %zext = zext i8 %start to i16
204  %cmp = icmp slt i16 %zext, %n
205  br i1 %cmp, label %for.body, label %for.end
206
207for.body:                                         ; preds = %entry, %for.body
208  br i1 %cmp, label %for.body, label %for.end
209
210for.end:                                          ; preds = %for.body, %entry
211  ret void
212}
213
214@G = external global i8
215
216; Negative case where the loop could be infinite and make progress
217define void @slt_neg_well_defined_infinite(i16 %n) mustprogress {
218; CHECK-LABEL: @slt_neg_well_defined_infinite(
219; CHECK-NEXT:  entry:
220; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
221; CHECK:       for.body:
222; CHECK-NEXT:    [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
223; CHECK-NEXT:    store volatile i8 [[IV]], ptr @G, align 1
224; CHECK-NEXT:    [[IV_NEXT]] = add i8 [[IV]], 1
225; CHECK-NEXT:    [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16
226; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i16 [[ZEXT]], [[N:%.*]]
227; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
228; CHECK:       for.end:
229; CHECK-NEXT:    ret void
230;
231entry:
232  br label %for.body
233
234for.body:                                         ; preds = %entry, %for.body
235  %iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ]
236  store volatile i8 %iv, ptr @G
237  %iv.next = add i8 %iv, 1
238  %zext = zext i8 %iv.next to i16
239  %cmp = icmp slt i16 %zext, %n
240  br i1 %cmp, label %for.body, label %for.end
241
242for.end:                                          ; preds = %for.body, %entry
243  ret void
244}
245
246; Negative case with no mustprogress rsltuirement
247define void @slt_neg_no_mustprogress(i16 %n) {
248; CHECK-LABEL: @slt_neg_no_mustprogress(
249; CHECK-NEXT:  entry:
250; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
251; CHECK:       for.body:
252; CHECK-NEXT:    [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
253; CHECK-NEXT:    [[IV_NEXT]] = add i8 [[IV]], 1
254; CHECK-NEXT:    [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16
255; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i16 [[ZEXT]], [[N:%.*]]
256; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
257; CHECK:       for.end:
258; CHECK-NEXT:    ret void
259;
260entry:
261  br label %for.body
262
263for.body:                                         ; preds = %entry, %for.body
264  %iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ]
265  %iv.next = add i8 %iv, 1
266  %zext = zext i8 %iv.next to i16
267  %cmp = icmp slt i16 %zext, %n
268  br i1 %cmp, label %for.body, label %for.end
269
270for.end:                                          ; preds = %for.body, %entry
271  ret void
272}
273
274declare void @unknown()
275
276define void @slt_neg_abnormal_exit(i16 %n) mustprogress {
277; CHECK-LABEL: @slt_neg_abnormal_exit(
278; CHECK-NEXT:  entry:
279; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
280; CHECK:       for.body:
281; CHECK-NEXT:    [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
282; CHECK-NEXT:    [[IV_NEXT]] = add i8 [[IV]], 1
283; CHECK-NEXT:    call void @unknown()
284; CHECK-NEXT:    [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16
285; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i16 [[ZEXT]], [[N:%.*]]
286; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
287; CHECK:       for.end:
288; CHECK-NEXT:    ret void
289;
290entry:
291  br label %for.body
292
293for.body:                                         ; preds = %entry, %for.body
294  %iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ]
295  %iv.next = add i8 %iv, 1
296  call void @unknown()
297  %zext = zext i8 %iv.next to i16
298  %cmp = icmp slt i16 %zext, %n
299  br i1 %cmp, label %for.body, label %for.end
300
301for.end:                                          ; preds = %for.body, %entry
302  ret void
303}
304
305; For the other comparison flavors, we only bother to repeat the positive
306; tests since the negative variants are mostly the same.
307
308define void @ne_constant_rhs(i16 %n.raw, i8 %start) mustprogress {
309; CHECK-LABEL: @ne_constant_rhs(
310; CHECK-NEXT:  entry:
311; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
312; CHECK:       for.body:
313; CHECK-NEXT:    [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[START:%.*]], [[ENTRY:%.*]] ]
314; CHECK-NEXT:    [[IV_NEXT]] = add i8 [[IV]], 1
315; CHECK-NEXT:    [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16
316; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i16 [[ZEXT]], 254
317; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
318; CHECK:       for.end:
319; CHECK-NEXT:    ret void
320;
321entry:
322  br label %for.body
323
324for.body:                                         ; preds = %entry, %for.body
325  %iv = phi i8 [ %iv.next, %for.body ], [ %start, %entry ]
326  %iv.next = add i8 %iv, 1
327  %zext = zext i8 %iv.next to i16
328  %cmp = icmp ne i16 %zext, 254
329  br i1 %cmp, label %for.body, label %for.end
330
331for.end:                                          ; preds = %for.body, %entry
332  ret void
333}
334
335define void @ne_non_constant_rhs(i16 %n) mustprogress {
336; CHECK-LABEL: @ne_non_constant_rhs(
337; CHECK-NEXT:  entry:
338; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
339; CHECK:       for.body:
340; CHECK-NEXT:    [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
341; CHECK-NEXT:    [[IV_NEXT]] = add i8 [[IV]], 1
342; CHECK-NEXT:    [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16
343; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i16 [[ZEXT]], [[N:%.*]]
344; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
345; CHECK:       for.end:
346; CHECK-NEXT:    ret void
347;
348entry:
349  br label %for.body
350
351for.body:                                         ; preds = %entry, %for.body
352  %iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ]
353  %iv.next = add i8 %iv, 1
354  %zext = zext i8 %iv.next to i16
355  %cmp = icmp ne i16 %zext, %n
356  br i1 %cmp, label %for.body, label %for.end
357
358for.end:                                          ; preds = %for.body, %entry
359  ret void
360}
361
362define void @eq_constant_rhs(i16 %n.raw, i8 %start) mustprogress {
363; CHECK-LABEL: @eq_constant_rhs(
364; CHECK-NEXT:  entry:
365; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
366; CHECK:       for.body:
367; CHECK-NEXT:    [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[START:%.*]], [[ENTRY:%.*]] ]
368; CHECK-NEXT:    [[IV_NEXT]] = add i8 [[IV]], 1
369; CHECK-NEXT:    [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16
370; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i16 [[ZEXT]], 254
371; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
372; CHECK:       for.end:
373; CHECK-NEXT:    ret void
374;
375entry:
376  br label %for.body
377
378for.body:                                         ; preds = %entry, %for.body
379  %iv = phi i8 [ %iv.next, %for.body ], [ %start, %entry ]
380  %iv.next = add i8 %iv, 1
381  %zext = zext i8 %iv.next to i16
382  %cmp = icmp eq i16 %zext, 254
383  br i1 %cmp, label %for.body, label %for.end
384
385for.end:                                          ; preds = %for.body, %entry
386  ret void
387}
388
389define void @eq_non_constant_rhs(i16 %n) mustprogress {
390; CHECK-LABEL: @eq_non_constant_rhs(
391; CHECK-NEXT:  entry:
392; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
393; CHECK:       for.body:
394; CHECK-NEXT:    [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
395; CHECK-NEXT:    [[IV_NEXT]] = add i8 [[IV]], 1
396; CHECK-NEXT:    [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16
397; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i16 [[ZEXT]], [[N:%.*]]
398; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
399; CHECK:       for.end:
400; CHECK-NEXT:    ret void
401;
402entry:
403  br label %for.body
404
405for.body:                                         ; preds = %entry, %for.body
406  %iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ]
407  %iv.next = add i8 %iv, 1
408  %zext = zext i8 %iv.next to i16
409  %cmp = icmp eq i16 %zext, %n
410  br i1 %cmp, label %for.body, label %for.end
411
412for.end:                                          ; preds = %for.body, %entry
413  ret void
414}
415
416define void @sgt_constant_rhs(i16 %n.raw, i8 %start) mustprogress {
417; CHECK-LABEL: @sgt_constant_rhs(
418; CHECK-NEXT:  entry:
419; CHECK-NEXT:    [[TMP0:%.*]] = trunc i16 254 to i8
420; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
421; CHECK:       for.body:
422; CHECK-NEXT:    [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[START:%.*]], [[ENTRY:%.*]] ]
423; CHECK-NEXT:    [[IV_NEXT]] = add i8 [[IV]], 1
424; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i8 [[IV_NEXT]], [[TMP0]]
425; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
426; CHECK:       for.end:
427; CHECK-NEXT:    ret void
428;
429entry:
430  br label %for.body
431
432for.body:                                         ; preds = %entry, %for.body
433  %iv = phi i8 [ %iv.next, %for.body ], [ %start, %entry ]
434  %iv.next = add i8 %iv, 1
435  %zext = zext i8 %iv.next to i16
436  %cmp = icmp sgt i16 %zext, 254
437  br i1 %cmp, label %for.body, label %for.end
438
439for.end:                                          ; preds = %for.body, %entry
440  ret void
441}
442
443define void @sgt_non_constant_rhs(i16 %n) mustprogress {
444; CHECK-LABEL: @sgt_non_constant_rhs(
445; CHECK-NEXT:  entry:
446; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
447; CHECK:       for.body:
448; CHECK-NEXT:    [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
449; CHECK-NEXT:    [[IV_NEXT]] = add i8 [[IV]], 1
450; CHECK-NEXT:    [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16
451; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i16 [[ZEXT]], [[N:%.*]]
452; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
453; CHECK:       for.end:
454; CHECK-NEXT:    ret void
455;
456entry:
457  br label %for.body
458
459for.body:                                         ; preds = %entry, %for.body
460  %iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ]
461  %iv.next = add i8 %iv, 1
462  %zext = zext i8 %iv.next to i16
463  %cmp = icmp sgt i16 %zext, %n
464  br i1 %cmp, label %for.body, label %for.end
465
466for.end:                                          ; preds = %for.body, %entry
467  ret void
468}
469
470define void @sle_constant_rhs(i16 %n.raw, i8 %start) mustprogress {
471; CHECK-LABEL: @sle_constant_rhs(
472; CHECK-NEXT:  entry:
473; CHECK-NEXT:    [[TMP0:%.*]] = trunc i16 254 to i8
474; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
475; CHECK:       for.body:
476; CHECK-NEXT:    [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[START:%.*]], [[ENTRY:%.*]] ]
477; CHECK-NEXT:    [[IV_NEXT]] = add i8 [[IV]], 1
478; CHECK-NEXT:    [[CMP:%.*]] = icmp ule i8 [[IV_NEXT]], [[TMP0]]
479; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
480; CHECK:       for.end:
481; CHECK-NEXT:    ret void
482;
483entry:
484  br label %for.body
485
486for.body:                                         ; preds = %entry, %for.body
487  %iv = phi i8 [ %iv.next, %for.body ], [ %start, %entry ]
488  %iv.next = add i8 %iv, 1
489  %zext = zext i8 %iv.next to i16
490  %cmp = icmp sle i16 %zext, 254
491  br i1 %cmp, label %for.body, label %for.end
492
493for.end:                                          ; preds = %for.body, %entry
494  ret void
495}
496
497define void @sle_non_constant_rhs(i16 %n) mustprogress {
498; CHECK-LABEL: @sle_non_constant_rhs(
499; CHECK-NEXT:  entry:
500; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
501; CHECK:       for.body:
502; CHECK-NEXT:    [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
503; CHECK-NEXT:    [[IV_NEXT]] = add i8 [[IV]], 1
504; CHECK-NEXT:    [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16
505; CHECK-NEXT:    [[CMP:%.*]] = icmp sle i16 [[ZEXT]], [[N:%.*]]
506; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
507; CHECK:       for.end:
508; CHECK-NEXT:    ret void
509;
510entry:
511  br label %for.body
512
513for.body:                                         ; preds = %entry, %for.body
514  %iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ]
515  %iv.next = add i8 %iv, 1
516  %zext = zext i8 %iv.next to i16
517  %cmp = icmp sle i16 %zext, %n
518  br i1 %cmp, label %for.body, label %for.end
519
520for.end:                                          ; preds = %for.body, %entry
521  ret void
522}
523
524define void @sge_constant_rhs(i16 %n.raw, i8 %start) mustprogress {
525; CHECK-LABEL: @sge_constant_rhs(
526; CHECK-NEXT:  entry:
527; CHECK-NEXT:    [[TMP0:%.*]] = trunc i16 254 to i8
528; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
529; CHECK:       for.body:
530; CHECK-NEXT:    [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[START:%.*]], [[ENTRY:%.*]] ]
531; CHECK-NEXT:    [[IV_NEXT]] = add i8 [[IV]], 1
532; CHECK-NEXT:    [[CMP:%.*]] = icmp uge i8 [[IV_NEXT]], [[TMP0]]
533; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
534; CHECK:       for.end:
535; CHECK-NEXT:    ret void
536;
537entry:
538  br label %for.body
539
540for.body:                                         ; preds = %entry, %for.body
541  %iv = phi i8 [ %iv.next, %for.body ], [ %start, %entry ]
542  %iv.next = add i8 %iv, 1
543  %zext = zext i8 %iv.next to i16
544  %cmp = icmp sge i16 %zext, 254
545  br i1 %cmp, label %for.body, label %for.end
546
547for.end:                                          ; preds = %for.body, %entry
548  ret void
549}
550
551define void @sge_non_constant_rhs(i16 %n) mustprogress {
552; CHECK-LABEL: @sge_non_constant_rhs(
553; CHECK-NEXT:  entry:
554; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
555; CHECK:       for.body:
556; CHECK-NEXT:    [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
557; CHECK-NEXT:    [[IV_NEXT]] = add i8 [[IV]], 1
558; CHECK-NEXT:    [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16
559; CHECK-NEXT:    [[CMP:%.*]] = icmp sge i16 [[ZEXT]], [[N:%.*]]
560; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
561; CHECK:       for.end:
562; CHECK-NEXT:    ret void
563;
564entry:
565  br label %for.body
566
567for.body:                                         ; preds = %entry, %for.body
568  %iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ]
569  %iv.next = add i8 %iv, 1
570  %zext = zext i8 %iv.next to i16
571  %cmp = icmp sge i16 %zext, %n
572  br i1 %cmp, label %for.body, label %for.end
573
574for.end:                                          ; preds = %for.body, %entry
575  ret void
576}
577
578define void @ult_constant_rhs(i16 %n.raw, i8 %start) mustprogress {
579; CHECK-LABEL: @ult_constant_rhs(
580; CHECK-NEXT:  entry:
581; CHECK-NEXT:    [[TMP0:%.*]] = trunc i16 254 to i8
582; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
583; CHECK:       for.body:
584; CHECK-NEXT:    [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[START:%.*]], [[ENTRY:%.*]] ]
585; CHECK-NEXT:    [[IV_NEXT]] = add i8 [[IV]], 1
586; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i8 [[IV_NEXT]], [[TMP0]]
587; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
588; CHECK:       for.end:
589; CHECK-NEXT:    ret void
590;
591entry:
592  br label %for.body
593
594for.body:                                         ; preds = %entry, %for.body
595  %iv = phi i8 [ %iv.next, %for.body ], [ %start, %entry ]
596  %iv.next = add i8 %iv, 1
597  %zext = zext i8 %iv.next to i16
598  %cmp = icmp ult i16 %zext, 254
599  br i1 %cmp, label %for.body, label %for.end
600
601for.end:                                          ; preds = %for.body, %entry
602  ret void
603}
604
605define void @ult_non_constant_rhs(i16 %n) mustprogress {
606; CHECK-LABEL: @ult_non_constant_rhs(
607; CHECK-NEXT:  entry:
608; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
609; CHECK:       for.body:
610; CHECK-NEXT:    [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
611; CHECK-NEXT:    [[IV_NEXT]] = add i8 [[IV]], 1
612; CHECK-NEXT:    [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16
613; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i16 [[ZEXT]], [[N:%.*]]
614; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
615; CHECK:       for.end:
616; CHECK-NEXT:    ret void
617;
618entry:
619  br label %for.body
620
621for.body:                                         ; preds = %entry, %for.body
622  %iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ]
623  %iv.next = add i8 %iv, 1
624  %zext = zext i8 %iv.next to i16
625  %cmp = icmp ult i16 %zext, %n
626  br i1 %cmp, label %for.body, label %for.end
627
628for.end:                                          ; preds = %for.body, %entry
629  ret void
630}
631
632define void @ugt_constant_rhs(i16 %n.raw, i8 %start) mustprogress {
633; CHECK-LABEL: @ugt_constant_rhs(
634; CHECK-NEXT:  entry:
635; CHECK-NEXT:    [[TMP0:%.*]] = trunc i16 254 to i8
636; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
637; CHECK:       for.body:
638; CHECK-NEXT:    [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[START:%.*]], [[ENTRY:%.*]] ]
639; CHECK-NEXT:    [[IV_NEXT]] = add i8 [[IV]], 1
640; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i8 [[IV_NEXT]], [[TMP0]]
641; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
642; CHECK:       for.end:
643; CHECK-NEXT:    ret void
644;
645entry:
646  br label %for.body
647
648for.body:                                         ; preds = %entry, %for.body
649  %iv = phi i8 [ %iv.next, %for.body ], [ %start, %entry ]
650  %iv.next = add i8 %iv, 1
651  %zext = zext i8 %iv.next to i16
652  %cmp = icmp ugt i16 %zext, 254
653  br i1 %cmp, label %for.body, label %for.end
654
655for.end:                                          ; preds = %for.body, %entry
656  ret void
657}
658
659define void @ugt_neg_non_loop(i16 %n.raw, i8 %start) mustprogress {
660; CHECK-LABEL: @ugt_neg_non_loop(
661; CHECK-NEXT:  entry:
662; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
663; CHECK:       for.body:
664; CHECK-NEXT:    [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[START:%.*]], [[ENTRY:%.*]] ]
665; CHECK-NEXT:    [[IV_NEXT]] = add i8 [[IV]], 1
666; CHECK-NEXT:    [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16
667; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i16 [[ZEXT]], -2
668; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
669; CHECK:       for.end:
670; CHECK-NEXT:    ret void
671;
672entry:
673  br label %for.body
674
675for.body:                                         ; preds = %entry, %for.body
676  %iv = phi i8 [ %iv.next, %for.body ], [ %start, %entry ]
677  %iv.next = add i8 %iv, 1
678  %zext = zext i8 %iv.next to i16
679  %cmp = icmp ugt i16 %zext, -2
680  br i1 %cmp, label %for.body, label %for.end
681
682for.end:                                          ; preds = %for.body, %entry
683  ret void
684}
685
686define void @ugt_non_constant_rhs(i16 %n) mustprogress {
687; CHECK-LABEL: @ugt_non_constant_rhs(
688; CHECK-NEXT:  entry:
689; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
690; CHECK:       for.body:
691; CHECK-NEXT:    [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
692; CHECK-NEXT:    [[IV_NEXT]] = add i8 [[IV]], 1
693; CHECK-NEXT:    [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16
694; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i16 [[ZEXT]], [[N:%.*]]
695; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
696; CHECK:       for.end:
697; CHECK-NEXT:    ret void
698;
699entry:
700  br label %for.body
701
702for.body:                                         ; preds = %entry, %for.body
703  %iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ]
704  %iv.next = add i8 %iv, 1
705  %zext = zext i8 %iv.next to i16
706  %cmp = icmp ugt i16 %zext, %n
707  br i1 %cmp, label %for.body, label %for.end
708
709for.end:                                          ; preds = %for.body, %entry
710  ret void
711}
712
713define void @ule_constant_rhs(i16 %n.raw, i8 %start) mustprogress {
714; CHECK-LABEL: @ule_constant_rhs(
715; CHECK-NEXT:  entry:
716; CHECK-NEXT:    [[TMP0:%.*]] = trunc i16 254 to i8
717; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
718; CHECK:       for.body:
719; CHECK-NEXT:    [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[START:%.*]], [[ENTRY:%.*]] ]
720; CHECK-NEXT:    [[IV_NEXT]] = add i8 [[IV]], 1
721; CHECK-NEXT:    [[CMP:%.*]] = icmp ule i8 [[IV_NEXT]], [[TMP0]]
722; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
723; CHECK:       for.end:
724; CHECK-NEXT:    ret void
725;
726entry:
727  br label %for.body
728
729for.body:                                         ; preds = %entry, %for.body
730  %iv = phi i8 [ %iv.next, %for.body ], [ %start, %entry ]
731  %iv.next = add i8 %iv, 1
732  %zext = zext i8 %iv.next to i16
733  %cmp = icmp ule i16 %zext, 254
734  br i1 %cmp, label %for.body, label %for.end
735
736for.end:                                          ; preds = %for.body, %entry
737  ret void
738}
739
740define void @ule_non_constant_rhs(i16 %n) mustprogress {
741; CHECK-LABEL: @ule_non_constant_rhs(
742; CHECK-NEXT:  entry:
743; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
744; CHECK:       for.body:
745; CHECK-NEXT:    [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
746; CHECK-NEXT:    [[IV_NEXT]] = add i8 [[IV]], 1
747; CHECK-NEXT:    [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16
748; CHECK-NEXT:    [[CMP:%.*]] = icmp ule i16 [[ZEXT]], [[N:%.*]]
749; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
750; CHECK:       for.end:
751; CHECK-NEXT:    ret void
752;
753entry:
754  br label %for.body
755
756for.body:                                         ; preds = %entry, %for.body
757  %iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ]
758  %iv.next = add i8 %iv, 1
759  %zext = zext i8 %iv.next to i16
760  %cmp = icmp ule i16 %zext, %n
761  br i1 %cmp, label %for.body, label %for.end
762
763for.end:                                          ; preds = %for.body, %entry
764  ret void
765}
766
767define void @uge_constant_rhs(i16 %n.raw, i8 %start) mustprogress {
768; CHECK-LABEL: @uge_constant_rhs(
769; CHECK-NEXT:  entry:
770; CHECK-NEXT:    [[TMP0:%.*]] = trunc i16 254 to i8
771; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
772; CHECK:       for.body:
773; CHECK-NEXT:    [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[START:%.*]], [[ENTRY:%.*]] ]
774; CHECK-NEXT:    [[IV_NEXT]] = add i8 [[IV]], 1
775; CHECK-NEXT:    [[CMP:%.*]] = icmp uge i8 [[IV_NEXT]], [[TMP0]]
776; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
777; CHECK:       for.end:
778; CHECK-NEXT:    ret void
779;
780entry:
781  br label %for.body
782
783for.body:                                         ; preds = %entry, %for.body
784  %iv = phi i8 [ %iv.next, %for.body ], [ %start, %entry ]
785  %iv.next = add i8 %iv, 1
786  %zext = zext i8 %iv.next to i16
787  %cmp = icmp uge i16 %zext, 254
788  br i1 %cmp, label %for.body, label %for.end
789
790for.end:                                          ; preds = %for.body, %entry
791  ret void
792}
793
794define void @uge_non_constant_rhs(i16 %n) mustprogress {
795; CHECK-LABEL: @uge_non_constant_rhs(
796; CHECK-NEXT:  entry:
797; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
798; CHECK:       for.body:
799; CHECK-NEXT:    [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
800; CHECK-NEXT:    [[IV_NEXT]] = add i8 [[IV]], 1
801; CHECK-NEXT:    [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16
802; CHECK-NEXT:    [[CMP:%.*]] = icmp uge i16 [[ZEXT]], [[N:%.*]]
803; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
804; CHECK:       for.end:
805; CHECK-NEXT:    ret void
806;
807entry:
808  br label %for.body
809
810for.body:                                         ; preds = %entry, %for.body
811  %iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ]
812  %iv.next = add i8 %iv, 1
813  %zext = zext i8 %iv.next to i16
814  %cmp = icmp uge i16 %zext, %n
815  br i1 %cmp, label %for.body, label %for.end
816
817for.end:                                          ; preds = %for.body, %entry
818  ret void
819}
820
821; Show that these transformatios also work with inverted operands
822; We only both to do this with slt/ult, but it applies to all predicates.
823
824define void @slt_constant_lhs(i16 %n.raw, i8 %start) mustprogress {
825; CHECK-LABEL: @slt_constant_lhs(
826; CHECK-NEXT:  entry:
827; CHECK-NEXT:    [[TMP0:%.*]] = trunc i16 254 to i8
828; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
829; CHECK:       for.body:
830; CHECK-NEXT:    [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[START:%.*]], [[ENTRY:%.*]] ]
831; CHECK-NEXT:    [[IV_NEXT]] = add i8 [[IV]], 1
832; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i8 [[TMP0]], [[IV_NEXT]]
833; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
834; CHECK:       for.end:
835; CHECK-NEXT:    ret void
836;
837entry:
838  br label %for.body
839
840for.body:                                         ; preds = %entry, %for.body
841  %iv = phi i8 [ %iv.next, %for.body ], [ %start, %entry ]
842  %iv.next = add i8 %iv, 1
843  %zext = zext i8 %iv.next to i16
844  %cmp = icmp slt i16 254, %zext
845  br i1 %cmp, label %for.body, label %for.end
846
847for.end:                                          ; preds = %for.body, %entry
848  ret void
849}
850
851define void @slt_non_constant_lhs(i16 %n) mustprogress {
852; CHECK-LABEL: @slt_non_constant_lhs(
853; CHECK-NEXT:  entry:
854; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
855; CHECK:       for.body:
856; CHECK-NEXT:    [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
857; CHECK-NEXT:    [[IV_NEXT]] = add i8 [[IV]], 1
858; CHECK-NEXT:    [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16
859; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i16 [[N:%.*]], [[ZEXT]]
860; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
861; CHECK:       for.end:
862; CHECK-NEXT:    ret void
863;
864entry:
865  br label %for.body
866
867for.body:                                         ; preds = %entry, %for.body
868  %iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ]
869  %iv.next = add i8 %iv, 1
870  %zext = zext i8 %iv.next to i16
871  %cmp = icmp slt i16 %n, %zext
872  br i1 %cmp, label %for.body, label %for.end
873
874for.end:                                          ; preds = %for.body, %entry
875  ret void
876}
877
878define void @ult_constant_lhs(i16 %n.raw, i8 %start) mustprogress {
879; CHECK-LABEL: @ult_constant_lhs(
880; CHECK-NEXT:  entry:
881; CHECK-NEXT:    [[TMP0:%.*]] = trunc i16 254 to i8
882; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
883; CHECK:       for.body:
884; CHECK-NEXT:    [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[START:%.*]], [[ENTRY:%.*]] ]
885; CHECK-NEXT:    [[IV_NEXT]] = add i8 [[IV]], 1
886; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i8 [[TMP0]], [[IV_NEXT]]
887; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
888; CHECK:       for.end:
889; CHECK-NEXT:    ret void
890;
891entry:
892  br label %for.body
893
894for.body:                                         ; preds = %entry, %for.body
895  %iv = phi i8 [ %iv.next, %for.body ], [ %start, %entry ]
896  %iv.next = add i8 %iv, 1
897  %zext = zext i8 %iv.next to i16
898  %cmp = icmp ult i16 254, %zext
899  br i1 %cmp, label %for.body, label %for.end
900
901for.end:                                          ; preds = %for.body, %entry
902  ret void
903}
904
905define void @ult_non_constant_lhs(i16 %n) mustprogress {
906; CHECK-LABEL: @ult_non_constant_lhs(
907; CHECK-NEXT:  entry:
908; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
909; CHECK:       for.body:
910; CHECK-NEXT:    [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
911; CHECK-NEXT:    [[IV_NEXT]] = add i8 [[IV]], 1
912; CHECK-NEXT:    [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16
913; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i16 [[N:%.*]], [[ZEXT]]
914; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
915; CHECK:       for.end:
916; CHECK-NEXT:    ret void
917;
918entry:
919  br label %for.body
920
921for.body:                                         ; preds = %entry, %for.body
922  %iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ]
923  %iv.next = add i8 %iv, 1
924  %zext = zext i8 %iv.next to i16
925  %cmp = icmp ult i16 %n, %zext
926  br i1 %cmp, label %for.body, label %for.end
927
928for.end:                                          ; preds = %for.body, %entry
929  ret void
930}
931
932define i16 @ult_multiuse_profit(i16 %n.raw, i8 %start) mustprogress {
933; CHECK-LABEL: @ult_multiuse_profit(
934; CHECK-NEXT:  entry:
935; CHECK-NEXT:    [[TMP0:%.*]] = add i8 [[START:%.*]], 1
936; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[TMP0]] to i16
937; CHECK-NEXT:    [[TMP2:%.*]] = trunc i16 254 to i8
938; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
939; CHECK:       for.body:
940; CHECK-NEXT:    [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[START]], [[ENTRY:%.*]] ]
941; CHECK-NEXT:    [[IV_NEXT]] = add i8 [[IV]], 1
942; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i8 [[IV_NEXT]], [[TMP2]]
943; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
944; CHECK:       for.end:
945; CHECK-NEXT:    [[UMAX:%.*]] = call i16 @llvm.umax.i16(i16 [[TMP1]], i16 254)
946; CHECK-NEXT:    ret i16 [[UMAX]]
947;
948entry:
949  br label %for.body
950
951for.body:                                         ; preds = %entry, %for.body
952  %iv = phi i8 [ %iv.next, %for.body ], [ %start, %entry ]
953  %iv.next = add i8 %iv, 1
954  %zext = zext i8 %iv.next to i16
955  %cmp = icmp ult i16 %zext, 254
956  br i1 %cmp, label %for.body, label %for.end
957
958for.end:                                          ; preds = %for.body, %entry
959  ret i16 %zext
960}
961
962define i16 @ult_multiuse_profit2(i16 %n.raw, i8 %start) mustprogress {
963; CHECK-LABEL: @ult_multiuse_profit2(
964; CHECK-NEXT:  entry:
965; CHECK-NEXT:    [[TMP0:%.*]] = trunc i16 254 to i8
966; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
967; CHECK:       for.body:
968; CHECK-NEXT:    [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[START:%.*]], [[ENTRY:%.*]] ]
969; CHECK-NEXT:    [[IV2:%.*]] = phi i16 [ [[ZEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY]] ]
970; CHECK-NEXT:    [[IV_NEXT]] = add i8 [[IV]], 1
971; CHECK-NEXT:    [[ZEXT]] = zext i8 [[IV_NEXT]] to i16
972; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i8 [[IV_NEXT]], [[TMP0]]
973; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
974; CHECK:       for.end:
975; CHECK-NEXT:    [[IV2_LCSSA:%.*]] = phi i16 [ [[IV2]], [[FOR_BODY]] ]
976; CHECK-NEXT:    ret i16 [[IV2_LCSSA]]
977;
978entry:
979  br label %for.body
980
981for.body:                                         ; preds = %entry, %for.body
982  %iv = phi i8 [ %iv.next, %for.body ], [ %start, %entry ]
983  %iv2 = phi i16 [%zext, %for.body], [0, %entry]
984  %iv.next = add i8 %iv, 1
985  %zext = zext i8 %iv.next to i16
986  %cmp = icmp ult i16 %zext, 254
987  br i1 %cmp, label %for.body, label %for.end
988
989for.end:                                          ; preds = %for.body, %entry
990  ret i16 %iv2
991}
992
993define void @slt_restricted_rhs(i16 %n.raw) mustprogress {
994; CHECK-LABEL: @slt_restricted_rhs(
995; CHECK-NEXT:  entry:
996; CHECK-NEXT:    [[N:%.*]] = and i16 [[N_RAW:%.*]], 255
997; CHECK-NEXT:    [[SMAX:%.*]] = call i16 @llvm.smax.i16(i16 [[N]], i16 1)
998; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
999; CHECK:       for.body:
1000; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i16 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
1001; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i16 [[INDVARS_IV]], 1
1002; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i16 [[INDVARS_IV_NEXT]], [[SMAX]]
1003; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_END:%.*]]
1004; CHECK:       for.end:
1005; CHECK-NEXT:    ret void
1006;
1007entry:
1008  %n = and i16 %n.raw, 255
1009  br label %for.body
1010
1011for.body:                                         ; preds = %entry, %for.body
1012  %iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ]
1013  %iv.next = add i8 %iv, 1
1014  %zext = zext i8 %iv.next to i16
1015  %cmp = icmp slt i16 %zext, %n
1016  br i1 %cmp, label %for.body, label %for.end
1017
1018for.end:                                          ; preds = %for.body, %entry
1019  ret void
1020}
1021
1022define void @slt_guarded_rhs(i16 %n) mustprogress {
1023; CHECK-LABEL: @slt_guarded_rhs(
1024; CHECK-NEXT:  entry:
1025; CHECK-NEXT:    [[IN_RANGE:%.*]] = icmp ult i16 [[N:%.*]], 256
1026; CHECK-NEXT:    br i1 [[IN_RANGE]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]]
1027; CHECK:       for.body.preheader:
1028; CHECK-NEXT:    [[TMP0:%.*]] = trunc i16 [[N]] to i8
1029; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
1030; CHECK:       for.body:
1031; CHECK-NEXT:    [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
1032; CHECK-NEXT:    [[IV_NEXT]] = add nuw i8 [[IV]], 1
1033; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i8 [[IV_NEXT]], [[TMP0]]
1034; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]]
1035; CHECK:       for.end.loopexit:
1036; CHECK-NEXT:    br label [[FOR_END]]
1037; CHECK:       for.end:
1038; CHECK-NEXT:    ret void
1039;
1040entry:
1041  %in_range = icmp ult i16 %n, 256
1042  br i1 %in_range, label %for.body, label %for.end
1043
1044for.body:                                         ; preds = %entry, %for.body
1045  %iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ]
1046  %iv.next = add i8 %iv, 1
1047  %zext = zext i8 %iv.next to i16
1048  %cmp = icmp slt i16 %zext, %n
1049  br i1 %cmp, label %for.body, label %for.end
1050
1051for.end:                                          ; preds = %for.body, %entry
1052  ret void
1053}
1054
1055define i8 @test_drop_icmp_samesign(i1 %cond, i32 range(i32 0, 32) %x) {
1056; CHECK-LABEL: @test_drop_icmp_samesign(
1057; CHECK-NEXT:  entry:
1058; CHECK-NEXT:    br i1 [[COND:%.*]], label [[FOR_BODY_PREHEADER:%.*]], label [[ELSE:%.*]]
1059; CHECK:       for.body.preheader:
1060; CHECK-NEXT:    [[TMP0:%.*]] = trunc i32 [[X:%.*]] to i8
1061; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
1062; CHECK:       else:
1063; CHECK-NEXT:    [[CALL1:%.*]] = call i8 @callee()
1064; CHECK-NEXT:    br label [[EXIT:%.*]]
1065; CHECK:       for.body:
1066; CHECK-NEXT:    [[CALL2:%.*]] = call i8 @callee()
1067; CHECK-NEXT:    [[COND2:%.*]] = icmp ugt i8 [[TMP0]], [[CALL2]]
1068; CHECK-NEXT:    br i1 [[COND2]], label [[FOR_BODY]], label [[EXIT_LOOPEXIT:%.*]]
1069; CHECK:       exit.loopexit:
1070; CHECK-NEXT:    [[CALL2_LCSSA:%.*]] = phi i8 [ [[CALL2]], [[FOR_BODY]] ]
1071; CHECK-NEXT:    br label [[EXIT]]
1072; CHECK:       exit:
1073; CHECK-NEXT:    [[RES:%.*]] = phi i8 [ [[CALL1]], [[ELSE]] ], [ [[CALL2_LCSSA]], [[EXIT_LOOPEXIT]] ]
1074; CHECK-NEXT:    ret i8 [[RES]]
1075;
1076entry:
1077  br i1 %cond, label %for.body, label %else
1078
1079else:
1080  %call1 = call i8 @callee()
1081  br label %exit
1082
1083for.body:
1084  %call2 = call i8 @callee()
1085  %ext = zext i8 %call2 to i32
1086  %cond2 = icmp samesign ugt i32 %x, %ext
1087  br i1 %cond2, label %for.body, label %exit
1088
1089exit:
1090  %res = phi i8 [ %call1, %else ], [ %call2, %for.body ]
1091  ret i8 %res
1092}
1093
1094declare i8 @callee()
1095