• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -S -indvars -indvars-predicate-loops=0 %s | FileCheck %s
3target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
4target triple = "x86_64-unknown-linux-gnu"
5
6define void @test1(i64 %start) {
7; CHECK-LABEL: @test1(
8; CHECK-NEXT:  entry:
9; CHECK-NEXT:    br label [[LOOP:%.*]]
10; CHECK:       loop:
11; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i64 [[START:%.*]], -1
12; CHECK-NEXT:    br i1 [[CMP1]], label [[FOR_END:%.*]], label [[LOOP]]
13; CHECK:       for.end:
14; CHECK-NEXT:    ret void
15;
16entry:
17  br label %loop
18
19loop:
20  %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %loop ]
21  %indvars.iv.next = add nsw i64 %indvars.iv, 1
22  %cmp1 = icmp slt i64 %indvars.iv, -1
23  br i1 %cmp1, label %for.end, label %loop
24
25for.end:                                          ; preds = %if.end, %entry
26  ret void
27}
28
29define void @test2(i64 %start) {
30; CHECK-LABEL: @test2(
31; CHECK-NEXT:  entry:
32; CHECK-NEXT:    br label [[LOOP:%.*]]
33; CHECK:       loop:
34; CHECK-NEXT:    [[CMP1:%.*]] = icmp sle i64 [[START:%.*]], -1
35; CHECK-NEXT:    br i1 [[CMP1]], label [[FOR_END:%.*]], label [[LOOP]]
36; CHECK:       for.end:
37; CHECK-NEXT:    ret void
38;
39entry:
40  br label %loop
41
42loop:
43  %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %loop ]
44  %indvars.iv.next = add nsw i64 %indvars.iv, 1
45  %cmp1 = icmp sle i64 %indvars.iv, -1
46  br i1 %cmp1, label %for.end, label %loop
47
48for.end:                                          ; preds = %if.end, %entry
49  ret void
50}
51
52; As long as the test dominates the backedge, we're good
53define void @test3(i64 %start) {
54; CHECK-LABEL: @test3(
55; CHECK-NEXT:  entry:
56; CHECK-NEXT:    br label [[LOOP:%.*]]
57; CHECK:       loop:
58; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
59; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
60; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT]], 25
61; CHECK-NEXT:    br i1 [[CMP]], label [[BACKEDGE]], label [[FOR_END:%.*]]
62; CHECK:       backedge:
63; CHECK-NEXT:    call void @foo()
64; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i64 [[START]], -1
65; CHECK-NEXT:    br i1 [[CMP1]], label [[FOR_END]], label [[LOOP]]
66; CHECK:       for.end:
67; CHECK-NEXT:    ret void
68;
69entry:
70  br label %loop
71
72loop:
73  %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %backedge ]
74  %indvars.iv.next = add nsw i64 %indvars.iv, 1
75  %cmp = icmp eq i64 %indvars.iv.next, 25
76  br i1 %cmp, label %backedge, label %for.end
77
78backedge:
79  ; prevent flattening, needed to make sure we're testing what we intend
80  call void @foo()
81  %cmp1 = icmp slt i64 %indvars.iv, -1
82  br i1 %cmp1, label %for.end, label %loop
83
84for.end:                                          ; preds = %if.end, %entry
85  ret void
86}
87
88define void @test4(i64 %start) {
89; CHECK-LABEL: @test4(
90; CHECK-NEXT:  entry:
91; CHECK-NEXT:    br label [[LOOP:%.*]]
92; CHECK:       loop:
93; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
94; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
95; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT]], 25
96; CHECK-NEXT:    br i1 [[CMP]], label [[BACKEDGE]], label [[FOR_END:%.*]]
97; CHECK:       backedge:
98; CHECK-NEXT:    call void @foo()
99; CHECK-NEXT:    [[CMP1:%.*]] = icmp sgt i64 [[START]], -1
100; CHECK-NEXT:    br i1 [[CMP1]], label [[LOOP]], label [[FOR_END]]
101; CHECK:       for.end:
102; CHECK-NEXT:    ret void
103;
104entry:
105  br label %loop
106
107loop:
108  %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %backedge ]
109  %indvars.iv.next = add nsw i64 %indvars.iv, 1
110  %cmp = icmp eq i64 %indvars.iv.next, 25
111  br i1 %cmp, label %backedge, label %for.end
112
113backedge:
114  ; prevent flattening, needed to make sure we're testing what we intend
115  call void @foo()
116  %cmp1 = icmp sgt i64 %indvars.iv, -1
117  br i1 %cmp1, label %loop, label %for.end
118
119for.end:                                          ; preds = %if.end, %entry
120  ret void
121}
122
123define void @test5(i64 %start) {
124; CHECK-LABEL: @test5(
125; CHECK-NEXT:  entry:
126; CHECK-NEXT:    br label [[LOOP:%.*]]
127; CHECK:       loop:
128; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
129; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw i64 [[INDVARS_IV]], 1
130; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT]], 25
131; CHECK-NEXT:    br i1 [[CMP]], label [[BACKEDGE]], label [[FOR_END:%.*]]
132; CHECK:       backedge:
133; CHECK-NEXT:    call void @foo()
134; CHECK-NEXT:    [[CMP1:%.*]] = icmp ugt i64 [[START]], 100
135; CHECK-NEXT:    br i1 [[CMP1]], label [[LOOP]], label [[FOR_END]]
136; CHECK:       for.end:
137; CHECK-NEXT:    ret void
138;
139entry:
140  br label %loop
141
142loop:
143  %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %backedge ]
144  %indvars.iv.next = add nuw i64 %indvars.iv, 1
145  %cmp = icmp eq i64 %indvars.iv.next, 25
146  br i1 %cmp, label %backedge, label %for.end
147
148backedge:
149  ; prevent flattening, needed to make sure we're testing what we intend
150  call void @foo()
151  %cmp1 = icmp ugt i64 %indvars.iv, 100
152  br i1 %cmp1, label %loop, label %for.end
153
154for.end:                                          ; preds = %if.end, %entry
155  ret void
156}
157
158define void @test6(i64 %start) {
159; CHECK-LABEL: @test6(
160; CHECK-NEXT:  entry:
161; CHECK-NEXT:    br label [[LOOP:%.*]]
162; CHECK:       loop:
163; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
164; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw i64 [[INDVARS_IV]], 1
165; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT]], 25
166; CHECK-NEXT:    br i1 [[CMP]], label [[BACKEDGE]], label [[FOR_END:%.*]]
167; CHECK:       backedge:
168; CHECK-NEXT:    call void @foo()
169; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i64 [[START]], 100
170; CHECK-NEXT:    br i1 [[CMP1]], label [[FOR_END]], label [[LOOP]]
171; CHECK:       for.end:
172; CHECK-NEXT:    ret void
173;
174entry:
175  br label %loop
176
177loop:
178  %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %backedge ]
179  %indvars.iv.next = add nuw i64 %indvars.iv, 1
180  %cmp = icmp eq i64 %indvars.iv.next, 25
181  br i1 %cmp, label %backedge, label %for.end
182
183backedge:
184  ; prevent flattening, needed to make sure we're testing what we intend
185  call void @foo()
186  %cmp1 = icmp ult i64 %indvars.iv, 100
187  br i1 %cmp1, label %for.end, label %loop
188
189for.end:                                          ; preds = %if.end, %entry
190  ret void
191}
192
193define void @test7(i64 %start, i64* %inc_ptr) {
194; CHECK-LABEL: @test7(
195; CHECK-NEXT:  entry:
196; CHECK-NEXT:    [[INC:%.*]] = load i64, i64* [[INC_PTR:%.*]], !range !0
197; CHECK-NEXT:    [[OK:%.*]] = icmp sge i64 [[INC]], 0
198; CHECK-NEXT:    br i1 [[OK]], label [[LOOP_PREHEADER:%.*]], label [[FOR_END:%.*]]
199; CHECK:       loop.preheader:
200; CHECK-NEXT:    br label [[LOOP:%.*]]
201; CHECK:       loop:
202; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i64 [[START:%.*]], -1
203; CHECK-NEXT:    br i1 [[CMP1]], label [[FOR_END_LOOPEXIT:%.*]], label [[LOOP]]
204; CHECK:       for.end.loopexit:
205; CHECK-NEXT:    br label [[FOR_END]]
206; CHECK:       for.end:
207; CHECK-NEXT:    ret void
208;
209entry:
210  %inc = load i64, i64* %inc_ptr, !range !0
211  %ok = icmp sge i64 %inc, 0
212  br i1 %ok, label %loop, label %for.end
213
214loop:
215  %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %loop ]
216  %indvars.iv.next = add nsw i64 %indvars.iv, %inc
217  %cmp1 = icmp slt i64 %indvars.iv, -1
218  br i1 %cmp1, label %for.end, label %loop
219
220for.end:                                          ; preds = %if.end, %entry
221  ret void
222}
223
224; Negative test - we can't show that the internal branch executes, so we can't
225; fold the test to a loop invariant one.
226define void @test1_neg(i64 %start) {
227; CHECK-LABEL: @test1_neg(
228; CHECK-NEXT:  entry:
229; CHECK-NEXT:    br label [[LOOP:%.*]]
230; CHECK:       loop:
231; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
232; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
233; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT]], 25
234; CHECK-NEXT:    br i1 [[CMP]], label [[BACKEDGE]], label [[SKIP:%.*]]
235; CHECK:       skip:
236; CHECK-NEXT:    call void @foo()
237; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i64 [[INDVARS_IV]], -1
238; CHECK-NEXT:    br i1 [[CMP1]], label [[FOR_END:%.*]], label [[BACKEDGE]]
239; CHECK:       backedge:
240; CHECK-NEXT:    call void @foo()
241; CHECK-NEXT:    br label [[LOOP]]
242; CHECK:       for.end:
243; CHECK-NEXT:    ret void
244;
245entry:
246  br label %loop
247
248loop:
249  %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %backedge ]
250  %indvars.iv.next = add nsw i64 %indvars.iv, 1
251  %cmp = icmp eq i64 %indvars.iv.next, 25
252  br i1 %cmp, label %backedge, label %skip
253skip:
254  ; prevent flattening, needed to make sure we're testing what we intend
255  call void @foo()
256  %cmp1 = icmp slt i64 %indvars.iv, -1
257  br i1 %cmp1, label %for.end, label %backedge
258backedge:
259  ; prevent flattening, needed to make sure we're testing what we intend
260  call void @foo()
261  br label %loop
262
263for.end:                                          ; preds = %if.end, %entry
264  ret void
265}
266
267; Slightly subtle version of @test4 where the icmp dominates the backedge,
268; but the exit branch doesn't.
269define void @test2_neg(i64 %start) {
270; CHECK-LABEL: @test2_neg(
271; CHECK-NEXT:  entry:
272; CHECK-NEXT:    br label [[LOOP:%.*]]
273; CHECK:       loop:
274; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
275; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
276; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT]], 25
277; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i64 [[INDVARS_IV]], -1
278; CHECK-NEXT:    br i1 [[CMP]], label [[BACKEDGE]], label [[SKIP:%.*]]
279; CHECK:       skip:
280; CHECK-NEXT:    call void @foo()
281; CHECK-NEXT:    br i1 [[CMP1]], label [[FOR_END:%.*]], label [[BACKEDGE]]
282; CHECK:       backedge:
283; CHECK-NEXT:    call void @foo()
284; CHECK-NEXT:    br label [[LOOP]]
285; CHECK:       for.end:
286; CHECK-NEXT:    ret void
287;
288entry:
289  br label %loop
290
291loop:
292  %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %backedge ]
293  %indvars.iv.next = add nsw i64 %indvars.iv, 1
294  %cmp = icmp eq i64 %indvars.iv.next, 25
295  %cmp1 = icmp slt i64 %indvars.iv, -1
296  br i1 %cmp, label %backedge, label %skip
297skip:
298  ; prevent flattening, needed to make sure we're testing what we intend
299  call void @foo()
300  br i1 %cmp1, label %for.end, label %backedge
301backedge:
302  ; prevent flattening, needed to make sure we're testing what we intend
303  call void @foo()
304  br label %loop
305
306for.end:                                          ; preds = %if.end, %entry
307  ret void
308}
309
310; The branch has to exit the loop if the condition is true
311define void @test3_neg(i64 %start) {
312; CHECK-LABEL: @test3_neg(
313; CHECK-NEXT:  entry:
314; CHECK-NEXT:    [[TMP0:%.*]] = icmp sgt i64 [[START:%.*]], -1
315; CHECK-NEXT:    [[SMAX:%.*]] = select i1 [[TMP0]], i64 [[START]], i64 -1
316; CHECK-NEXT:    [[TMP1:%.*]] = add i64 [[SMAX]], 1
317; CHECK-NEXT:    br label [[LOOP:%.*]]
318; CHECK:       loop:
319; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[START]], [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
320; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add i64 [[INDVARS_IV]], 1
321; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[TMP1]]
322; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[FOR_END:%.*]]
323; CHECK:       for.end:
324; CHECK-NEXT:    ret void
325;
326entry:
327  br label %loop
328
329loop:
330  %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %loop ]
331  %indvars.iv.next = add nsw i64 %indvars.iv, 1
332  %cmp1 = icmp slt i64 %indvars.iv, -1
333  br i1 %cmp1, label %loop, label %for.end
334
335for.end:                                          ; preds = %if.end, %entry
336  ret void
337}
338
339define void @test4_neg(i64 %start) {
340; CHECK-LABEL: @test4_neg(
341; CHECK-NEXT:  entry:
342; CHECK-NEXT:    [[TMP0:%.*]] = icmp sgt i64 [[START:%.*]], 0
343; CHECK-NEXT:    [[SMAX:%.*]] = select i1 [[TMP0]], i64 [[START]], i64 0
344; CHECK-NEXT:    [[TMP1:%.*]] = add nuw i64 [[SMAX]], 1
345; CHECK-NEXT:    br label [[LOOP:%.*]]
346; CHECK:       loop:
347; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[START]], [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
348; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add i64 [[INDVARS_IV]], 1
349; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT]], 25
350; CHECK-NEXT:    br i1 [[CMP]], label [[BACKEDGE]], label [[FOR_END:%.*]]
351; CHECK:       backedge:
352; CHECK-NEXT:    call void @foo()
353; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT]], [[TMP1]]
354; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_END]], label [[LOOP]]
355; CHECK:       for.end:
356; CHECK-NEXT:    ret void
357;
358entry:
359  br label %loop
360
361loop:
362  %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %backedge ]
363  %indvars.iv.next = add nsw i64 %indvars.iv, 1
364  %cmp = icmp eq i64 %indvars.iv.next, 25
365  br i1 %cmp, label %backedge, label %for.end
366
367backedge:
368  ; prevent flattening, needed to make sure we're testing what we intend
369  call void @foo()
370  %cmp1 = icmp sgt i64 %indvars.iv, -1
371
372; %cmp1 can be made loop invariant only if the branch below goes to
373; %the header when %cmp1 is true.
374  br i1 %cmp1, label %for.end, label %loop
375
376for.end:                                          ; preds = %if.end, %entry
377  ret void
378}
379
380define void @test5_neg(i64 %start, i64 %inc) {
381; CHECK-LABEL: @test5_neg(
382; CHECK-NEXT:  entry:
383; CHECK-NEXT:    br label [[LOOP:%.*]]
384; CHECK:       loop:
385; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
386; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], [[INC:%.*]]
387; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i64 [[INDVARS_IV]], -1
388; CHECK-NEXT:    br i1 [[CMP1]], label [[FOR_END:%.*]], label [[LOOP]]
389; CHECK:       for.end:
390; CHECK-NEXT:    ret void
391;
392entry:
393  br label %loop
394
395loop:
396  %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %loop ]
397  %indvars.iv.next = add nsw i64 %indvars.iv, %inc
398  %cmp1 = icmp slt i64 %indvars.iv, -1
399  br i1 %cmp1, label %for.end, label %loop
400
401for.end:                                          ; preds = %if.end, %entry
402  ret void
403}
404
405define void @test8(i64 %start, i64* %inc_ptr) {
406; CHECK-LABEL: @test8(
407; CHECK-NEXT:  entry:
408; CHECK-NEXT:    [[INC:%.*]] = load i64, i64* [[INC_PTR:%.*]], !range !1
409; CHECK-NEXT:    [[OK:%.*]] = icmp sge i64 [[INC]], 0
410; CHECK-NEXT:    br i1 [[OK]], label [[LOOP_PREHEADER:%.*]], label [[FOR_END:%.*]]
411; CHECK:       loop.preheader:
412; CHECK-NEXT:    br label [[LOOP:%.*]]
413; CHECK:       loop:
414; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ], [ [[START:%.*]], [[LOOP_PREHEADER]] ]
415; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], [[INC]]
416; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i64 [[INDVARS_IV]], -1
417; CHECK-NEXT:    br i1 [[CMP1]], label [[FOR_END_LOOPEXIT:%.*]], label [[LOOP]]
418; CHECK:       for.end.loopexit:
419; CHECK-NEXT:    br label [[FOR_END]]
420; CHECK:       for.end:
421; CHECK-NEXT:    ret void
422;
423entry:
424  %inc = load i64, i64* %inc_ptr, !range !1
425  %ok = icmp sge i64 %inc, 0
426  br i1 %ok, label %loop, label %for.end
427
428loop:
429  %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %loop ]
430  %indvars.iv.next = add nsw i64 %indvars.iv, %inc
431  %cmp1 = icmp slt i64 %indvars.iv, -1
432  br i1 %cmp1, label %for.end, label %loop
433
434for.end:                                          ; preds = %if.end, %entry
435  ret void
436}
437
438; check to handle loops without preheaders, but invariant operands
439; (we handle this today by inserting a preheader)
440define void @test9(i1 %cnd, i64 %start) {
441; CHECK-LABEL: @test9(
442; CHECK-NEXT:  entry:
443; CHECK-NEXT:    br i1 [[CND:%.*]], label [[ENTRY1:%.*]], label [[ENTRY2:%.*]]
444; CHECK:       entry1:
445; CHECK-NEXT:    br label [[LOOP_PREHEADER:%.*]]
446; CHECK:       entry2:
447; CHECK-NEXT:    br label [[LOOP_PREHEADER]]
448; CHECK:       loop.preheader:
449; CHECK-NEXT:    br label [[LOOP:%.*]]
450; CHECK:       loop:
451; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i64 [[START:%.*]], -1
452; CHECK-NEXT:    br i1 [[CMP1]], label [[FOR_END:%.*]], label [[LOOP]]
453; CHECK:       for.end:
454; CHECK-NEXT:    ret void
455;
456entry:
457  br i1 %cnd, label %entry1, label %entry2
458entry1:
459  br label %loop
460entry2:
461  br label %loop
462loop:
463  %indvars.iv = phi i64 [ %start, %entry1 ],[ %start, %entry2 ], [ %indvars.iv.next, %loop ]
464  %indvars.iv.next = add nsw i64 %indvars.iv, 1
465  %cmp1 = icmp slt i64 %indvars.iv, -1
466  br i1 %cmp1, label %for.end, label %loop
467
468for.end:                                          ; preds = %if.end, %entry
469  ret void
470}
471
472declare void @use(i1 %x)
473
474; check that we handle conditions with loop invariant operands which
475; *aren't* in the header - this is a very rare and fragile case where
476; we have a "loop" which is known to run exactly one iteration but
477; haven't yet simplified the uses of the IV
478define void @test10() {
479; CHECK-LABEL: @test10(
480; CHECK-NEXT:  entry:
481; CHECK-NEXT:    br label [[LOOP:%.*]]
482; CHECK:       loop:
483; CHECK-NEXT:    [[PHI1:%.*]] = phi i32 [ [[PHI2:%.*]], [[LATCH:%.*]] ], [ 0, [[ENTRY:%.*]] ]
484; CHECK-NEXT:    [[DEC:%.*]] = add nuw nsw i32 [[PHI1]], -1
485; CHECK-NEXT:    br i1 false, label [[LEFT:%.*]], label [[RIGHT:%.*]]
486; CHECK:       left:
487; CHECK-NEXT:    br label [[LATCH]]
488; CHECK:       right:
489; CHECK-NEXT:    br label [[LATCH]]
490; CHECK:       latch:
491; CHECK-NEXT:    [[PHI2]] = phi i32 [ [[PHI1]], [[LEFT]] ], [ [[DEC]], [[RIGHT]] ]
492; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 -1, undef
493; CHECK-NEXT:    br i1 true, label [[EXIT:%.*]], label [[LOOP]]
494; CHECK:       exit:
495; CHECK-NEXT:    [[CMP_LCSSA:%.*]] = phi i1 [ [[CMP]], [[LATCH]] ]
496; CHECK-NEXT:    call void @use(i1 [[CMP_LCSSA]])
497; CHECK-NEXT:    ret void
498;
499entry:
500  br label %loop
501
502loop:
503  %phi1 = phi i32 [ %phi2, %latch ], [ 0, %entry ]
504  %dec = add i32 %phi1, -1
505  br i1 false, label %left, label %right
506
507left:
508  br label %latch
509
510right:
511  br label %latch
512
513latch:
514  %phi2 = phi i32 [ %phi1, %left ], [ %dec, %right ]
515  %cmp = icmp slt i32 %phi2, undef
516  br i1 true, label %exit, label %loop
517
518exit:
519  call void @use(i1 %cmp)
520  ret void
521}
522
523; check that we can figure out that iv.next > 1 from the facts that iv >= 0 and
524; iv.start != 0.
525define void @test11(i64* %inc_ptr) {
526; CHECK-LABEL: @test11(
527; CHECK-NEXT:  entry:
528; CHECK-NEXT:    [[INC:%.*]] = load i64, i64* [[INC_PTR:%.*]], !range !0
529; CHECK-NEXT:    [[NE_COND:%.*]] = icmp ne i64 [[INC]], 0
530; CHECK-NEXT:    br i1 [[NE_COND]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
531; CHECK:       loop.preheader:
532; CHECK-NEXT:    br label [[LOOP:%.*]]
533; CHECK:       loop:
534; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[INC]], [[LOOP_PREHEADER]] ]
535; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
536; CHECK-NEXT:    br i1 true, label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
537; CHECK:       if.true:
538; CHECK-NEXT:    br label [[BACKEDGE]]
539; CHECK:       if.false:
540; CHECK-NEXT:    br label [[BACKEDGE]]
541; CHECK:       backedge:
542; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[IV_NEXT]], 201
543; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
544; CHECK:       exit.loopexit:
545; CHECK-NEXT:    br label [[EXIT]]
546; CHECK:       exit:
547; CHECK-NEXT:    ret void
548;
549entry:
550  %inc = load i64, i64* %inc_ptr, !range !0
551  %ne.cond = icmp ne i64 %inc, 0
552  br i1 %ne.cond, label %loop, label %exit
553
554loop:
555  %iv = phi i64 [ %inc, %entry ], [ %iv.next, %backedge ]
556  %iv.next = add i64 %iv, 1
557  %brcond = icmp sgt i64 %iv.next, 1
558  br i1 %brcond, label %if.true, label %if.false
559
560if.true:
561  br label %backedge
562
563if.false:
564  br label %backedge
565
566backedge:
567  %loopcond = icmp slt i64 %iv, 200
568  br i1 %loopcond, label %loop, label %exit
569
570exit:
571  ret void
572}
573
574; check that we can prove that a recurrency is greater than another recurrency
575; in the same loop, with the same step, and with smaller starting value.
576define void @test12(i64* %inc_ptr) {
577; CHECK-LABEL: @test12(
578; CHECK-NEXT:  entry:
579; CHECK-NEXT:    [[INC:%.*]] = load i64, i64* [[INC_PTR:%.*]], !range !0
580; CHECK-NEXT:    br label [[LOOP:%.*]]
581; CHECK:       loop:
582; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[INC]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
583; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
584; CHECK-NEXT:    br i1 true, label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
585; CHECK:       if.true:
586; CHECK-NEXT:    br label [[BACKEDGE]]
587; CHECK:       if.false:
588; CHECK-NEXT:    br label [[BACKEDGE]]
589; CHECK:       backedge:
590; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[IV_NEXT]], 201
591; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
592; CHECK:       exit:
593; CHECK-NEXT:    ret void
594;
595entry:
596  %inc = load i64, i64* %inc_ptr, !range !0
597  %inc.minus.1 = sub i64 %inc, 1
598  br label %loop
599
600loop:
601  %iv = phi i64 [ %inc, %entry ], [ %iv.next, %backedge ]
602  %iv.minus.1 = phi i64 [ %inc.minus.1, %entry ], [ %iv.minus.1.next, %backedge ]
603  %iv.next = add i64 %iv, 1
604  %iv.minus.1.next = add i64 %iv.minus.1, 1
605  %brcond = icmp sgt i64 %iv.next, %iv.minus.1.next
606  br i1 %brcond, label %if.true, label %if.false
607
608if.true:
609  br label %backedge
610
611if.false:
612  br label %backedge
613
614backedge:
615  %loopcond = icmp slt i64 %iv, 200
616  br i1 %loopcond, label %loop, label %exit
617
618exit:
619  ret void
620}
621
622!0 = !{i64 0, i64 100}
623!1 = !{i64 -1, i64 100}
624
625declare void @foo()
626