1 ; RUN: opt -verify-loop-info -irce -S < %s | FileCheck %s
2 ; RUN: opt -verify-loop-info -passes='require<branch-prob>,loop(irce)' -S < %s | FileCheck %s
4 define void @decrementing_loop(i32 *%arr, i32 *%a_len_ptr, i32 %n) {
6 %len = load i32, i32* %a_len_ptr, !range !0
7 %first.itr.check = icmp sgt i32 %n, 0
9 br i1 %first.itr.check, label %loop, label %exit
12 %idx = phi i32 [ %start, %entry ] , [ %idx.dec, %in.bounds ]
13 %idx.dec = sub i32 %idx, 1
14 %abc.high = icmp slt i32 %idx, %len
15 %abc.low = icmp sge i32 %idx, 0
16 %abc = and i1 %abc.low, %abc.high
17 br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !1
20 %addr = getelementptr i32, i32* %arr, i32 %idx
21 store i32 0, i32* %addr
22 %next = icmp sgt i32 %idx.dec, -1
23 br i1 %next, label %loop, label %exit
31 ; CHECK: loop.preheader:
32 ; CHECK: [[not_len:[^ ]+]] = sub i32 -1, %len
33 ; CHECK: [[not_n:[^ ]+]] = sub i32 -1, %n
34 ; CHECK: [[not_len_hiclamp_cmp:[^ ]+]] = icmp sgt i32 [[not_len]], [[not_n]]
35 ; CHECK: [[not_len_hiclamp:[^ ]+]] = select i1 [[not_len_hiclamp_cmp]], i32 [[not_len]], i32 [[not_n]]
36 ; CHECK: [[len_hiclamp:[^ ]+]] = sub i32 -1, [[not_len_hiclamp]]
37 ; CHECK: [[not_exit_preloop_at_cmp:[^ ]+]] = icmp sgt i32 [[len_hiclamp]], 0
38 ; CHECK: [[not_exit_preloop_at:[^ ]+]] = select i1 [[not_exit_preloop_at_cmp]], i32 [[len_hiclamp]], i32 0
39 ; CHECK: %exit.preloop.at = add i32 [[not_exit_preloop_at]], -1
42 ; Make sure that we can eliminate the range check when the loop looks like:
43 ; for (i = len.a - 1; i >= 0; --i)
45 define void @test_01(i32* %a, i32* %b, i32* %a_len_ptr, i32* %b_len_ptr) {
47 ; CHECK-LABEL: test_01
49 ; CHECK-NEXT: br label %loop
51 ; CHECK: %rc = and i1 true, true
52 ; CHECK: loop.preloop:
55 %len.a = load i32, i32* %a_len_ptr, !range !0
56 %len.b = load i32, i32* %b_len_ptr, !range !0
57 %first.itr.check = icmp ne i32 %len.a, 0
58 br i1 %first.itr.check, label %loop, label %exit
61 %idx = phi i32 [ %len.a, %entry ] , [ %idx.next, %in.bounds ]
62 %idx.next = sub i32 %idx, 1
63 %rca = icmp ult i32 %idx.next, %len.a
64 %rcb = icmp ult i32 %idx.next, %len.b
65 %rc = and i1 %rca, %rcb
66 br i1 %rc, label %in.bounds, label %out.of.bounds, !prof !1
69 %el.a = getelementptr i32, i32* %a, i32 %idx.next
70 %el.b = getelementptr i32, i32* %b, i32 %idx.next
71 %v = load i32, i32* %el.a
72 store i32 %v, i32* %el.b
73 %loop.cond = icmp slt i32 %idx, 2
74 br i1 %loop.cond, label %exit, label %loop
83 ; Same as test_01, but the latch condition is unsigned
84 define void @test_02(i32* %a, i32* %b, i32* %a_len_ptr, i32* %b_len_ptr) {
86 ; CHECK-LABEL: test_02
88 ; CHECK-NEXT: br label %loop
90 ; CHECK: %rc = and i1 true, true
91 ; CHECK: loop.preloop:
94 %len.a = load i32, i32* %a_len_ptr, !range !0
95 %len.b = load i32, i32* %b_len_ptr, !range !0
96 %first.itr.check = icmp ne i32 %len.a, 0
97 br i1 %first.itr.check, label %loop, label %exit
100 %idx = phi i32 [ %len.a, %entry ] , [ %idx.next, %in.bounds ]
101 %idx.next = sub i32 %idx, 1
102 %rca = icmp ult i32 %idx.next, %len.a
103 %rcb = icmp ult i32 %idx.next, %len.b
104 %rc = and i1 %rca, %rcb
105 br i1 %rc, label %in.bounds, label %out.of.bounds, !prof !1
108 %el.a = getelementptr i32, i32* %a, i32 %idx.next
109 %el.b = getelementptr i32, i32* %b, i32 %idx.next
110 %v = load i32, i32* %el.a
111 store i32 %v, i32* %el.b
112 %loop.cond = icmp ult i32 %idx, 2
113 br i1 %loop.cond, label %exit, label %loop
122 ; Check that we can figure out that IV is non-negative via implication through
124 define void @test_03(i32* %a, i32* %a_len_ptr, i1 %cond) {
126 ; CHECK-LABEL: test_03
128 ; CHECK-NEXT: br label %loop
130 ; CHECK: br i1 true, label %in.bounds, label %out.of.bounds
131 ; CHECK: loop.preloop:
134 %len.a = load i32, i32* %a_len_ptr, !range !0
135 %len.minus.one = sub nsw i32 %len.a, 1
136 %len.minus.two = sub nsw i32 %len.a, 2
137 br i1 %cond, label %if.true, label %if.false
146 %starting.value = phi i32 [ %len.minus.two, %if.true ], [ %len.minus.one, %if.false ]
147 %first.itr.check = icmp sgt i32 %len.a, 3
148 br i1 %first.itr.check, label %loop, label %exit
151 %idx = phi i32 [ %starting.value, %merge ] , [ %idx.next, %in.bounds ]
152 %idx.next = sub i32 %idx, 1
153 %rc = icmp ult i32 %idx.next, %len.a
154 br i1 %rc, label %in.bounds, label %out.of.bounds, !prof !1
157 %el.a = getelementptr i32, i32* %a, i32 %idx.next
158 %v = load i32, i32* %el.a
159 %loop.cond = icmp slt i32 %idx, 2
160 br i1 %loop.cond, label %exit, label %loop
169 ; Check that we can figure out that IV is non-negative via implication through
171 define void @test_04(i32* %a, i32* %a_len_ptr, i1 %cond) {
173 ; CHECK-LABEL: test_04
175 ; CHECK-NEXT: br label %loop
177 ; CHECK: br i1 true, label %in.bounds, label %out.of.bounds
178 ; CHECK: loop.preloop:
181 %len.a = load i32, i32* %a_len_ptr, !range !0
182 %len.minus.one = sub nsw i32 %len.a, 1
183 %len.plus.one = add nsw i32 %len.a, 1
184 %len.minus.two = sub nsw i32 %len.a, 2
185 br i1 %cond, label %if.true, label %if.false
194 %starting.value = phi i32 [ %len.minus.two, %if.true ], [ %len.minus.one, %if.false ]
195 %len.phi = phi i32 [ %len.a, %if.true ], [ %len.plus.one, %if.false ]
196 %first.itr.check = icmp sgt i32 %len.a, 3
197 br i1 %first.itr.check, label %loop, label %exit
200 %idx = phi i32 [ %starting.value, %merge ] , [ %idx.next, %in.bounds ]
201 %idx.next = sub i32 %idx, 1
202 %rc = icmp ult i32 %idx.next, %len.phi
203 br i1 %rc, label %in.bounds, label %out.of.bounds, !prof !1
206 %el.a = getelementptr i32, i32* %a, i32 %idx.next
207 %v = load i32, i32* %el.a
208 %loop.cond = icmp slt i32 %idx, 2
209 br i1 %loop.cond, label %exit, label %loop
218 ; Check that we can figure out that IV is non-negative via implication through
219 ; two Phi nodes, one being AddRec.
220 define void @test_05(i32* %a, i32* %a_len_ptr, i1 %cond) {
222 ; CHECK-LABEL: test_05
224 ; CHECK-NEXT: br label %loop
226 ; CHECK: br i1 true, label %in.bounds, label %out.of.bounds
227 ; CHECK: loop.preloop:
230 %len.a = load i32, i32* %a_len_ptr, !range !0
231 %len.minus.one = sub nsw i32 %len.a, 1
232 %len.plus.one = add nsw i32 %len.a, 1
233 %len.minus.two = sub nsw i32 %len.a, 2
237 %starting.value = phi i32 [ %len.minus.two, %entry ], [ %len.minus.one, %merge ]
238 %len.phi = phi i32 [ %len.a, %entry ], [ %len.phi.next, %merge ]
239 %len.phi.next = add nsw i32 %len.phi, 1
240 br i1 true, label %first.iter.check, label %merge
243 %first.itr.check = icmp sgt i32 %len.a, 3
244 br i1 %first.itr.check, label %loop, label %exit
247 %idx = phi i32 [ %starting.value, %first.iter.check ] , [ %idx.next, %in.bounds ]
248 %idx.next = sub i32 %idx, 1
249 %rc = icmp ult i32 %idx.next, %len.phi
250 br i1 %rc, label %in.bounds, label %out.of.bounds, !prof !1
253 %el.a = getelementptr i32, i32* %a, i32 %idx.next
254 %v = load i32, i32* %el.a
255 %loop.cond = icmp slt i32 %idx, 2
256 br i1 %loop.cond, label %exit, label %loop
265 !0 = !{i32 0, i32 2147483647}
266 !1 = !{!"branch_weights", i32 64, i32 4}