Revert r354244 "[DAGCombiner] Eliminate dead stores to stack."
[llvm-complete.git] / test / Transforms / IRCE / decrementing-loop.ll
blob4c82cd3e34148c16ff1baf1ac8b3e5456e345d63
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) {
5  entry:
6   %len = load i32, i32* %a_len_ptr, !range !0
7   %first.itr.check = icmp sgt i32 %n, 0
8   %start = sub i32 %n, 1
9   br i1 %first.itr.check, label %loop, label %exit
11  loop:
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
19  in.bounds:
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
25  out.of.bounds:
26   ret void
28  exit:
29   ret void
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)
44 ;   b[i] = a[i];
45 define void @test_01(i32* %a, i32* %b, i32* %a_len_ptr, i32* %b_len_ptr) {
47 ; CHECK-LABEL: test_01
48 ; CHECK:       mainloop:
49 ; CHECK-NEXT:    br label %loop
50 ; CHECK:       loop:
51 ; CHECK:         %rc = and i1 true, true
52 ; CHECK:       loop.preloop:
54  entry:
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
60  loop:
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
68  in.bounds:
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
76  out.of.bounds:
77   ret void
79  exit:
80   ret void
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
87 ; CHECK:       mainloop:
88 ; CHECK-NEXT:    br label %loop
89 ; CHECK:       loop:
90 ; CHECK:         %rc = and i1 true, true
91 ; CHECK:       loop.preloop:
93  entry:
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
99  loop:
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
107  in.bounds:
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
115  out.of.bounds:
116   ret void
118  exit:
119   ret void
122 ; Check that we can figure out that IV is non-negative via implication through
123 ; Phi node.
124 define void @test_03(i32* %a, i32* %a_len_ptr, i1 %cond) {
126 ; CHECK-LABEL: test_03
127 ; CHECK:       mainloop:
128 ; CHECK-NEXT:    br label %loop
129 ; CHECK:       loop:
130 ; CHECK:         br i1 true, label %in.bounds, label %out.of.bounds
131 ; CHECK:       loop.preloop:
133  entry:
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
139 if.true:
140   br label %merge
142 if.false:
143   br label %merge
145 merge:
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
150 loop:
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
156 in.bounds:
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
162 out.of.bounds:
163   ret void
165 exit:
166   ret void
169 ; Check that we can figure out that IV is non-negative via implication through
170 ; two Phi nodes.
171 define void @test_04(i32* %a, i32* %a_len_ptr, i1 %cond) {
173 ; CHECK-LABEL: test_04
174 ; CHECK:       mainloop:
175 ; CHECK-NEXT:    br label %loop
176 ; CHECK:       loop:
177 ; CHECK:         br i1 true, label %in.bounds, label %out.of.bounds
178 ; CHECK:       loop.preloop:
180  entry:
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
187 if.true:
188   br label %merge
190 if.false:
191   br label %merge
193 merge:
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
199 loop:
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
205 in.bounds:
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
211 out.of.bounds:
212   ret void
214 exit:
215   ret void
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
223 ; CHECK:       mainloop:
224 ; CHECK-NEXT:    br label %loop
225 ; CHECK:       loop:
226 ; CHECK:         br i1 true, label %in.bounds, label %out.of.bounds
227 ; CHECK:       loop.preloop:
229  entry:
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
234   br label %merge
236 merge:
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
242 first.iter.check:
243   %first.itr.check = icmp sgt i32 %len.a, 3
244   br i1 %first.itr.check, label %loop, label %exit
246 loop:
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
252 in.bounds:
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
258 out.of.bounds:
259   ret void
261 exit:
262   ret void
265 !0 = !{i32 0, i32 2147483647}
266 !1 = !{!"branch_weights", i32 64, i32 4}