• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; RUN: opt -S -indvars %s | FileCheck %s
2target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
3target triple = "x86_64-unknown-linux-gnu"
4
5define void @test1(i64 %start) {
6; CHECK-LABEL: @test1
7entry:
8  br label %loop
9
10loop:
11  %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %loop ]
12  %indvars.iv.next = add nsw i64 %indvars.iv, 1
13; CHECK: %cmp1 = icmp slt i64 %start, -1
14  %cmp1 = icmp slt i64 %indvars.iv, -1
15  br i1 %cmp1, label %for.end, label %loop
16
17for.end:                                          ; preds = %if.end, %entry
18  ret void
19}
20
21define void @test2(i64 %start) {
22; CHECK-LABEL: @test2
23entry:
24  br label %loop
25
26loop:
27  %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %loop ]
28  %indvars.iv.next = add nsw i64 %indvars.iv, 1
29; CHECK: %cmp1 = icmp sle i64 %start, -1
30  %cmp1 = icmp sle i64 %indvars.iv, -1
31  br i1 %cmp1, label %for.end, label %loop
32
33for.end:                                          ; preds = %if.end, %entry
34  ret void
35}
36
37; As long as the test dominates the backedge, we're good
38define void @test3(i64 %start) {
39; CHECK-LABEL: @test3
40entry:
41  br label %loop
42
43loop:
44  %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %backedge ]
45  %indvars.iv.next = add nsw i64 %indvars.iv, 1
46  %cmp = icmp eq i64 %indvars.iv.next, 25
47  br i1 %cmp, label %backedge, label %for.end
48
49backedge:
50  ; prevent flattening, needed to make sure we're testing what we intend
51  call void @foo()
52; CHECK: %cmp1 = icmp slt i64 %start, -1
53  %cmp1 = icmp slt i64 %indvars.iv, -1
54  br i1 %cmp1, label %for.end, label %loop
55
56for.end:                                          ; preds = %if.end, %entry
57  ret void
58}
59
60define void @test4(i64 %start) {
61; CHECK-LABEL: @test4
62entry:
63  br label %loop
64
65loop:
66  %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %backedge ]
67  %indvars.iv.next = add nsw i64 %indvars.iv, 1
68  %cmp = icmp eq i64 %indvars.iv.next, 25
69  br i1 %cmp, label %backedge, label %for.end
70
71backedge:
72  ; prevent flattening, needed to make sure we're testing what we intend
73  call void @foo()
74; CHECK: %cmp1 = icmp sgt i64 %start, -1
75  %cmp1 = icmp sgt i64 %indvars.iv, -1
76  br i1 %cmp1, label %loop, label %for.end
77
78for.end:                                          ; preds = %if.end, %entry
79  ret void
80}
81
82define void @test5(i64 %start) {
83; CHECK-LABEL: @test5
84entry:
85  br label %loop
86
87loop:
88  %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %backedge ]
89  %indvars.iv.next = add nuw i64 %indvars.iv, 1
90  %cmp = icmp eq i64 %indvars.iv.next, 25
91  br i1 %cmp, label %backedge, label %for.end
92
93backedge:
94  ; prevent flattening, needed to make sure we're testing what we intend
95  call void @foo()
96; CHECK: %cmp1 = icmp ugt i64 %start, 100
97  %cmp1 = icmp ugt i64 %indvars.iv, 100
98  br i1 %cmp1, label %loop, label %for.end
99
100for.end:                                          ; preds = %if.end, %entry
101  ret void
102}
103
104define void @test6(i64 %start) {
105; CHECK-LABEL: @test6
106entry:
107  br label %loop
108
109loop:
110  %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %backedge ]
111  %indvars.iv.next = add nuw i64 %indvars.iv, 1
112  %cmp = icmp eq i64 %indvars.iv.next, 25
113  br i1 %cmp, label %backedge, label %for.end
114
115backedge:
116  ; prevent flattening, needed to make sure we're testing what we intend
117  call void @foo()
118; CHECK: %cmp1 = icmp ult i64 %start, 100
119  %cmp1 = icmp ult i64 %indvars.iv, 100
120  br i1 %cmp1, label %for.end, label %loop
121
122for.end:                                          ; preds = %if.end, %entry
123  ret void
124}
125
126define void @test7(i64 %start, i64* %inc_ptr) {
127; CHECK-LABEL: @test7
128entry:
129  %inc = load i64, i64* %inc_ptr, !range !0
130  %ok = icmp sge i64 %inc, 0
131  br i1 %ok, label %loop, label %for.end
132
133loop:
134  %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %loop ]
135  %indvars.iv.next = add nsw i64 %indvars.iv, %inc
136; CHECK: %cmp1 = icmp slt i64 %start, -1
137  %cmp1 = icmp slt i64 %indvars.iv, -1
138  br i1 %cmp1, label %for.end, label %loop
139
140for.end:                                          ; preds = %if.end, %entry
141  ret void
142}
143
144; Negative test - we can't show that the internal branch executes, so we can't
145; fold the test to a loop invariant one.
146define void @test1_neg(i64 %start) {
147; CHECK-LABEL: @test1_neg
148entry:
149  br label %loop
150
151loop:
152  %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %backedge ]
153  %indvars.iv.next = add nsw i64 %indvars.iv, 1
154  %cmp = icmp eq i64 %indvars.iv.next, 25
155  br i1 %cmp, label %backedge, label %skip
156skip:
157  ; prevent flattening, needed to make sure we're testing what we intend
158  call void @foo()
159; CHECK: %cmp1 = icmp slt i64 %indvars.iv, -1
160  %cmp1 = icmp slt i64 %indvars.iv, -1
161  br i1 %cmp1, label %for.end, label %backedge
162backedge:
163  ; prevent flattening, needed to make sure we're testing what we intend
164  call void @foo()
165  br label %loop
166
167for.end:                                          ; preds = %if.end, %entry
168  ret void
169}
170
171; Slightly subtle version of @test4 where the icmp dominates the backedge,
172; but the exit branch doesn't.
173define void @test2_neg(i64 %start) {
174; CHECK-LABEL: @test2_neg
175entry:
176  br label %loop
177
178loop:
179  %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %backedge ]
180  %indvars.iv.next = add nsw i64 %indvars.iv, 1
181  %cmp = icmp eq i64 %indvars.iv.next, 25
182; CHECK: %cmp1 = icmp slt i64 %indvars.iv, -1
183  %cmp1 = icmp slt i64 %indvars.iv, -1
184  br i1 %cmp, label %backedge, label %skip
185skip:
186  ; prevent flattening, needed to make sure we're testing what we intend
187  call void @foo()
188  br i1 %cmp1, label %for.end, label %backedge
189backedge:
190  ; prevent flattening, needed to make sure we're testing what we intend
191  call void @foo()
192  br label %loop
193
194for.end:                                          ; preds = %if.end, %entry
195  ret void
196}
197
198; The branch has to exit the loop if the condition is true
199define void @test3_neg(i64 %start) {
200; CHECK-LABEL: @test3_neg
201entry:
202  br label %loop
203
204loop:
205  %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %loop ]
206  %indvars.iv.next = add nsw i64 %indvars.iv, 1
207; CHECK: %cmp1 = icmp slt i64 %indvars.iv, -1
208  %cmp1 = icmp slt i64 %indvars.iv, -1
209  br i1 %cmp1, label %loop, label %for.end
210
211for.end:                                          ; preds = %if.end, %entry
212  ret void
213}
214
215define void @test4_neg(i64 %start) {
216; CHECK-LABEL: @test4_neg
217entry:
218  br label %loop
219
220loop:
221  %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %backedge ]
222  %indvars.iv.next = add nsw i64 %indvars.iv, 1
223  %cmp = icmp eq i64 %indvars.iv.next, 25
224  br i1 %cmp, label %backedge, label %for.end
225
226backedge:
227  ; prevent flattening, needed to make sure we're testing what we intend
228  call void @foo()
229; CHECK: %cmp1 = icmp sgt i64 %indvars.iv, -1
230  %cmp1 = icmp sgt i64 %indvars.iv, -1
231
232; %cmp1 can be made loop invariant only if the branch below goes to
233; %the header when %cmp1 is true.
234  br i1 %cmp1, label %for.end, label %loop
235
236for.end:                                          ; preds = %if.end, %entry
237  ret void
238}
239
240define void @test5_neg(i64 %start, i64 %inc) {
241; CHECK-LABEL: @test5_neg
242entry:
243  br label %loop
244
245loop:
246  %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %loop ]
247  %indvars.iv.next = add nsw i64 %indvars.iv, %inc
248; CHECK: %cmp1 = icmp slt i64 %indvars.iv, -1
249  %cmp1 = icmp slt i64 %indvars.iv, -1
250  br i1 %cmp1, label %for.end, label %loop
251
252for.end:                                          ; preds = %if.end, %entry
253  ret void
254}
255
256define void @test8(i64 %start, i64* %inc_ptr) {
257; CHECK-LABEL: @test8
258entry:
259  %inc = load i64, i64* %inc_ptr, !range !1
260  %ok = icmp sge i64 %inc, 0
261  br i1 %ok, label %loop, label %for.end
262
263loop:
264  %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %loop ]
265  %indvars.iv.next = add nsw i64 %indvars.iv, %inc
266; CHECK: %cmp1 = icmp slt i64 %indvars.iv, -1
267  %cmp1 = icmp slt i64 %indvars.iv, -1
268  br i1 %cmp1, label %for.end, label %loop
269
270for.end:                                          ; preds = %if.end, %entry
271  ret void
272}
273
274; check to handle loops without preheaders, but invariant operands
275; (we handle this today by inserting a preheader)
276define void @test9(i1 %cnd, i64 %start) {
277; CHECK-LABEL: @test9
278; CHECK-LABEL: loop.preheader:
279entry:
280  br i1 %cnd, label %entry1, label %entry2
281entry1:
282  br label %loop
283entry2:
284  br label %loop
285loop:
286  %indvars.iv = phi i64 [ %start, %entry1 ],[ %start, %entry2 ], [ %indvars.iv.next, %loop ]
287  %indvars.iv.next = add nsw i64 %indvars.iv, 1
288; CHECK: %cmp1 = icmp slt i64 %start, -1
289  %cmp1 = icmp slt i64 %indvars.iv, -1
290  br i1 %cmp1, label %for.end, label %loop
291
292for.end:                                          ; preds = %if.end, %entry
293  ret void
294}
295
296declare void @use(i1 %x)
297
298; check that we handle conditions with loop invariant operands which
299; *aren't* in the header - this is a very rare and fragile case where
300; we have a "loop" which is known to run exactly one iteration but
301; haven't yet simplified the uses of the IV
302define void @test10() {
303; CHECK-LABEL: @test10
304entry:
305  br label %loop
306
307loop:
308  %phi1 = phi i32 [ %phi2, %latch ], [ 0, %entry ]
309  %dec = add i32 %phi1, -1
310  br i1 false, label %left, label %right
311
312left:
313  br label %latch
314
315right:
316  br label %latch
317
318latch:
319  %phi2 = phi i32 [ %phi1, %left ], [ %dec, %right ]
320  ; CHECK: %cmp = icmp slt i32 -1, undef
321  %cmp = icmp slt i32 %phi2, undef
322  br i1 true, label %exit, label %loop
323
324exit:
325  call void @use(i1 %cmp)
326  ret void
327}
328
329; check that we can figure out that iv.next > 1 from the facts that iv >= 0 and
330; iv.start != 0.
331define void @test11(i64* %inc_ptr) {
332; CHECK-LABEL: @test11
333entry:
334  %inc = load i64, i64* %inc_ptr, !range !0
335  %ne.cond = icmp ne i64 %inc, 0
336  br i1 %ne.cond, label %loop, label %exit
337
338loop:
339  %iv = phi i64 [ %inc, %entry ], [ %iv.next, %backedge ]
340  %iv.next = add i64 %iv, 1
341  %brcond = icmp sgt i64 %iv.next, 1
342  ; CHECK: br i1 true, label %if.true, label %if.false
343  br i1 %brcond, label %if.true, label %if.false
344
345if.true:
346  br label %backedge
347
348if.false:
349  br label %backedge
350
351backedge:
352  %loopcond = icmp slt i64 %iv, 200
353  br i1 %loopcond, label %loop, label %exit
354
355exit:
356  ret void
357}
358
359; check that we can prove that a recurrency is greater than another recurrency
360; in the same loop, with the same step, and with smaller starting value.
361define void @test12(i64* %inc_ptr) {
362; CHECK-LABEL: @test12
363entry:
364  %inc = load i64, i64* %inc_ptr, !range !0
365  %inc.minus.1 = sub i64 %inc, 1
366  br label %loop
367
368loop:
369  %iv = phi i64 [ %inc, %entry ], [ %iv.next, %backedge ]
370  %iv.minus.1 = phi i64 [ %inc.minus.1, %entry ], [ %iv.minus.1.next, %backedge ]
371  %iv.next = add i64 %iv, 1
372  %iv.minus.1.next = add i64 %iv.minus.1, 1
373  %brcond = icmp sgt i64 %iv.next, %iv.minus.1.next
374  ; CHECK: br i1 true, label %if.true, label %if.false
375  br i1 %brcond, label %if.true, label %if.false
376
377if.true:
378  br label %backedge
379
380if.false:
381  br label %backedge
382
383backedge:
384  %loopcond = icmp slt i64 %iv, 200
385  br i1 %loopcond, label %loop, label %exit
386
387exit:
388  ret void
389}
390
391!0 = !{i64 0, i64 100}
392!1 = !{i64 -1, i64 100}
393
394declare void @foo()
395