[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / IRCE / stride_more_than_1.ll
blob1700462f069487fb5f95833b700818d1b8459834
1 ; RUN: opt -verify-loop-info -irce-print-changed-loops -irce -S < %s 2>&1 | FileCheck %s
2 ; RUN: opt -verify-loop-info -irce-print-changed-loops -passes='require<branch-prob>,irce' -S < %s 2>&1 | FileCheck %s
4 ; CHECK: irce: in function test_01: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
5 ; CHECK: irce: in function test_02: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
6 ; CHECK: irce: in function test_03: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
7 ; CHECK: irce: in function test_04: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
8 ; CHECK: irce: in function test_05: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
9 ; CHECK: irce: in function test_06: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
10 ; CHECK-NOT: irce: in function test_07: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
11 ; CHECK: irce: in function test_08: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
13 ; IV = 0; IV <s 100; IV += 7; 0 <= Len <= 50. IRCE is allowed.
14 define void @test_01(i32* %arr, i32* %a_len_ptr) {
16 ; CHECK:      @test_01(
17 ; CHECK:      entry:
18 ; CHECK-NEXT:   %exit.mainloop.at = load i32, i32* %a_len_ptr
19 ; CHECK-NEXT:   [[COND1:%[^ ]+]] = icmp slt i32 0, %exit.mainloop.at
20 ; CHECK-NEXT:   br i1 [[COND1]], label %loop.preheader, label %main.pseudo.exit
21 ; CHECK:      loop.preheader:
22 ; CHECK-NEXT:   br label %loop
23 ; CHECK:      loop:
24 ; CHECK-NEXT:   %idx = phi i32 [ %idx.next, %in.bounds ], [ 0, %loop.preheader ]
25 ; CHECK-NEXT:   %idx.next = add i32 %idx, 7
26 ; CHECK-NEXT:   %abc = icmp slt i32 %idx, %exit.mainloop.at
27 ; CHECK-NEXT:   br i1 true, label %in.bounds, label %out.of.bounds.loopexit1
28 ; CHECK:      in.bounds:
29 ; CHECK-NEXT:   %addr = getelementptr i32, i32* %arr, i32 %idx
30 ; CHECK-NEXT:   store i32 0, i32* %addr
31 ; CHECK-NEXT:   %next = icmp slt i32 %idx.next, 100
32 ; CHECK-NEXT:   [[COND2:%[^ ]+]] = icmp slt i32 %idx.next, %exit.mainloop.at
33 ; CHECK-NEXT:   br i1 [[COND2]], label %loop, label %main.exit.selector
34 ; CHECK:      main.exit.selector:
35 ; CHECK-NEXT:   %idx.next.lcssa = phi i32 [ %idx.next, %in.bounds ]
36 ; CHECK-NEXT:   [[COND3:%[^ ]+]] = icmp slt i32 %idx.next.lcssa, 100
37 ; CHECK-NEXT:   br i1 [[COND3]], label %main.pseudo.exit, label %exit
38 ; CHECK:      main.pseudo.exit:
39 ; CHECK-NEXT:   %idx.copy = phi i32 [ 0, %entry ], [ %idx.next.lcssa, %main.exit.selector ]
40 ; CHECK-NEXT:    %indvar.end = phi i32 [ 0, %entry ], [ %idx.next.lcssa, %main.exit.selector ]
41 ; CHECK-NEXT:    br label %postloop
42 ; CHECK:      postloop:
43 ; CHECK-NEXT:   br label %loop.postloop
44 ; CHECK:      loop.postloop:
45 ; CHECK-NEXT:   %idx.postloop = phi i32 [ %idx.copy, %postloop ], [ %idx.next.postloop, %in.bounds.postloop ]
46 ; CHECK-NEXT:   %idx.next.postloop = add i32 %idx.postloop, 7
47 ; CHECK-NEXT:   %abc.postloop = icmp slt i32 %idx.postloop, %exit.mainloop.at
48 ; CHECK-NEXT:   br i1 %abc.postloop, label %in.bounds.postloop, label %out.of.bounds.loopexit
49 ; CHECK:      in.bounds.postloop:
50 ; CHECK-NEXT:   %addr.postloop = getelementptr i32, i32* %arr, i32 %idx.postloop
51 ; CHECK-NEXT:   store i32 0, i32* %addr.postloop
52 ; CHECK-NEXT:   %next.postloop = icmp slt i32 %idx.next.postloop, 100
53 ; CHECK-NEXT:   br i1 %next.postloop, label %loop.postloop, label %exit.loopexit
55 entry:
56   %len = load i32, i32* %a_len_ptr, !range !0
57   br label %loop
59 loop:
60   %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
61   %idx.next = add i32 %idx, 7
62   %abc = icmp slt i32 %idx, %len
63   br i1 %abc, label %in.bounds, label %out.of.bounds
65 in.bounds:
66   %addr = getelementptr i32, i32* %arr, i32 %idx
67   store i32 0, i32* %addr
68   %next = icmp slt i32 %idx.next, 100
69   br i1 %next, label %loop, label %exit
71 out.of.bounds:
72   ret void
74 exit:
75   ret void
78 ; IV = 0; IV <s MAX_INT - 7; IV += 7; 0 <= Len <= 50. IRCE is allowed.
79 define void @test_02(i32* %arr, i32* %a_len_ptr) {
81 ; CHECK:      @test_02(
82 ; CHECK:      entry:
83 ; CHECK-NEXT:   %exit.mainloop.at = load i32, i32* %a_len_ptr
84 ; CHECK-NEXT:   [[COND1:%[^ ]+]] = icmp slt i32 0, %exit.mainloop.at
85 ; CHECK-NEXT:   br i1 [[COND1]], label %loop.preheader, label %main.pseudo.exit
86 ; CHECK:      loop.preheader:
87 ; CHECK-NEXT:   br label %loop
88 ; CHECK:      loop:
89 ; CHECK-NEXT:   %idx = phi i32 [ %idx.next, %in.bounds ], [ 0, %loop.preheader ]
90 ; CHECK-NEXT:   %idx.next = add i32 %idx, 7
91 ; CHECK-NEXT:   %abc = icmp slt i32 %idx, %exit.mainloop.at
92 ; CHECK-NEXT:   br i1 true, label %in.bounds, label %out.of.bounds.loopexit1
93 ; CHECK:      in.bounds:
94 ; CHECK-NEXT:   %addr = getelementptr i32, i32* %arr, i32 %idx
95 ; CHECK-NEXT:   store i32 0, i32* %addr
96 ; CHECK-NEXT:   %next = icmp slt i32 %idx.next, 2147483640
97 ; CHECK-NEXT:   [[COND2:%[^ ]+]] = icmp slt i32 %idx.next, %exit.mainloop.at
98 ; CHECK-NEXT:   br i1 [[COND2]], label %loop, label %main.exit.selector
99 ; CHECK:      main.exit.selector:
100 ; CHECK-NEXT:   %idx.next.lcssa = phi i32 [ %idx.next, %in.bounds ]
101 ; CHECK-NEXT:   [[COND3:%[^ ]+]] = icmp slt i32 %idx.next.lcssa, 2147483640
102 ; CHECK-NEXT:   br i1 [[COND3]], label %main.pseudo.exit, label %exit
103 ; CHECK:      main.pseudo.exit:
104 ; CHECK-NEXT:   %idx.copy = phi i32 [ 0, %entry ], [ %idx.next.lcssa, %main.exit.selector ]
105 ; CHECK-NEXT:    %indvar.end = phi i32 [ 0, %entry ], [ %idx.next.lcssa, %main.exit.selector ]
106 ; CHECK-NEXT:    br label %postloop
107 ; CHECK:      postloop:
108 ; CHECK-NEXT:   br label %loop.postloop
109 ; CHECK:      loop.postloop:
110 ; CHECK-NEXT:   %idx.postloop = phi i32 [ %idx.copy, %postloop ], [ %idx.next.postloop, %in.bounds.postloop ]
111 ; CHECK-NEXT:   %idx.next.postloop = add i32 %idx.postloop, 7
112 ; CHECK-NEXT:   %abc.postloop = icmp slt i32 %idx.postloop, %exit.mainloop.at
113 ; CHECK-NEXT:   br i1 %abc.postloop, label %in.bounds.postloop, label %out.of.bounds.loopexit
114 ; CHECK:      in.bounds.postloop:
115 ; CHECK-NEXT:   %addr.postloop = getelementptr i32, i32* %arr, i32 %idx.postloop
116 ; CHECK-NEXT:   store i32 0, i32* %addr.postloop
117 ; CHECK-NEXT:   %next.postloop = icmp slt i32 %idx.next.postloop, 2147483640
118 ; CHECK-NEXT:   br i1 %next.postloop, label %loop.postloop, label %exit.loopexit
120 entry:
121   %len = load i32, i32* %a_len_ptr, !range !0
122   br label %loop
124 loop:
125   %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
126   %idx.next = add i32 %idx, 7
127   %abc = icmp slt i32 %idx, %len
128   br i1 %abc, label %in.bounds, label %out.of.bounds
130 in.bounds:
131   %addr = getelementptr i32, i32* %arr, i32 %idx
132   store i32 0, i32* %addr
133   %next = icmp slt i32 %idx.next, 2147483640
134   br i1 %next, label %loop, label %exit
136 out.of.bounds:
137   ret void
139 exit:
140   ret void
143 ; IV = 0; IV <s MAX_INT; IV += 7; 0 <= Len <= MAX_INT - 7. This is the greatest
144 ; value of Len for which IRCE is allowed.
145 define void @test_03(i32* %arr, i32* %a_len_ptr) {
147 ; CHECK:      @test_03(
148 ; CHECK:      entry:
149 ; CHECK-NEXT:   %exit.mainloop.at = load i32, i32* %a_len_ptr
150 ; CHECK-NEXT:   [[COND1:%[^ ]+]] = icmp slt i32 0, %exit.mainloop.at
151 ; CHECK-NEXT:   br i1 [[COND1]], label %loop.preheader, label %main.pseudo.exit
152 ; CHECK:      loop.preheader:
153 ; CHECK-NEXT:   br label %loop
154 ; CHECK:      loop:
155 ; CHECK-NEXT:   %idx = phi i32 [ %idx.next, %in.bounds ], [ 0, %loop.preheader ]
156 ; CHECK-NEXT:   %idx.next = add i32 %idx, 7
157 ; CHECK-NEXT:   %abc = icmp slt i32 %idx, %exit.mainloop.at
158 ; CHECK-NEXT:   br i1 true, label %in.bounds, label %out.of.bounds.loopexit1
159 ; CHECK:      in.bounds:
160 ; CHECK-NEXT:   %addr = getelementptr i32, i32* %arr, i32 %idx
161 ; CHECK-NEXT:   store i32 0, i32* %addr
162 ; CHECK-NEXT:   %next = icmp slt i32 %idx.next, 2147483647
163 ; CHECK-NEXT:   [[COND2:%[^ ]+]] = icmp slt i32 %idx.next, %exit.mainloop.at
164 ; CHECK-NEXT:   br i1 [[COND2]], label %loop, label %main.exit.selector
165 ; CHECK:      main.exit.selector:
166 ; CHECK-NEXT:   %idx.next.lcssa = phi i32 [ %idx.next, %in.bounds ]
167 ; CHECK-NEXT:   [[COND3:%[^ ]+]] = icmp slt i32 %idx.next.lcssa, 2147483647
168 ; CHECK-NEXT:   br i1 [[COND3]], label %main.pseudo.exit, label %exit
169 ; CHECK:      main.pseudo.exit:
170 ; CHECK-NEXT:   %idx.copy = phi i32 [ 0, %entry ], [ %idx.next.lcssa, %main.exit.selector ]
171 ; CHECK-NEXT:    %indvar.end = phi i32 [ 0, %entry ], [ %idx.next.lcssa, %main.exit.selector ]
172 ; CHECK-NEXT:    br label %postloop
173 ; CHECK:      postloop:
174 ; CHECK-NEXT:   br label %loop.postloop
175 ; CHECK:      loop.postloop:
176 ; CHECK-NEXT:   %idx.postloop = phi i32 [ %idx.copy, %postloop ], [ %idx.next.postloop, %in.bounds.postloop ]
177 ; CHECK-NEXT:   %idx.next.postloop = add i32 %idx.postloop, 7
178 ; CHECK-NEXT:   %abc.postloop = icmp slt i32 %idx.postloop, %exit.mainloop.at
179 ; CHECK-NEXT:   br i1 %abc.postloop, label %in.bounds.postloop, label %out.of.bounds.loopexit
180 ; CHECK:      in.bounds.postloop:
181 ; CHECK-NEXT:   %addr.postloop = getelementptr i32, i32* %arr, i32 %idx.postloop
182 ; CHECK-NEXT:   store i32 0, i32* %addr.postloop
183 ; CHECK-NEXT:   %next.postloop = icmp slt i32 %idx.next.postloop, 2147483647
184 ; CHECK-NEXT:   br i1 %next.postloop, label %loop.postloop, label %exit.loopexit
186 entry:
187   %len = load i32, i32* %a_len_ptr, !range !1
188   br label %loop
190 loop:
191   %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
192   %idx.next = add i32 %idx, 7
193   %abc = icmp slt i32 %idx, %len
194   br i1 %abc, label %in.bounds, label %out.of.bounds
196 in.bounds:
197   %addr = getelementptr i32, i32* %arr, i32 %idx
198   store i32 0, i32* %addr
199   %next = icmp slt i32 %idx.next, 2147483647
200   br i1 %next, label %loop, label %exit
202 out.of.bounds:
203   ret void
205 exit:
206   ret void
209 ; IV = 0; IV <s MAX_INT; IV += 7; 0 <= Len <= MAX_INT - 6. IRCE is allowed
210 ; because the branch would fail once idx.next == MAX_INT - 1 keeping the
211 ; access in bounds.
212 define void @test_04(i32* %arr, i32* %a_len_ptr) {
213   ; CHECK:  @test_04(
214   ; CHECK:  loop:
215   ; CHECK:  [[IV:%[^ ]+]] = phi i32
216   ; CHECK:  [[IDX_NEXT:%[^ ]+]] = add i32 [[IV]], 7
218   ; CHECK:  main.exit.selector:
219   ; CHECK:  [[PSEUDO_PHI:%[^ ]+]] =  phi i32 [ [[IDX_NEXT]], %in.bounds ]
220   ; CHECK:  [[COND:%[^ ]+]] = icmp slt i32 [[PSEUDO_PHI]], 2147483647
221   ; CHECK:  br i1 [[COND]], label %main.pseudo.exit, label %exit
223   ; CHECK: loop.postloop:
224   ; CHECK: [[IDX_POST:%[^ ]+]] = phi i32
225   ; CHECK: [[COND_POST:%[^ ]+]] = icmp slt i32 [[IDX_POST]], %exit.mainloop.at
226   ; CHECK: br i1 [[COND_POST]], label %in.bounds.postloop, label %out.of.bounds.loopexit
228 entry:
229   %len = load i32, i32* %a_len_ptr, !range !2
230   br label %loop
232 loop:
233   %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
234   %idx.next = add i32 %idx, 7
235   %abc = icmp slt i32 %idx, %len
236   br i1 %abc, label %in.bounds, label %out.of.bounds
238 in.bounds:
239   %addr = getelementptr i32, i32* %arr, i32 %idx
240   store i32 0, i32* %addr
241   %next = icmp slt i32 %idx.next, 2147483647
242   br i1 %next, label %loop, label %exit
244 out.of.bounds:
245   ret void
247 exit:
248   ret void
251 ; IV = 100; IV >s -1; IV -= 7; 0 <= Len <= 50. IRCE is allowed.
252 define void @test_05(i32* %arr, i32* %a_len_ptr) {
254 ; CHECK:      @test_05(
255 ; CHECK:      entry:
256 ; CHECK-NEXT:   %len = load i32, i32* %a_len_ptr
257 ; CHECK-NEXT:   %exit.preloop.at = add nsw i32 %len, -1
258 ; CHECK-NEXT:   [[COND1:%[^ ]+]] = icmp sgt i32 100, %exit.preloop.at
259 ; CHECK-NEXT:   br i1 [[COND1]], label %loop.preloop.preheader, label %preloop.pseudo.exit
260 ; CHECK:      loop.preloop.preheader:
261 ; CHECK-NEXT:   br label %loop.preloop
262 ; CHECK:      mainloop:
263 ; CHECK-NEXT:   br label %loop
264 ; CHECK:      loop:
265 ; CHECK-NEXT:   %idx = phi i32 [ %idx.preloop.copy, %mainloop ], [ %idx.next, %in.bounds ]
266 ; CHECK-NEXT:   %idx.next = add i32 %idx, -7
267 ; CHECK-NEXT:   %abc = icmp slt i32 %idx, %len
268 ; CHECK-NEXT:   br i1 true, label %in.bounds, label %out.of.bounds.loopexit1
269 ; CHECK:      in.bounds:
270 ; CHECK-NEXT:   %addr = getelementptr i32, i32* %arr, i32 %idx
271 ; CHECK-NEXT:   store i32 0, i32* %addr
272 ; CHECK-NEXT:   %next = icmp sgt i32 %idx.next, -1
273 ; CHECK-NEXT:   br i1 %next, label %loop, label %exit.loopexit
274 ; CHECK:      loop.preloop:
275 ; CHECK-NEXT:   %idx.preloop = phi i32 [ %idx.next.preloop, %in.bounds.preloop ], [ 100, %loop.preloop.preheader ]
276 ; CHECK-NEXT:   %idx.next.preloop = add i32 %idx.preloop, -7
277 ; CHECK-NEXT:   %abc.preloop = icmp slt i32 %idx.preloop, %len
278 ; CHECK-NEXT:   br i1 %abc.preloop, label %in.bounds.preloop, label %out.of.bounds.loopexit
279 ; CHECK:      in.bounds.preloop:
280 ; CHECK-NEXT:   %addr.preloop = getelementptr i32, i32* %arr, i32 %idx.preloop
281 ; CHECK-NEXT:   store i32 0, i32* %addr.preloop
282 ; CHECK-NEXT:   %next.preloop = icmp sgt i32 %idx.next.preloop, -1
283 ; CHECK-NEXT:   [[COND2:%[^ ]+]] = icmp sgt i32 %idx.next.preloop, %exit.preloop.at
284 ; CHECK-NEXT:   br i1 [[COND2]], label %loop.preloop, label %preloop.exit.selector
285 ; CHECK:      preloop.exit.selector:
286 ; CHECK-NEXT:   %idx.next.preloop.lcssa = phi i32 [ %idx.next.preloop, %in.bounds.preloop ]
287 ; CHECK-NEXT:   [[COND3:%[^ ]+]] = icmp sgt i32 %idx.next.preloop.lcssa, -1
288 ; CHECK-NEXT:   br i1 [[COND3]], label %preloop.pseudo.exit, label %exit
289 ; CHECK:      preloop.pseudo.exit:
290 ; CHECK-NEXT:   %idx.preloop.copy = phi i32 [ 100, %entry ], [ %idx.next.preloop.lcssa, %preloop.exit.selector ]
291 ; CHECK-NEXT:   %indvar.end = phi i32 [ 100, %entry ], [ %idx.next.preloop.lcssa, %preloop.exit.selector ]
292 ; CHECK-NEXT:   br label %mainloop
294 entry:
295   %len = load i32, i32* %a_len_ptr, !range !0
296   br label %loop
298 loop:
299   %idx = phi i32 [ 100, %entry ], [ %idx.next, %in.bounds ]
300   %idx.next = add i32 %idx, -7
301   %abc = icmp slt i32 %idx, %len
302   br i1 %abc, label %in.bounds, label %out.of.bounds
304 in.bounds:
305   %addr = getelementptr i32, i32* %arr, i32 %idx
306   store i32 0, i32* %addr
307   %next = icmp sgt i32 %idx.next, -1
308   br i1 %next, label %loop, label %exit
310 out.of.bounds:
311   ret void
313 exit:
314   ret void
317 ; IV = MAX_INT - 7; IV >u 6; IV -= 7; 10 <= Len <= 50. IRCE is allowed.
318 define void @test_06(i32* %arr, i32* %a_len_ptr) {
320 ; CHECK:      @test_06(
321 ; CHECK:      entry:
322 ; CHECK-NEXT:   %len = load i32, i32* %a_len_ptr
323 ; CHECK-NEXT:   %exit.preloop.at = add nsw i32 %len, -1
324 ; CHECK-NEXT:   [[COND1:%[^ ]+]] = icmp ugt i32 2147483640, %exit.preloop.at
325 ; CHECK-NEXT:   br i1 [[COND1]], label %loop.preloop.preheader, label %preloop.pseudo.exit
326 ; CHECK:      loop.preloop.preheader:
327 ; CHECK-NEXT:   br label %loop.preloop
328 ; CHECK:      mainloop:
329 ; CHECK-NEXT:   br label %loop
330 ; CHECK:      loop:
331 ; CHECK-NEXT:   %idx = phi i32 [ %idx.preloop.copy, %mainloop ], [ %idx.next, %in.bounds ]
332 ; CHECK-NEXT:   %idx.next = add i32 %idx, -7
333 ; CHECK-NEXT:   %abc = icmp slt i32 %idx, %len
334 ; CHECK-NEXT:   br i1 true, label %in.bounds, label %out.of.bounds.loopexit1
335 ; CHECK:      in.bounds:
336 ; CHECK-NEXT:   %addr = getelementptr i32, i32* %arr, i32 %idx
337 ; CHECK-NEXT:   store i32 0, i32* %addr
338 ; CHECK-NEXT:   %next = icmp ugt i32 %idx.next, 6
339 ; CHECK-NEXT:   br i1 %next, label %loop, label %exit.loopexit
340 ; CHECK:      loop.preloop:
341 ; CHECK-NEXT:   %idx.preloop = phi i32 [ %idx.next.preloop, %in.bounds.preloop ], [ 2147483640, %loop.preloop.preheader ]
342 ; CHECK-NEXT:   %idx.next.preloop = add i32 %idx.preloop, -7
343 ; CHECK-NEXT:   %abc.preloop = icmp slt i32 %idx.preloop, %len
344 ; CHECK-NEXT:   br i1 %abc.preloop, label %in.bounds.preloop, label %out.of.bounds.loopexit
345 ; CHECK:      in.bounds.preloop:
346 ; CHECK-NEXT:   %addr.preloop = getelementptr i32, i32* %arr, i32 %idx.preloop
347 ; CHECK-NEXT:   store i32 0, i32* %addr.preloop
348 ; CHECK-NEXT:   %next.preloop = icmp ugt i32 %idx.next.preloop, 6
349 ; CHECK-NEXT:   [[COND2:%[^ ]+]] = icmp ugt i32 %idx.next.preloop, %exit.preloop.at
350 ; CHECK-NEXT:   br i1 [[COND2]], label %loop.preloop, label %preloop.exit.selector
351 ; CHECK:      preloop.exit.selector:
352 ; CHECK-NEXT:   %idx.next.preloop.lcssa = phi i32 [ %idx.next.preloop, %in.bounds.preloop ]
353 ; CHECK-NEXT:   [[COND3:%[^ ]+]] = icmp ugt i32 %idx.next.preloop.lcssa, 6
354 ; CHECK-NEXT:   br i1 [[COND3]], label %preloop.pseudo.exit, label %exit
355 ; CHECK:      preloop.pseudo.exit:
356 ; CHECK-NEXT:   %idx.preloop.copy = phi i32 [ 2147483640, %entry ], [ %idx.next.preloop.lcssa, %preloop.exit.selector ]
357 ; CHECK-NEXT:   %indvar.end = phi i32 [ 2147483640, %entry ], [ %idx.next.preloop.lcssa, %preloop.exit.selector ]
358 ; CHECK-NEXT:   br label %mainloop
360 entry:
361   %len = load i32, i32* %a_len_ptr, !range !3
362   br label %loop
364 loop:
365   %idx = phi i32 [ 2147483640, %entry ], [ %idx.next, %in.bounds ]
366   %idx.next = add i32 %idx, -7
367   %abc = icmp slt i32 %idx, %len
368   br i1 %abc, label %in.bounds, label %out.of.bounds
370 in.bounds:
371   %addr = getelementptr i32, i32* %arr, i32 %idx
372   store i32 0, i32* %addr
373   %next = icmp ugt i32 %idx.next, 6
374   br i1 %next, label %loop, label %exit
376 out.of.bounds:
377   ret void
379 exit:
380   ret void
383 ; IV = MAX_INT - 7; IV >u 5; IV -= 7; 10 <= Len <= 50. IRCE is not allowed,
384 ; because we can cross the 0 border.
385 define void @test_07(i32* %arr, i32* %a_len_ptr) {
387 ; CHECK:      @test_07(
389 entry:
390   %len = load i32, i32* %a_len_ptr, !range !3
391   br label %loop
393 loop:
394   %idx = phi i32 [ 2147483640, %entry ], [ %idx.next, %in.bounds ]
395   %idx.next = add i32 %idx, -7
396   %abc = icmp slt i32 %idx, %len
397   br i1 %abc, label %in.bounds, label %out.of.bounds
399 in.bounds:
400   %addr = getelementptr i32, i32* %arr, i32 %idx
401   store i32 0, i32* %addr
402   %next = icmp ugt i32 %idx.next, 5
403   br i1 %next, label %loop, label %exit
405 out.of.bounds:
406   ret void
408 exit:
409   ret void
412 ; IV = MAX_INT; IV >u 6; IV -= 7; 10 <= Len <= 50. IRCE is allowed.
413 define void @test_08(i32* %arr, i32* %a_len_ptr) {
415 ; CHECK:      @test_08(
416 ; CHECK:      entry:
417 ; CHECK-NEXT:   %len = load i32, i32* %a_len_ptr
418 ; CHECK-NEXT:   %exit.preloop.at = add nsw i32 %len, -1
419 ; CHECK-NEXT:   [[COND1:%[^ ]+]] = icmp ugt i32 2147483647, %exit.preloop.at
420 ; CHECK-NEXT:   br i1 [[COND1]], label %loop.preloop.preheader, label %preloop.pseudo.exit
421 ; CHECK:      loop.preloop.preheader:
422 ; CHECK-NEXT:   br label %loop.preloop
423 ; CHECK:      mainloop:
424 ; CHECK-NEXT:   br label %loop
425 ; CHECK:      loop:
426 ; CHECK-NEXT:   %idx = phi i32 [ %idx.preloop.copy, %mainloop ], [ %idx.next, %in.bounds ]
427 ; CHECK-NEXT:   %idx.next = add i32 %idx, -7
428 ; CHECK-NEXT:   %abc = icmp slt i32 %idx, %len
429 ; CHECK-NEXT:   br i1 true, label %in.bounds, label %out.of.bounds.loopexit1
430 ; CHECK:      in.bounds:
431 ; CHECK-NEXT:   %addr = getelementptr i32, i32* %arr, i32 %idx
432 ; CHECK-NEXT:   store i32 0, i32* %addr
433 ; CHECK-NEXT:   %next = icmp ugt i32 %idx.next, 6
434 ; CHECK-NEXT:   br i1 %next, label %loop, label %exit.loopexit
435 ; CHECK:      loop.preloop:
436 ; CHECK-NEXT:   %idx.preloop = phi i32 [ %idx.next.preloop, %in.bounds.preloop ], [ 2147483647, %loop.preloop.preheader ]
437 ; CHECK-NEXT:   %idx.next.preloop = add i32 %idx.preloop, -7
438 ; CHECK-NEXT:   %abc.preloop = icmp slt i32 %idx.preloop, %len
439 ; CHECK-NEXT:   br i1 %abc.preloop, label %in.bounds.preloop, label %out.of.bounds.loopexit
440 ; CHECK:      in.bounds.preloop:
441 ; CHECK-NEXT:   %addr.preloop = getelementptr i32, i32* %arr, i32 %idx.preloop
442 ; CHECK-NEXT:   store i32 0, i32* %addr.preloop
443 ; CHECK-NEXT:   %next.preloop = icmp ugt i32 %idx.next.preloop, 6
444 ; CHECK-NEXT:   [[COND2:%[^ ]+]] = icmp ugt i32 %idx.next.preloop, %exit.preloop.at
445 ; CHECK-NEXT:   br i1 [[COND2]], label %loop.preloop, label %preloop.exit.selector
446 ; CHECK:      preloop.exit.selector:
447 ; CHECK-NEXT:   %idx.next.preloop.lcssa = phi i32 [ %idx.next.preloop, %in.bounds.preloop ]
448 ; CHECK-NEXT:   [[COND3:%[^ ]+]] = icmp ugt i32 %idx.next.preloop.lcssa, 6
449 ; CHECK-NEXT:   br i1 [[COND3]], label %preloop.pseudo.exit, label %exit
450 ; CHECK:      preloop.pseudo.exit:
451 ; CHECK-NEXT:   %idx.preloop.copy = phi i32 [ 2147483647, %entry ], [ %idx.next.preloop.lcssa, %preloop.exit.selector ]
452 ; CHECK-NEXT:   %indvar.end = phi i32 [ 2147483647, %entry ], [ %idx.next.preloop.lcssa, %preloop.exit.selector ]
453 ; CHECK-NEXT:   br label %mainloop
455 entry:
456   %len = load i32, i32* %a_len_ptr, !range !3
457   br label %loop
459 loop:
460   %idx = phi i32 [ 2147483647, %entry ], [ %idx.next, %in.bounds ]
461   %idx.next = add i32 %idx, -7
462   %abc = icmp slt i32 %idx, %len
463   br i1 %abc, label %in.bounds, label %out.of.bounds
465 in.bounds:
466   %addr = getelementptr i32, i32* %arr, i32 %idx
467   store i32 0, i32* %addr
468   %next = icmp ugt i32 %idx.next, 6
469   br i1 %next, label %loop, label %exit
471 out.of.bounds:
472   ret void
474 exit:
475   ret void
478 !0 = !{i32 0, i32 50}
479 !1 = !{i32 0, i32 2147483640}
480 !2 = !{i32 0, i32 2147483641}
481 !3 = !{i32 10, i32 50}