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>,loop(irce)' -S < %s 2>&1 | FileCheck %s
3
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>
12
13; IV = 0; IV <s 100; IV += 7; 0 <= Len <= 50. IRCE is allowed.
14define void @test_01(i32* %arr, i32* %a_len_ptr) {
15
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
54
55entry:
56  %len = load i32, i32* %a_len_ptr, !range !0
57  br label %loop
58
59loop:
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
64
65in.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
70
71out.of.bounds:
72  ret void
73
74exit:
75  ret void
76}
77
78; IV = 0; IV <s MAX_INT - 7; IV += 7; 0 <= Len <= 50. IRCE is allowed.
79define void @test_02(i32* %arr, i32* %a_len_ptr) {
80
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
119
120entry:
121  %len = load i32, i32* %a_len_ptr, !range !0
122  br label %loop
123
124loop:
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
129
130in.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
135
136out.of.bounds:
137  ret void
138
139exit:
140  ret void
141}
142
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.
145define void @test_03(i32* %arr, i32* %a_len_ptr) {
146
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
185
186entry:
187  %len = load i32, i32* %a_len_ptr, !range !1
188  br label %loop
189
190loop:
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
195
196in.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
201
202out.of.bounds:
203  ret void
204
205exit:
206  ret void
207}
208
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.
212define 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
217
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
222
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
227
228entry:
229  %len = load i32, i32* %a_len_ptr, !range !2
230  br label %loop
231
232loop:
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
237
238in.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
243
244out.of.bounds:
245  ret void
246
247exit:
248  ret void
249}
250
251; IV = 100; IV >s -1; IV -= 7; 0 <= Len <= 50. IRCE is allowed.
252define void @test_05(i32* %arr, i32* %a_len_ptr) {
253
254; CHECK:      @test_05(
255; CHECK:      entry:
256; CHECK-NEXT:   %len = load i32, i32* %a_len_ptr
257; CHECK-NEXT:   %exit.preloop.at = add 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
293
294entry:
295  %len = load i32, i32* %a_len_ptr, !range !0
296  br label %loop
297
298loop:
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
303
304in.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
309
310out.of.bounds:
311  ret void
312
313exit:
314  ret void
315}
316
317; IV = MAX_INT - 7; IV >u 6; IV -= 7; 10 <= Len <= 50. IRCE is allowed.
318define void @test_06(i32* %arr, i32* %a_len_ptr) {
319
320; CHECK:      @test_06(
321; CHECK:      entry:
322; CHECK-NEXT:   %len = load i32, i32* %a_len_ptr
323; CHECK-NEXT:   %exit.preloop.at = add 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
359
360entry:
361  %len = load i32, i32* %a_len_ptr, !range !3
362  br label %loop
363
364loop:
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
369
370in.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
375
376out.of.bounds:
377  ret void
378
379exit:
380  ret void
381}
382
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.
385define void @test_07(i32* %arr, i32* %a_len_ptr) {
386
387; CHECK:      @test_07(
388
389entry:
390  %len = load i32, i32* %a_len_ptr, !range !3
391  br label %loop
392
393loop:
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
398
399in.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
404
405out.of.bounds:
406  ret void
407
408exit:
409  ret void
410}
411
412; IV = MAX_INT; IV >u 6; IV -= 7; 10 <= Len <= 50. IRCE is allowed.
413define void @test_08(i32* %arr, i32* %a_len_ptr) {
414
415; CHECK:      @test_08(
416; CHECK:      entry:
417; CHECK-NEXT:   %len = load i32, i32* %a_len_ptr
418; CHECK-NEXT:   %exit.preloop.at = add 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
454
455entry:
456  %len = load i32, i32* %a_len_ptr, !range !3
457  br label %loop
458
459loop:
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
464
465in.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
470
471out.of.bounds:
472  ret void
473
474exit:
475  ret void
476}
477
478!0 = !{i32 0, i32 50}
479!1 = !{i32 0, i32 2147483640}
480!2 = !{i32 0, i32 2147483641}
481!3 = !{i32 10, i32 50}
482