xref: /llvm-project/llvm/test/Transforms/IRCE/stride_more_than_1.ll (revision eecb99c5f66c8491766628a2925587e20f3b1dbd)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
2; RUN: opt -verify-loop-info -irce-print-changed-loops -passes=irce -S < %s 2>&1 | FileCheck %s
3; RUN: opt -verify-loop-info -irce-print-changed-loops -passes='require<branch-prob>,irce' -S < %s 2>&1 | FileCheck %s
4
5; CHECK: irce: in function test_01: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
6; CHECK: irce: in function test_02: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
7; CHECK: irce: in function test_03: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
8; CHECK: irce: in function test_04: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
9; CHECK: irce: in function test_05: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
10; CHECK: irce: in function test_06: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
11; CHECK-NOT: irce: in function test_07: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
12; CHECK: irce: in function test_08: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
13
14; IV = 0; IV <s 100; IV += 7; 0 <= Len <= 50. IRCE is allowed.
15define void @test_01(ptr %arr, ptr %a_len_ptr) {
16; CHECK-LABEL: define void @test_01
17; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
18; CHECK-NEXT:  entry:
19; CHECK-NEXT:    [[EXIT_MAINLOOP_AT:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0:![0-9]+]]
20; CHECK-NEXT:    [[TMP0:%.*]] = icmp slt i32 0, [[EXIT_MAINLOOP_AT]]
21; CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
22; CHECK:       loop.preheader:
23; CHECK-NEXT:    br label [[LOOP:%.*]]
24; CHECK:       loop:
25; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
26; CHECK-NEXT:    [[IDX_NEXT]] = add nsw i32 [[IDX]], 7
27; CHECK-NEXT:    [[ABC:%.*]] = icmp slt i32 [[IDX]], [[EXIT_MAINLOOP_AT]]
28; CHECK-NEXT:    br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]]
29; CHECK:       in.bounds:
30; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]
31; CHECK-NEXT:    store i32 0, ptr [[ADDR]], align 4
32; CHECK-NEXT:    [[NEXT:%.*]] = icmp slt i32 [[IDX_NEXT]], 100
33; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i32 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]
34; CHECK-NEXT:    br i1 [[TMP1]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
35; CHECK:       main.exit.selector:
36; CHECK-NEXT:    [[IDX_NEXT_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT]], [[IN_BOUNDS]] ]
37; CHECK-NEXT:    [[TMP2:%.*]] = icmp slt i32 [[IDX_NEXT_LCSSA]], 100
38; CHECK-NEXT:    br i1 [[TMP2]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT:%.*]]
39; CHECK:       main.pseudo.exit:
40; CHECK-NEXT:    [[IDX_COPY:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
41; CHECK-NEXT:    [[INDVAR_END:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
42; CHECK-NEXT:    br label [[POSTLOOP:%.*]]
43; CHECK:       out.of.bounds.loopexit:
44; CHECK-NEXT:    br label [[OUT_OF_BOUNDS:%.*]]
45; CHECK:       out.of.bounds.loopexit1:
46; CHECK-NEXT:    br label [[OUT_OF_BOUNDS]]
47; CHECK:       out.of.bounds:
48; CHECK-NEXT:    ret void
49; CHECK:       exit.loopexit:
50; CHECK-NEXT:    br label [[EXIT]]
51; CHECK:       exit:
52; CHECK-NEXT:    ret void
53; CHECK:       postloop:
54; CHECK-NEXT:    br label [[LOOP_POSTLOOP:%.*]]
55; CHECK:       loop.postloop:
56; CHECK-NEXT:    [[IDX_POSTLOOP:%.*]] = phi i32 [ [[IDX_COPY]], [[POSTLOOP]] ], [ [[IDX_NEXT_POSTLOOP:%.*]], [[IN_BOUNDS_POSTLOOP:%.*]] ]
57; CHECK-NEXT:    [[IDX_NEXT_POSTLOOP]] = add i32 [[IDX_POSTLOOP]], 7
58; CHECK-NEXT:    [[ABC_POSTLOOP:%.*]] = icmp slt i32 [[IDX_POSTLOOP]], [[EXIT_MAINLOOP_AT]]
59; CHECK-NEXT:    br i1 [[ABC_POSTLOOP]], label [[IN_BOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]]
60; CHECK:       in.bounds.postloop:
61; CHECK-NEXT:    [[ADDR_POSTLOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_POSTLOOP]]
62; CHECK-NEXT:    store i32 0, ptr [[ADDR_POSTLOOP]], align 4
63; CHECK-NEXT:    [[NEXT_POSTLOOP:%.*]] = icmp slt i32 [[IDX_NEXT_POSTLOOP]], 100
64; CHECK-NEXT:    br i1 [[NEXT_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT:%.*]], !llvm.loop [[LOOP1:![0-9]+]], !loop_constrainer.loop.clone !6
65;
66
67entry:
68  %len = load i32, ptr %a_len_ptr, !range !0
69  br label %loop
70
71loop:
72  %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
73  %idx.next = add i32 %idx, 7
74  %abc = icmp slt i32 %idx, %len
75  br i1 %abc, label %in.bounds, label %out.of.bounds
76
77in.bounds:
78  %addr = getelementptr i32, ptr %arr, i32 %idx
79  store i32 0, ptr %addr
80  %next = icmp slt i32 %idx.next, 100
81  br i1 %next, label %loop, label %exit
82
83out.of.bounds:
84  ret void
85
86exit:
87  ret void
88}
89
90; IV = 0; IV <s MAX_INT - 7; IV += 7; 0 <= Len <= 50. IRCE is allowed.
91define void @test_02(ptr %arr, ptr %a_len_ptr) {
92; CHECK-LABEL: define void @test_02
93; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
94; CHECK-NEXT:  entry:
95; CHECK-NEXT:    [[EXIT_MAINLOOP_AT:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0]]
96; CHECK-NEXT:    [[TMP0:%.*]] = icmp slt i32 0, [[EXIT_MAINLOOP_AT]]
97; CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
98; CHECK:       loop.preheader:
99; CHECK-NEXT:    br label [[LOOP:%.*]]
100; CHECK:       loop:
101; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
102; CHECK-NEXT:    [[IDX_NEXT]] = add nsw i32 [[IDX]], 7
103; CHECK-NEXT:    [[ABC:%.*]] = icmp slt i32 [[IDX]], [[EXIT_MAINLOOP_AT]]
104; CHECK-NEXT:    br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]]
105; CHECK:       in.bounds:
106; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]
107; CHECK-NEXT:    store i32 0, ptr [[ADDR]], align 4
108; CHECK-NEXT:    [[NEXT:%.*]] = icmp slt i32 [[IDX_NEXT]], 2147483640
109; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i32 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]
110; CHECK-NEXT:    br i1 [[TMP1]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
111; CHECK:       main.exit.selector:
112; CHECK-NEXT:    [[IDX_NEXT_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT]], [[IN_BOUNDS]] ]
113; CHECK-NEXT:    [[TMP2:%.*]] = icmp slt i32 [[IDX_NEXT_LCSSA]], 2147483640
114; CHECK-NEXT:    br i1 [[TMP2]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT:%.*]]
115; CHECK:       main.pseudo.exit:
116; CHECK-NEXT:    [[IDX_COPY:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
117; CHECK-NEXT:    [[INDVAR_END:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
118; CHECK-NEXT:    br label [[POSTLOOP:%.*]]
119; CHECK:       out.of.bounds.loopexit:
120; CHECK-NEXT:    br label [[OUT_OF_BOUNDS:%.*]]
121; CHECK:       out.of.bounds.loopexit1:
122; CHECK-NEXT:    br label [[OUT_OF_BOUNDS]]
123; CHECK:       out.of.bounds:
124; CHECK-NEXT:    ret void
125; CHECK:       exit.loopexit:
126; CHECK-NEXT:    br label [[EXIT]]
127; CHECK:       exit:
128; CHECK-NEXT:    ret void
129; CHECK:       postloop:
130; CHECK-NEXT:    br label [[LOOP_POSTLOOP:%.*]]
131; CHECK:       loop.postloop:
132; CHECK-NEXT:    [[IDX_POSTLOOP:%.*]] = phi i32 [ [[IDX_COPY]], [[POSTLOOP]] ], [ [[IDX_NEXT_POSTLOOP:%.*]], [[IN_BOUNDS_POSTLOOP:%.*]] ]
133; CHECK-NEXT:    [[IDX_NEXT_POSTLOOP]] = add i32 [[IDX_POSTLOOP]], 7
134; CHECK-NEXT:    [[ABC_POSTLOOP:%.*]] = icmp slt i32 [[IDX_POSTLOOP]], [[EXIT_MAINLOOP_AT]]
135; CHECK-NEXT:    br i1 [[ABC_POSTLOOP]], label [[IN_BOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]]
136; CHECK:       in.bounds.postloop:
137; CHECK-NEXT:    [[ADDR_POSTLOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_POSTLOOP]]
138; CHECK-NEXT:    store i32 0, ptr [[ADDR_POSTLOOP]], align 4
139; CHECK-NEXT:    [[NEXT_POSTLOOP:%.*]] = icmp slt i32 [[IDX_NEXT_POSTLOOP]], 2147483640
140; CHECK-NEXT:    br i1 [[NEXT_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT:%.*]], !llvm.loop [[LOOP7:![0-9]+]], !loop_constrainer.loop.clone !6
141;
142
143entry:
144  %len = load i32, ptr %a_len_ptr, !range !0
145  br label %loop
146
147loop:
148  %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
149  %idx.next = add i32 %idx, 7
150  %abc = icmp slt i32 %idx, %len
151  br i1 %abc, label %in.bounds, label %out.of.bounds
152
153in.bounds:
154  %addr = getelementptr i32, ptr %arr, i32 %idx
155  store i32 0, ptr %addr
156  %next = icmp slt i32 %idx.next, 2147483640
157  br i1 %next, label %loop, label %exit
158
159out.of.bounds:
160  ret void
161
162exit:
163  ret void
164}
165
166; IV = 0; IV <s MAX_INT; IV += 7; 0 <= Len <= MAX_INT - 7. This is the greatest
167; value of Len for which IRCE is allowed.
168define void @test_03(ptr %arr, ptr %a_len_ptr) {
169; CHECK-LABEL: define void @test_03
170; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
171; CHECK-NEXT:  entry:
172; CHECK-NEXT:    [[EXIT_MAINLOOP_AT:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG8:![0-9]+]]
173; CHECK-NEXT:    [[TMP0:%.*]] = icmp slt i32 0, [[EXIT_MAINLOOP_AT]]
174; CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
175; CHECK:       loop.preheader:
176; CHECK-NEXT:    br label [[LOOP:%.*]]
177; CHECK:       loop:
178; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
179; CHECK-NEXT:    [[IDX_NEXT]] = add nsw i32 [[IDX]], 7
180; CHECK-NEXT:    [[ABC:%.*]] = icmp slt i32 [[IDX]], [[EXIT_MAINLOOP_AT]]
181; CHECK-NEXT:    br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]]
182; CHECK:       in.bounds:
183; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]
184; CHECK-NEXT:    store i32 0, ptr [[ADDR]], align 4
185; CHECK-NEXT:    [[NEXT:%.*]] = icmp slt i32 [[IDX_NEXT]], 2147483647
186; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i32 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]
187; CHECK-NEXT:    br i1 [[TMP1]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
188; CHECK:       main.exit.selector:
189; CHECK-NEXT:    [[IDX_NEXT_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT]], [[IN_BOUNDS]] ]
190; CHECK-NEXT:    [[TMP2:%.*]] = icmp slt i32 [[IDX_NEXT_LCSSA]], 2147483647
191; CHECK-NEXT:    br i1 [[TMP2]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT:%.*]]
192; CHECK:       main.pseudo.exit:
193; CHECK-NEXT:    [[IDX_COPY:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
194; CHECK-NEXT:    [[INDVAR_END:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
195; CHECK-NEXT:    br label [[POSTLOOP:%.*]]
196; CHECK:       out.of.bounds.loopexit:
197; CHECK-NEXT:    br label [[OUT_OF_BOUNDS:%.*]]
198; CHECK:       out.of.bounds.loopexit1:
199; CHECK-NEXT:    br label [[OUT_OF_BOUNDS]]
200; CHECK:       out.of.bounds:
201; CHECK-NEXT:    ret void
202; CHECK:       exit.loopexit:
203; CHECK-NEXT:    br label [[EXIT]]
204; CHECK:       exit:
205; CHECK-NEXT:    ret void
206; CHECK:       postloop:
207; CHECK-NEXT:    br label [[LOOP_POSTLOOP:%.*]]
208; CHECK:       loop.postloop:
209; CHECK-NEXT:    [[IDX_POSTLOOP:%.*]] = phi i32 [ [[IDX_COPY]], [[POSTLOOP]] ], [ [[IDX_NEXT_POSTLOOP:%.*]], [[IN_BOUNDS_POSTLOOP:%.*]] ]
210; CHECK-NEXT:    [[IDX_NEXT_POSTLOOP]] = add i32 [[IDX_POSTLOOP]], 7
211; CHECK-NEXT:    [[ABC_POSTLOOP:%.*]] = icmp slt i32 [[IDX_POSTLOOP]], [[EXIT_MAINLOOP_AT]]
212; CHECK-NEXT:    br i1 [[ABC_POSTLOOP]], label [[IN_BOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]]
213; CHECK:       in.bounds.postloop:
214; CHECK-NEXT:    [[ADDR_POSTLOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_POSTLOOP]]
215; CHECK-NEXT:    store i32 0, ptr [[ADDR_POSTLOOP]], align 4
216; CHECK-NEXT:    [[NEXT_POSTLOOP:%.*]] = icmp slt i32 [[IDX_NEXT_POSTLOOP]], 2147483647
217; CHECK-NEXT:    br i1 [[NEXT_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT:%.*]], !llvm.loop [[LOOP9:![0-9]+]], !loop_constrainer.loop.clone !6
218;
219
220entry:
221  %len = load i32, ptr %a_len_ptr, !range !1
222  br label %loop
223
224loop:
225  %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
226  %idx.next = add i32 %idx, 7
227  %abc = icmp slt i32 %idx, %len
228  br i1 %abc, label %in.bounds, label %out.of.bounds
229
230in.bounds:
231  %addr = getelementptr i32, ptr %arr, i32 %idx
232  store i32 0, ptr %addr
233  %next = icmp slt i32 %idx.next, 2147483647
234  br i1 %next, label %loop, label %exit
235
236out.of.bounds:
237  ret void
238
239exit:
240  ret void
241}
242
243; IV = 0; IV <s MAX_INT; IV += 7; 0 <= Len <= MAX_INT - 6. IRCE is allowed
244; because the branch would fail once idx.next == MAX_INT - 1 keeping the
245; access in bounds.
246define void @test_04(ptr %arr, ptr %a_len_ptr) {
247; CHECK-LABEL: define void @test_04
248; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
249; CHECK-NEXT:  entry:
250; CHECK-NEXT:    [[EXIT_MAINLOOP_AT:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG10:![0-9]+]]
251; CHECK-NEXT:    [[TMP0:%.*]] = icmp slt i32 0, [[EXIT_MAINLOOP_AT]]
252; CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
253; CHECK:       loop.preheader:
254; CHECK-NEXT:    br label [[LOOP:%.*]]
255; CHECK:       loop:
256; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
257; CHECK-NEXT:    [[IDX_NEXT]] = add nsw i32 [[IDX]], 7
258; CHECK-NEXT:    [[ABC:%.*]] = icmp slt i32 [[IDX]], [[EXIT_MAINLOOP_AT]]
259; CHECK-NEXT:    br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]]
260; CHECK:       in.bounds:
261; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]
262; CHECK-NEXT:    store i32 0, ptr [[ADDR]], align 4
263; CHECK-NEXT:    [[NEXT:%.*]] = icmp slt i32 [[IDX_NEXT]], 2147483647
264; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i32 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]
265; CHECK-NEXT:    br i1 [[TMP1]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
266; CHECK:       main.exit.selector:
267; CHECK-NEXT:    [[IDX_NEXT_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT]], [[IN_BOUNDS]] ]
268; CHECK-NEXT:    [[TMP2:%.*]] = icmp slt i32 [[IDX_NEXT_LCSSA]], 2147483647
269; CHECK-NEXT:    br i1 [[TMP2]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT:%.*]]
270; CHECK:       main.pseudo.exit:
271; CHECK-NEXT:    [[IDX_COPY:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
272; CHECK-NEXT:    [[INDVAR_END:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
273; CHECK-NEXT:    br label [[POSTLOOP:%.*]]
274; CHECK:       out.of.bounds.loopexit:
275; CHECK-NEXT:    br label [[OUT_OF_BOUNDS:%.*]]
276; CHECK:       out.of.bounds.loopexit1:
277; CHECK-NEXT:    br label [[OUT_OF_BOUNDS]]
278; CHECK:       out.of.bounds:
279; CHECK-NEXT:    ret void
280; CHECK:       exit.loopexit:
281; CHECK-NEXT:    br label [[EXIT]]
282; CHECK:       exit:
283; CHECK-NEXT:    ret void
284; CHECK:       postloop:
285; CHECK-NEXT:    br label [[LOOP_POSTLOOP:%.*]]
286; CHECK:       loop.postloop:
287; CHECK-NEXT:    [[IDX_POSTLOOP:%.*]] = phi i32 [ [[IDX_COPY]], [[POSTLOOP]] ], [ [[IDX_NEXT_POSTLOOP:%.*]], [[IN_BOUNDS_POSTLOOP:%.*]] ]
288; CHECK-NEXT:    [[IDX_NEXT_POSTLOOP]] = add i32 [[IDX_POSTLOOP]], 7
289; CHECK-NEXT:    [[ABC_POSTLOOP:%.*]] = icmp slt i32 [[IDX_POSTLOOP]], [[EXIT_MAINLOOP_AT]]
290; CHECK-NEXT:    br i1 [[ABC_POSTLOOP]], label [[IN_BOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]]
291; CHECK:       in.bounds.postloop:
292; CHECK-NEXT:    [[ADDR_POSTLOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_POSTLOOP]]
293; CHECK-NEXT:    store i32 0, ptr [[ADDR_POSTLOOP]], align 4
294; CHECK-NEXT:    [[NEXT_POSTLOOP:%.*]] = icmp slt i32 [[IDX_NEXT_POSTLOOP]], 2147483647
295; CHECK-NEXT:    br i1 [[NEXT_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT:%.*]], !llvm.loop [[LOOP11:![0-9]+]], !loop_constrainer.loop.clone !6
296;
297
298
299
300entry:
301  %len = load i32, ptr %a_len_ptr, !range !2
302  br label %loop
303
304loop:
305  %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
306  %idx.next = add i32 %idx, 7
307  %abc = icmp slt i32 %idx, %len
308  br i1 %abc, label %in.bounds, label %out.of.bounds
309
310in.bounds:
311  %addr = getelementptr i32, ptr %arr, i32 %idx
312  store i32 0, ptr %addr
313  %next = icmp slt i32 %idx.next, 2147483647
314  br i1 %next, label %loop, label %exit
315
316out.of.bounds:
317  ret void
318
319exit:
320  ret void
321}
322
323; IV = 100; IV >s -1; IV -= 7; 0 <= Len <= 50. IRCE is allowed.
324define void @test_05(ptr %arr, ptr %a_len_ptr) {
325; CHECK-LABEL: define void @test_05
326; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
327; CHECK-NEXT:  entry:
328; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0]]
329; CHECK-NEXT:    [[EXIT_PRELOOP_AT:%.*]] = add nsw i32 [[LEN]], -1
330; CHECK-NEXT:    [[TMP0:%.*]] = icmp sgt i32 100, [[EXIT_PRELOOP_AT]]
331; CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP_PRELOOP_PREHEADER:%.*]], label [[PRELOOP_PSEUDO_EXIT:%.*]]
332; CHECK:       loop.preloop.preheader:
333; CHECK-NEXT:    br label [[LOOP_PRELOOP:%.*]]
334; CHECK:       mainloop:
335; CHECK-NEXT:    br label [[LOOP:%.*]]
336; CHECK:       loop:
337; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ [[IDX_PRELOOP_COPY:%.*]], [[MAINLOOP:%.*]] ], [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ]
338; CHECK-NEXT:    [[IDX_NEXT]] = add nsw i32 [[IDX]], -7
339; CHECK-NEXT:    [[ABC:%.*]] = icmp slt i32 [[IDX]], [[LEN]]
340; CHECK-NEXT:    br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]]
341; CHECK:       in.bounds:
342; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]
343; CHECK-NEXT:    store i32 0, ptr [[ADDR]], align 4
344; CHECK-NEXT:    [[NEXT:%.*]] = icmp sgt i32 [[IDX_NEXT]], -1
345; CHECK-NEXT:    br i1 [[NEXT]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
346; CHECK:       out.of.bounds.loopexit:
347; CHECK-NEXT:    br label [[OUT_OF_BOUNDS:%.*]]
348; CHECK:       out.of.bounds.loopexit1:
349; CHECK-NEXT:    br label [[OUT_OF_BOUNDS]]
350; CHECK:       out.of.bounds:
351; CHECK-NEXT:    ret void
352; CHECK:       exit.loopexit:
353; CHECK-NEXT:    br label [[EXIT:%.*]]
354; CHECK:       exit:
355; CHECK-NEXT:    ret void
356; CHECK:       loop.preloop:
357; CHECK-NEXT:    [[IDX_PRELOOP:%.*]] = phi i32 [ [[IDX_NEXT_PRELOOP:%.*]], [[IN_BOUNDS_PRELOOP:%.*]] ], [ 100, [[LOOP_PRELOOP_PREHEADER]] ]
358; CHECK-NEXT:    [[IDX_NEXT_PRELOOP]] = add i32 [[IDX_PRELOOP]], -7
359; CHECK-NEXT:    [[ABC_PRELOOP:%.*]] = icmp slt i32 [[IDX_PRELOOP]], [[LEN]]
360; CHECK-NEXT:    br i1 [[ABC_PRELOOP]], label [[IN_BOUNDS_PRELOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]]
361; CHECK:       in.bounds.preloop:
362; CHECK-NEXT:    [[ADDR_PRELOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_PRELOOP]]
363; CHECK-NEXT:    store i32 0, ptr [[ADDR_PRELOOP]], align 4
364; CHECK-NEXT:    [[NEXT_PRELOOP:%.*]] = icmp sgt i32 [[IDX_NEXT_PRELOOP]], -1
365; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i32 [[IDX_NEXT_PRELOOP]], [[EXIT_PRELOOP_AT]]
366; CHECK-NEXT:    br i1 [[TMP1]], label [[LOOP_PRELOOP]], label [[PRELOOP_EXIT_SELECTOR:%.*]], !llvm.loop [[LOOP12:![0-9]+]], !loop_constrainer.loop.clone !6
367; CHECK:       preloop.exit.selector:
368; CHECK-NEXT:    [[IDX_NEXT_PRELOOP_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT_PRELOOP]], [[IN_BOUNDS_PRELOOP]] ]
369; CHECK-NEXT:    [[TMP2:%.*]] = icmp sgt i32 [[IDX_NEXT_PRELOOP_LCSSA]], -1
370; CHECK-NEXT:    br i1 [[TMP2]], label [[PRELOOP_PSEUDO_EXIT]], label [[EXIT]]
371; CHECK:       preloop.pseudo.exit:
372; CHECK-NEXT:    [[IDX_PRELOOP_COPY]] = phi i32 [ 100, [[ENTRY:%.*]] ], [ [[IDX_NEXT_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ]
373; CHECK-NEXT:    [[INDVAR_END:%.*]] = phi i32 [ 100, [[ENTRY]] ], [ [[IDX_NEXT_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ]
374; CHECK-NEXT:    br label [[MAINLOOP]]
375;
376
377entry:
378  %len = load i32, ptr %a_len_ptr, !range !0
379  br label %loop
380
381loop:
382  %idx = phi i32 [ 100, %entry ], [ %idx.next, %in.bounds ]
383  %idx.next = add i32 %idx, -7
384  %abc = icmp slt i32 %idx, %len
385  br i1 %abc, label %in.bounds, label %out.of.bounds
386
387in.bounds:
388  %addr = getelementptr i32, ptr %arr, i32 %idx
389  store i32 0, ptr %addr
390  %next = icmp sgt i32 %idx.next, -1
391  br i1 %next, label %loop, label %exit
392
393out.of.bounds:
394  ret void
395
396exit:
397  ret void
398}
399
400; IV = MAX_INT - 7; IV >u 6; IV -= 7; 10 <= Len <= 50. IRCE is allowed.
401define void @test_06(ptr %arr, ptr %a_len_ptr) {
402; CHECK-LABEL: define void @test_06
403; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
404; CHECK-NEXT:  entry:
405; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG13:![0-9]+]]
406; CHECK-NEXT:    [[EXIT_PRELOOP_AT:%.*]] = add nsw i32 [[LEN]], -1
407; CHECK-NEXT:    [[TMP0:%.*]] = icmp ugt i32 2147483640, [[EXIT_PRELOOP_AT]]
408; CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP_PRELOOP_PREHEADER:%.*]], label [[PRELOOP_PSEUDO_EXIT:%.*]]
409; CHECK:       loop.preloop.preheader:
410; CHECK-NEXT:    br label [[LOOP_PRELOOP:%.*]]
411; CHECK:       mainloop:
412; CHECK-NEXT:    br label [[LOOP:%.*]]
413; CHECK:       loop:
414; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ [[IDX_PRELOOP_COPY:%.*]], [[MAINLOOP:%.*]] ], [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ]
415; CHECK-NEXT:    [[IDX_NEXT]] = add i32 [[IDX]], -7
416; CHECK-NEXT:    [[ABC:%.*]] = icmp slt i32 [[IDX]], [[LEN]]
417; CHECK-NEXT:    br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]]
418; CHECK:       in.bounds:
419; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]
420; CHECK-NEXT:    store i32 0, ptr [[ADDR]], align 4
421; CHECK-NEXT:    [[NEXT:%.*]] = icmp ugt i32 [[IDX_NEXT]], 6
422; CHECK-NEXT:    br i1 [[NEXT]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
423; CHECK:       out.of.bounds.loopexit:
424; CHECK-NEXT:    br label [[OUT_OF_BOUNDS:%.*]]
425; CHECK:       out.of.bounds.loopexit1:
426; CHECK-NEXT:    br label [[OUT_OF_BOUNDS]]
427; CHECK:       out.of.bounds:
428; CHECK-NEXT:    ret void
429; CHECK:       exit.loopexit:
430; CHECK-NEXT:    br label [[EXIT:%.*]]
431; CHECK:       exit:
432; CHECK-NEXT:    ret void
433; CHECK:       loop.preloop:
434; CHECK-NEXT:    [[IDX_PRELOOP:%.*]] = phi i32 [ [[IDX_NEXT_PRELOOP:%.*]], [[IN_BOUNDS_PRELOOP:%.*]] ], [ 2147483640, [[LOOP_PRELOOP_PREHEADER]] ]
435; CHECK-NEXT:    [[IDX_NEXT_PRELOOP]] = add i32 [[IDX_PRELOOP]], -7
436; CHECK-NEXT:    [[ABC_PRELOOP:%.*]] = icmp slt i32 [[IDX_PRELOOP]], [[LEN]]
437; CHECK-NEXT:    br i1 [[ABC_PRELOOP]], label [[IN_BOUNDS_PRELOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]]
438; CHECK:       in.bounds.preloop:
439; CHECK-NEXT:    [[ADDR_PRELOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_PRELOOP]]
440; CHECK-NEXT:    store i32 0, ptr [[ADDR_PRELOOP]], align 4
441; CHECK-NEXT:    [[NEXT_PRELOOP:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP]], 6
442; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP]], [[EXIT_PRELOOP_AT]]
443; CHECK-NEXT:    br i1 [[TMP1]], label [[LOOP_PRELOOP]], label [[PRELOOP_EXIT_SELECTOR:%.*]], !llvm.loop [[LOOP14:![0-9]+]], !loop_constrainer.loop.clone !6
444; CHECK:       preloop.exit.selector:
445; CHECK-NEXT:    [[IDX_NEXT_PRELOOP_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT_PRELOOP]], [[IN_BOUNDS_PRELOOP]] ]
446; CHECK-NEXT:    [[TMP2:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP_LCSSA]], 6
447; CHECK-NEXT:    br i1 [[TMP2]], label [[PRELOOP_PSEUDO_EXIT]], label [[EXIT]]
448; CHECK:       preloop.pseudo.exit:
449; CHECK-NEXT:    [[IDX_PRELOOP_COPY]] = phi i32 [ 2147483640, [[ENTRY:%.*]] ], [ [[IDX_NEXT_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ]
450; CHECK-NEXT:    [[INDVAR_END:%.*]] = phi i32 [ 2147483640, [[ENTRY]] ], [ [[IDX_NEXT_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ]
451; CHECK-NEXT:    br label [[MAINLOOP]]
452;
453
454entry:
455  %len = load i32, ptr %a_len_ptr, !range !3
456  br label %loop
457
458loop:
459  %idx = phi i32 [ 2147483640, %entry ], [ %idx.next, %in.bounds ]
460  %idx.next = add i32 %idx, -7
461  %abc = icmp slt i32 %idx, %len
462  br i1 %abc, label %in.bounds, label %out.of.bounds
463
464in.bounds:
465  %addr = getelementptr i32, ptr %arr, i32 %idx
466  store i32 0, ptr %addr
467  %next = icmp ugt i32 %idx.next, 6
468  br i1 %next, label %loop, label %exit
469
470out.of.bounds:
471  ret void
472
473exit:
474  ret void
475}
476
477; IV = MAX_INT - 7; IV >u 5; IV -= 7; 10 <= Len <= 50. IRCE is not allowed,
478; because we can cross the 0 border.
479define void @test_07(ptr %arr, ptr %a_len_ptr) {
480; CHECK-LABEL: define void @test_07
481; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
482; CHECK-NEXT:  entry:
483; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG13]]
484; CHECK-NEXT:    br label [[LOOP:%.*]]
485; CHECK:       loop:
486; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ 2147483640, [[ENTRY:%.*]] ], [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ]
487; CHECK-NEXT:    [[IDX_NEXT]] = add i32 [[IDX]], -7
488; CHECK-NEXT:    [[ABC:%.*]] = icmp slt i32 [[IDX]], [[LEN]]
489; CHECK-NEXT:    br i1 [[ABC]], label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS:%.*]]
490; CHECK:       in.bounds:
491; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]
492; CHECK-NEXT:    store i32 0, ptr [[ADDR]], align 4
493; CHECK-NEXT:    [[NEXT:%.*]] = icmp ugt i32 [[IDX_NEXT]], 5
494; CHECK-NEXT:    br i1 [[NEXT]], label [[LOOP]], label [[EXIT:%.*]]
495; CHECK:       out.of.bounds:
496; CHECK-NEXT:    ret void
497; CHECK:       exit:
498; CHECK-NEXT:    ret void
499;
500
501entry:
502  %len = load i32, ptr %a_len_ptr, !range !3
503  br label %loop
504
505loop:
506  %idx = phi i32 [ 2147483640, %entry ], [ %idx.next, %in.bounds ]
507  %idx.next = add i32 %idx, -7
508  %abc = icmp slt i32 %idx, %len
509  br i1 %abc, label %in.bounds, label %out.of.bounds
510
511in.bounds:
512  %addr = getelementptr i32, ptr %arr, i32 %idx
513  store i32 0, ptr %addr
514  %next = icmp ugt i32 %idx.next, 5
515  br i1 %next, label %loop, label %exit
516
517out.of.bounds:
518  ret void
519
520exit:
521  ret void
522}
523
524; IV = MAX_INT; IV >u 6; IV -= 7; 10 <= Len <= 50. IRCE is allowed.
525define void @test_08(ptr %arr, ptr %a_len_ptr) {
526; CHECK-LABEL: define void @test_08
527; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
528; CHECK-NEXT:  entry:
529; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG13]]
530; CHECK-NEXT:    [[EXIT_PRELOOP_AT:%.*]] = add nsw i32 [[LEN]], -1
531; CHECK-NEXT:    [[TMP0:%.*]] = icmp ugt i32 2147483647, [[EXIT_PRELOOP_AT]]
532; CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP_PRELOOP_PREHEADER:%.*]], label [[PRELOOP_PSEUDO_EXIT:%.*]]
533; CHECK:       loop.preloop.preheader:
534; CHECK-NEXT:    br label [[LOOP_PRELOOP:%.*]]
535; CHECK:       mainloop:
536; CHECK-NEXT:    br label [[LOOP:%.*]]
537; CHECK:       loop:
538; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ [[IDX_PRELOOP_COPY:%.*]], [[MAINLOOP:%.*]] ], [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ]
539; CHECK-NEXT:    [[IDX_NEXT]] = add i32 [[IDX]], -7
540; CHECK-NEXT:    [[ABC:%.*]] = icmp slt i32 [[IDX]], [[LEN]]
541; CHECK-NEXT:    br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]]
542; CHECK:       in.bounds:
543; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]
544; CHECK-NEXT:    store i32 0, ptr [[ADDR]], align 4
545; CHECK-NEXT:    [[NEXT:%.*]] = icmp ugt i32 [[IDX_NEXT]], 6
546; CHECK-NEXT:    br i1 [[NEXT]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
547; CHECK:       out.of.bounds.loopexit:
548; CHECK-NEXT:    br label [[OUT_OF_BOUNDS:%.*]]
549; CHECK:       out.of.bounds.loopexit1:
550; CHECK-NEXT:    br label [[OUT_OF_BOUNDS]]
551; CHECK:       out.of.bounds:
552; CHECK-NEXT:    ret void
553; CHECK:       exit.loopexit:
554; CHECK-NEXT:    br label [[EXIT:%.*]]
555; CHECK:       exit:
556; CHECK-NEXT:    ret void
557; CHECK:       loop.preloop:
558; CHECK-NEXT:    [[IDX_PRELOOP:%.*]] = phi i32 [ [[IDX_NEXT_PRELOOP:%.*]], [[IN_BOUNDS_PRELOOP:%.*]] ], [ 2147483647, [[LOOP_PRELOOP_PREHEADER]] ]
559; CHECK-NEXT:    [[IDX_NEXT_PRELOOP]] = add i32 [[IDX_PRELOOP]], -7
560; CHECK-NEXT:    [[ABC_PRELOOP:%.*]] = icmp slt i32 [[IDX_PRELOOP]], [[LEN]]
561; CHECK-NEXT:    br i1 [[ABC_PRELOOP]], label [[IN_BOUNDS_PRELOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]]
562; CHECK:       in.bounds.preloop:
563; CHECK-NEXT:    [[ADDR_PRELOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_PRELOOP]]
564; CHECK-NEXT:    store i32 0, ptr [[ADDR_PRELOOP]], align 4
565; CHECK-NEXT:    [[NEXT_PRELOOP:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP]], 6
566; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP]], [[EXIT_PRELOOP_AT]]
567; CHECK-NEXT:    br i1 [[TMP1]], label [[LOOP_PRELOOP]], label [[PRELOOP_EXIT_SELECTOR:%.*]], !llvm.loop [[LOOP15:![0-9]+]], !loop_constrainer.loop.clone !6
568; CHECK:       preloop.exit.selector:
569; CHECK-NEXT:    [[IDX_NEXT_PRELOOP_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT_PRELOOP]], [[IN_BOUNDS_PRELOOP]] ]
570; CHECK-NEXT:    [[TMP2:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP_LCSSA]], 6
571; CHECK-NEXT:    br i1 [[TMP2]], label [[PRELOOP_PSEUDO_EXIT]], label [[EXIT]]
572; CHECK:       preloop.pseudo.exit:
573; CHECK-NEXT:    [[IDX_PRELOOP_COPY]] = phi i32 [ 2147483647, [[ENTRY:%.*]] ], [ [[IDX_NEXT_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ]
574; CHECK-NEXT:    [[INDVAR_END:%.*]] = phi i32 [ 2147483647, [[ENTRY]] ], [ [[IDX_NEXT_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ]
575; CHECK-NEXT:    br label [[MAINLOOP]]
576;
577
578entry:
579  %len = load i32, ptr %a_len_ptr, !range !3
580  br label %loop
581
582loop:
583  %idx = phi i32 [ 2147483647, %entry ], [ %idx.next, %in.bounds ]
584  %idx.next = add i32 %idx, -7
585  %abc = icmp slt i32 %idx, %len
586  br i1 %abc, label %in.bounds, label %out.of.bounds
587
588in.bounds:
589  %addr = getelementptr i32, ptr %arr, i32 %idx
590  store i32 0, ptr %addr
591  %next = icmp ugt i32 %idx.next, 6
592  br i1 %next, label %loop, label %exit
593
594out.of.bounds:
595  ret void
596
597exit:
598  ret void
599}
600
601; IRCE is legal here.
602; Here how it is done if the step was 1: https://godbolt.org/z/jEqWaseWc
603; It is also legal for step 4. Proof:
604; - Capacity check ensures that iv < limit <= SINT_MAX - 3, meaning that
605;   iv <= SINT_MAX - 4.
606; - Because of this, iv.next is always computed w/o overflow.
607; - The loop goes to backedge as long as iv < capacity - 3 && iv < num.elements - 4.
608; - So iterating up to smin(capacity - 3, num.elements - 4) should be safe.
609; - Proof by alive2: https://alive2.llvm.org/ce/z/vEhMxa
610define i32 @test_09(ptr %p, ptr %capacity_p, ptr %num_elements_p) {
611; CHECK-LABEL: define i32 @test_09
612; CHECK-SAME: (ptr [[P:%.*]], ptr [[CAPACITY_P:%.*]], ptr [[NUM_ELEMENTS_P:%.*]]) {
613; CHECK-NEXT:  entry:
614; CHECK-NEXT:    [[CAPACITY:%.*]] = load i32, ptr [[CAPACITY_P]], align 4, !range [[RNG16:![0-9]+]]
615; CHECK-NEXT:    [[NUM_ELEMENTS:%.*]] = load i32, ptr [[NUM_ELEMENTS_P]], align 4, !range [[RNG16]]
616; CHECK-NEXT:    [[LIMIT:%.*]] = sub i32 [[CAPACITY]], 3
617; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[CAPACITY]], -3
618; CHECK-NEXT:    [[TMP1:%.*]] = add nuw i32 [[CAPACITY]], 2147483646
619; CHECK-NEXT:    [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[TMP1]], i32 0)
620; CHECK-NEXT:    [[TMP2:%.*]] = sub i32 [[TMP0]], [[SMAX]]
621; CHECK-NEXT:    [[SMIN:%.*]] = call i32 @llvm.smin.i32(i32 [[LIMIT]], i32 0)
622; CHECK-NEXT:    [[SMAX2:%.*]] = call i32 @llvm.smax.i32(i32 [[SMIN]], i32 -1)
623; CHECK-NEXT:    [[TMP3:%.*]] = add nsw i32 [[SMAX2]], 1
624; CHECK-NEXT:    [[TMP4:%.*]] = mul i32 [[TMP2]], [[TMP3]]
625; CHECK-NEXT:    [[SMIN3:%.*]] = call i32 @llvm.smin.i32(i32 [[NUM_ELEMENTS]], i32 [[TMP4]])
626; CHECK-NEXT:    [[EXIT_MAINLOOP_AT:%.*]] = call i32 @llvm.smax.i32(i32 [[SMIN3]], i32 0)
627; CHECK-NEXT:    [[TMP5:%.*]] = icmp slt i32 0, [[EXIT_MAINLOOP_AT]]
628; CHECK-NEXT:    br i1 [[TMP5]], label [[LOOP_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
629; CHECK:       loop.preheader:
630; CHECK-NEXT:    br label [[LOOP:%.*]]
631; CHECK:       loop:
632; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
633; CHECK-NEXT:    [[CAPACITY_CHECK:%.*]] = icmp slt i32 [[IV]], [[LIMIT]]
634; CHECK-NEXT:    br i1 true, label [[BACKEDGE]], label [[OUT_OF_BOUNDS_LOOPEXIT5:%.*]], !prof [[PROF17:![0-9]+]]
635; CHECK:       backedge:
636; CHECK-NEXT:    [[IV_WIDE:%.*]] = zext i32 [[IV]] to i64
637; CHECK-NEXT:    [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i64 [[IV_WIDE]]
638; CHECK-NEXT:    store i32 1, ptr [[EL_PTR]], align 4
639; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 4
640; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], [[NUM_ELEMENTS]]
641; CHECK-NEXT:    [[TMP6:%.*]] = icmp slt i32 [[IV_NEXT]], [[EXIT_MAINLOOP_AT]]
642; CHECK-NEXT:    br i1 [[TMP6]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
643; CHECK:       main.exit.selector:
644; CHECK-NEXT:    [[IV_NEXT_LCSSA:%.*]] = phi i32 [ [[IV_NEXT]], [[BACKEDGE]] ]
645; CHECK-NEXT:    [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[BACKEDGE]] ]
646; CHECK-NEXT:    [[TMP7:%.*]] = icmp slt i32 [[IV_NEXT_LCSSA]], [[NUM_ELEMENTS]]
647; CHECK-NEXT:    br i1 [[TMP7]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT:%.*]]
648; CHECK:       main.pseudo.exit:
649; CHECK-NEXT:    [[IV_COPY:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
650; CHECK-NEXT:    [[INDVAR_END:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[IV_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
651; CHECK-NEXT:    br label [[POSTLOOP:%.*]]
652; CHECK:       exit.loopexit:
653; CHECK-NEXT:    [[IV_LCSSA1_PH:%.*]] = phi i32 [ [[IV_POSTLOOP:%.*]], [[BACKEDGE_POSTLOOP:%.*]] ]
654; CHECK-NEXT:    br label [[EXIT]]
655; CHECK:       exit:
656; CHECK-NEXT:    [[IV_LCSSA1:%.*]] = phi i32 [ [[IV_LCSSA]], [[MAIN_EXIT_SELECTOR]] ], [ [[IV_LCSSA1_PH]], [[EXIT_LOOPEXIT:%.*]] ]
657; CHECK-NEXT:    ret i32 [[IV_LCSSA1]]
658; CHECK:       out_of_bounds.loopexit:
659; CHECK-NEXT:    br label [[OUT_OF_BOUNDS:%.*]]
660; CHECK:       out_of_bounds.loopexit5:
661; CHECK-NEXT:    br label [[OUT_OF_BOUNDS]]
662; CHECK:       out_of_bounds:
663; CHECK-NEXT:    ret i32 -1
664; CHECK:       postloop:
665; CHECK-NEXT:    br label [[LOOP_POSTLOOP:%.*]]
666; CHECK:       loop.postloop:
667; CHECK-NEXT:    [[IV_POSTLOOP]] = phi i32 [ [[IV_COPY]], [[POSTLOOP]] ], [ [[IV_NEXT_POSTLOOP:%.*]], [[BACKEDGE_POSTLOOP]] ]
668; CHECK-NEXT:    [[CAPACITY_CHECK_POSTLOOP:%.*]] = icmp slt i32 [[IV_POSTLOOP]], [[LIMIT]]
669; CHECK-NEXT:    br i1 [[CAPACITY_CHECK_POSTLOOP]], label [[BACKEDGE_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]], !prof [[PROF17]]
670; CHECK:       backedge.postloop:
671; CHECK-NEXT:    [[IV_WIDE_POSTLOOP:%.*]] = zext i32 [[IV_POSTLOOP]] to i64
672; CHECK-NEXT:    [[EL_PTR_POSTLOOP:%.*]] = getelementptr i32, ptr [[P]], i64 [[IV_WIDE_POSTLOOP]]
673; CHECK-NEXT:    store i32 1, ptr [[EL_PTR_POSTLOOP]], align 4
674; CHECK-NEXT:    [[IV_NEXT_POSTLOOP]] = add nuw nsw i32 [[IV_POSTLOOP]], 4
675; CHECK-NEXT:    [[LOOP_COND_POSTLOOP:%.*]] = icmp slt i32 [[IV_NEXT_POSTLOOP]], [[NUM_ELEMENTS]]
676; CHECK-NEXT:    br i1 [[LOOP_COND_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT]], !llvm.loop [[LOOP18:![0-9]+]], !loop_constrainer.loop.clone !6
677;
678entry:
679  %capacity = load i32, ptr %capacity_p, !range !4
680  %num_elements = load i32, ptr %num_elements_p, !range !4
681  %limit = sub i32 %capacity, 3
682  br label %loop
683
684loop:
685  %iv = phi i32 [0, %entry], [%iv.next, %backedge]
686  %capacity_check = icmp slt i32 %iv, %limit
687  br i1 %capacity_check, label %backedge, label %out_of_bounds, !prof !5
688
689backedge:
690  %iv.wide = zext i32 %iv to i64
691  %el.ptr = getelementptr i32, ptr %p, i64 %iv.wide
692  store i32 1, ptr %el.ptr
693  %iv.next = add nuw nsw i32 %iv, 4
694  %loop_cond = icmp slt i32 %iv.next, %num_elements
695  br i1 %loop_cond, label %loop, label %exit
696
697exit:
698  ret i32 %iv
699
700out_of_bounds:
701  ret i32 -1
702}
703
704; Same as test_09 but range check comparison is inversed.
705; IRCE is allowed.
706define i32 @test_10(ptr %p, ptr %capacity_p, ptr %num_elements_p) {
707; CHECK-LABEL: define i32 @test_10
708; CHECK-SAME: (ptr [[P:%.*]], ptr [[CAPACITY_P:%.*]], ptr [[NUM_ELEMENTS_P:%.*]]) {
709; CHECK-NEXT:  entry:
710; CHECK-NEXT:    [[CAPACITY:%.*]] = load i32, ptr [[CAPACITY_P]], align 4, !range [[RNG16]]
711; CHECK-NEXT:    [[NUM_ELEMENTS:%.*]] = load i32, ptr [[NUM_ELEMENTS_P]], align 4, !range [[RNG16]]
712; CHECK-NEXT:    [[LIMIT:%.*]] = sub i32 [[CAPACITY]], 3
713; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[CAPACITY]], -3
714; CHECK-NEXT:    [[TMP1:%.*]] = add nuw i32 [[CAPACITY]], 2147483646
715; CHECK-NEXT:    [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[TMP1]], i32 0)
716; CHECK-NEXT:    [[TMP2:%.*]] = sub i32 [[TMP0]], [[SMAX]]
717; CHECK-NEXT:    [[SMIN:%.*]] = call i32 @llvm.smin.i32(i32 [[LIMIT]], i32 0)
718; CHECK-NEXT:    [[SMAX2:%.*]] = call i32 @llvm.smax.i32(i32 [[SMIN]], i32 -1)
719; CHECK-NEXT:    [[TMP3:%.*]] = add nsw i32 [[SMAX2]], 1
720; CHECK-NEXT:    [[TMP4:%.*]] = mul i32 [[TMP2]], [[TMP3]]
721; CHECK-NEXT:    [[SMIN3:%.*]] = call i32 @llvm.smin.i32(i32 [[NUM_ELEMENTS]], i32 [[TMP4]])
722; CHECK-NEXT:    [[EXIT_MAINLOOP_AT:%.*]] = call i32 @llvm.smax.i32(i32 [[SMIN3]], i32 0)
723; CHECK-NEXT:    [[TMP5:%.*]] = icmp slt i32 0, [[EXIT_MAINLOOP_AT]]
724; CHECK-NEXT:    br i1 [[TMP5]], label [[LOOP_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
725; CHECK:       loop.preheader:
726; CHECK-NEXT:    br label [[LOOP:%.*]]
727; CHECK:       loop:
728; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
729; CHECK-NEXT:    [[CAPACITY_CHECK:%.*]] = icmp slt i32 [[IV]], [[LIMIT]]
730; CHECK-NEXT:    br i1 true, label [[BACKEDGE]], label [[OUT_OF_BOUNDS_LOOPEXIT5:%.*]], !prof [[PROF17]]
731; CHECK:       backedge:
732; CHECK-NEXT:    [[IV_WIDE:%.*]] = zext i32 [[IV]] to i64
733; CHECK-NEXT:    [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i64 [[IV_WIDE]]
734; CHECK-NEXT:    store i32 1, ptr [[EL_PTR]], align 4
735; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 4
736; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], [[NUM_ELEMENTS]]
737; CHECK-NEXT:    [[TMP6:%.*]] = icmp slt i32 [[IV_NEXT]], [[EXIT_MAINLOOP_AT]]
738; CHECK-NEXT:    br i1 [[TMP6]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
739; CHECK:       main.exit.selector:
740; CHECK-NEXT:    [[IV_NEXT_LCSSA:%.*]] = phi i32 [ [[IV_NEXT]], [[BACKEDGE]] ]
741; CHECK-NEXT:    [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[BACKEDGE]] ]
742; CHECK-NEXT:    [[TMP7:%.*]] = icmp slt i32 [[IV_NEXT_LCSSA]], [[NUM_ELEMENTS]]
743; CHECK-NEXT:    br i1 [[TMP7]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT:%.*]]
744; CHECK:       main.pseudo.exit:
745; CHECK-NEXT:    [[IV_COPY:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
746; CHECK-NEXT:    [[INDVAR_END:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[IV_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
747; CHECK-NEXT:    br label [[POSTLOOP:%.*]]
748; CHECK:       exit.loopexit:
749; CHECK-NEXT:    [[IV_LCSSA1_PH:%.*]] = phi i32 [ [[IV_POSTLOOP:%.*]], [[BACKEDGE_POSTLOOP:%.*]] ]
750; CHECK-NEXT:    br label [[EXIT]]
751; CHECK:       exit:
752; CHECK-NEXT:    [[IV_LCSSA1:%.*]] = phi i32 [ [[IV_LCSSA]], [[MAIN_EXIT_SELECTOR]] ], [ [[IV_LCSSA1_PH]], [[EXIT_LOOPEXIT:%.*]] ]
753; CHECK-NEXT:    ret i32 [[IV_LCSSA1]]
754; CHECK:       out_of_bounds.loopexit:
755; CHECK-NEXT:    br label [[OUT_OF_BOUNDS:%.*]]
756; CHECK:       out_of_bounds.loopexit5:
757; CHECK-NEXT:    br label [[OUT_OF_BOUNDS]]
758; CHECK:       out_of_bounds:
759; CHECK-NEXT:    ret i32 -1
760; CHECK:       postloop:
761; CHECK-NEXT:    br label [[LOOP_POSTLOOP:%.*]]
762; CHECK:       loop.postloop:
763; CHECK-NEXT:    [[IV_POSTLOOP]] = phi i32 [ [[IV_COPY]], [[POSTLOOP]] ], [ [[IV_NEXT_POSTLOOP:%.*]], [[BACKEDGE_POSTLOOP]] ]
764; CHECK-NEXT:    [[CAPACITY_CHECK_POSTLOOP:%.*]] = icmp slt i32 [[IV_POSTLOOP]], [[LIMIT]]
765; CHECK-NEXT:    br i1 [[CAPACITY_CHECK_POSTLOOP]], label [[BACKEDGE_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]], !prof [[PROF17]]
766; CHECK:       backedge.postloop:
767; CHECK-NEXT:    [[IV_WIDE_POSTLOOP:%.*]] = zext i32 [[IV_POSTLOOP]] to i64
768; CHECK-NEXT:    [[EL_PTR_POSTLOOP:%.*]] = getelementptr i32, ptr [[P]], i64 [[IV_WIDE_POSTLOOP]]
769; CHECK-NEXT:    store i32 1, ptr [[EL_PTR_POSTLOOP]], align 4
770; CHECK-NEXT:    [[IV_NEXT_POSTLOOP]] = add nuw nsw i32 [[IV_POSTLOOP]], 4
771; CHECK-NEXT:    [[LOOP_COND_POSTLOOP:%.*]] = icmp slt i32 [[IV_NEXT_POSTLOOP]], [[NUM_ELEMENTS]]
772; CHECK-NEXT:    br i1 [[LOOP_COND_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT]], !llvm.loop [[LOOP19:![0-9]+]], !loop_constrainer.loop.clone !6
773;
774entry:
775  %capacity = load i32, ptr %capacity_p, !range !4
776  %num_elements = load i32, ptr %num_elements_p, !range !4
777  %limit = sub i32 %capacity, 3
778  br label %loop
779
780loop:
781  %iv = phi i32 [0, %entry], [%iv.next, %backedge]
782  %capacity_check = icmp sge i32 %iv, %limit
783  br i1 %capacity_check, label %out_of_bounds, label %backedge, !prof !6
784
785backedge:
786  %iv.wide = zext i32 %iv to i64
787  %el.ptr = getelementptr i32, ptr %p, i64 %iv.wide
788  store i32 1, ptr %el.ptr
789  %iv.next = add nuw nsw i32 %iv, 4
790  %loop_cond = icmp slt i32 %iv.next, %num_elements
791  br i1 %loop_cond, label %loop, label %exit
792
793exit:
794  ret i32 %iv
795
796out_of_bounds:
797  ret i32 -1
798}
799
800; Same as test_09 but range check comparison is non-strict:
801; IRCE is allowed.
802define i32 @test_11(ptr %p, ptr %capacity_p, ptr %num_elements_p) {
803; CHECK-LABEL: define i32 @test_11
804; CHECK-SAME: (ptr [[P:%.*]], ptr [[CAPACITY_P:%.*]], ptr [[NUM_ELEMENTS_P:%.*]]) {
805; CHECK-NEXT:  entry:
806; CHECK-NEXT:    [[CAPACITY:%.*]] = load i32, ptr [[CAPACITY_P]], align 4, !range [[RNG16]]
807; CHECK-NEXT:    [[NUM_ELEMENTS:%.*]] = load i32, ptr [[NUM_ELEMENTS_P]], align 4, !range [[RNG16]]
808; CHECK-NEXT:    [[LIMIT:%.*]] = sub i32 [[CAPACITY]], 4
809; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[CAPACITY]], -3
810; CHECK-NEXT:    [[TMP1:%.*]] = add nuw i32 [[CAPACITY]], 2147483646
811; CHECK-NEXT:    [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[TMP1]], i32 0)
812; CHECK-NEXT:    [[TMP2:%.*]] = sub i32 [[TMP0]], [[SMAX]]
813; CHECK-NEXT:    [[TMP3:%.*]] = add nsw i32 [[CAPACITY]], -3
814; CHECK-NEXT:    [[SMIN:%.*]] = call i32 @llvm.smin.i32(i32 [[TMP3]], i32 0)
815; CHECK-NEXT:    [[SMAX2:%.*]] = call i32 @llvm.smax.i32(i32 [[SMIN]], i32 -1)
816; CHECK-NEXT:    [[TMP4:%.*]] = add nsw i32 [[SMAX2]], 1
817; CHECK-NEXT:    [[TMP5:%.*]] = mul i32 [[TMP2]], [[TMP4]]
818; CHECK-NEXT:    [[SMIN3:%.*]] = call i32 @llvm.smin.i32(i32 [[NUM_ELEMENTS]], i32 [[TMP5]])
819; CHECK-NEXT:    [[EXIT_MAINLOOP_AT:%.*]] = call i32 @llvm.smax.i32(i32 [[SMIN3]], i32 0)
820; CHECK-NEXT:    [[TMP6:%.*]] = icmp slt i32 0, [[EXIT_MAINLOOP_AT]]
821; CHECK-NEXT:    br i1 [[TMP6]], label [[LOOP_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
822; CHECK:       loop.preheader:
823; CHECK-NEXT:    br label [[LOOP:%.*]]
824; CHECK:       loop:
825; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
826; CHECK-NEXT:    [[CAPACITY_CHECK:%.*]] = icmp sle i32 [[IV]], [[LIMIT]]
827; CHECK-NEXT:    br i1 true, label [[BACKEDGE]], label [[OUT_OF_BOUNDS_LOOPEXIT5:%.*]], !prof [[PROF17]]
828; CHECK:       backedge:
829; CHECK-NEXT:    [[IV_WIDE:%.*]] = zext i32 [[IV]] to i64
830; CHECK-NEXT:    [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i64 [[IV_WIDE]]
831; CHECK-NEXT:    store i32 1, ptr [[EL_PTR]], align 4
832; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 4
833; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], [[NUM_ELEMENTS]]
834; CHECK-NEXT:    [[TMP7:%.*]] = icmp slt i32 [[IV_NEXT]], [[EXIT_MAINLOOP_AT]]
835; CHECK-NEXT:    br i1 [[TMP7]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
836; CHECK:       main.exit.selector:
837; CHECK-NEXT:    [[IV_NEXT_LCSSA:%.*]] = phi i32 [ [[IV_NEXT]], [[BACKEDGE]] ]
838; CHECK-NEXT:    [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[BACKEDGE]] ]
839; CHECK-NEXT:    [[TMP8:%.*]] = icmp slt i32 [[IV_NEXT_LCSSA]], [[NUM_ELEMENTS]]
840; CHECK-NEXT:    br i1 [[TMP8]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT:%.*]]
841; CHECK:       main.pseudo.exit:
842; CHECK-NEXT:    [[IV_COPY:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
843; CHECK-NEXT:    [[INDVAR_END:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[IV_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
844; CHECK-NEXT:    br label [[POSTLOOP:%.*]]
845; CHECK:       exit.loopexit:
846; CHECK-NEXT:    [[IV_LCSSA1_PH:%.*]] = phi i32 [ [[IV_POSTLOOP:%.*]], [[BACKEDGE_POSTLOOP:%.*]] ]
847; CHECK-NEXT:    br label [[EXIT]]
848; CHECK:       exit:
849; CHECK-NEXT:    [[IV_LCSSA1:%.*]] = phi i32 [ [[IV_LCSSA]], [[MAIN_EXIT_SELECTOR]] ], [ [[IV_LCSSA1_PH]], [[EXIT_LOOPEXIT:%.*]] ]
850; CHECK-NEXT:    ret i32 [[IV_LCSSA1]]
851; CHECK:       out_of_bounds.loopexit:
852; CHECK-NEXT:    br label [[OUT_OF_BOUNDS:%.*]]
853; CHECK:       out_of_bounds.loopexit5:
854; CHECK-NEXT:    br label [[OUT_OF_BOUNDS]]
855; CHECK:       out_of_bounds:
856; CHECK-NEXT:    ret i32 -1
857; CHECK:       postloop:
858; CHECK-NEXT:    br label [[LOOP_POSTLOOP:%.*]]
859; CHECK:       loop.postloop:
860; CHECK-NEXT:    [[IV_POSTLOOP]] = phi i32 [ [[IV_COPY]], [[POSTLOOP]] ], [ [[IV_NEXT_POSTLOOP:%.*]], [[BACKEDGE_POSTLOOP]] ]
861; CHECK-NEXT:    [[CAPACITY_CHECK_POSTLOOP:%.*]] = icmp sle i32 [[IV_POSTLOOP]], [[LIMIT]]
862; CHECK-NEXT:    br i1 [[CAPACITY_CHECK_POSTLOOP]], label [[BACKEDGE_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]], !prof [[PROF17]]
863; CHECK:       backedge.postloop:
864; CHECK-NEXT:    [[IV_WIDE_POSTLOOP:%.*]] = zext i32 [[IV_POSTLOOP]] to i64
865; CHECK-NEXT:    [[EL_PTR_POSTLOOP:%.*]] = getelementptr i32, ptr [[P]], i64 [[IV_WIDE_POSTLOOP]]
866; CHECK-NEXT:    store i32 1, ptr [[EL_PTR_POSTLOOP]], align 4
867; CHECK-NEXT:    [[IV_NEXT_POSTLOOP]] = add nuw nsw i32 [[IV_POSTLOOP]], 4
868; CHECK-NEXT:    [[LOOP_COND_POSTLOOP:%.*]] = icmp slt i32 [[IV_NEXT_POSTLOOP]], [[NUM_ELEMENTS]]
869; CHECK-NEXT:    br i1 [[LOOP_COND_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT]], !llvm.loop [[LOOP20:![0-9]+]], !loop_constrainer.loop.clone !6
870;
871entry:
872  %capacity = load i32, ptr %capacity_p, !range !4
873  %num_elements = load i32, ptr %num_elements_p, !range !4
874  %limit = sub i32 %capacity, 4
875  br label %loop
876
877loop:
878  %iv = phi i32 [0, %entry], [%iv.next, %backedge]
879  %capacity_check = icmp sle i32 %iv, %limit
880  br i1 %capacity_check, label %backedge, label %out_of_bounds, !prof !5
881
882backedge:
883  %iv.wide = zext i32 %iv to i64
884  %el.ptr = getelementptr i32, ptr %p, i64 %iv.wide
885  store i32 1, ptr %el.ptr
886  %iv.next = add nuw nsw i32 %iv, 4
887  %loop_cond = icmp slt i32 %iv.next, %num_elements
888  br i1 %loop_cond, label %loop, label %exit
889
890exit:
891  ret i32 %iv
892
893out_of_bounds:
894  ret i32 -1
895}
896
897; Indvar base is non-overflowing binary 'or':
898; check that IRCE isn't trying to add NSW flag on it.
899define i32 @binop_or_is_iv_base(ptr %p, i32 %end) {
900; CHECK-LABEL: define i32 @binop_or_is_iv_base
901; CHECK-SAME: (ptr [[P:%.*]], i32 [[END:%.*]]) {
902; CHECK-NEXT:  entry:
903; CHECK-NEXT:    [[N:%.*]] = load atomic i32, ptr [[P]] unordered, align 8, !range [[RNG8]]
904; CHECK-NEXT:    [[CMP0:%.*]] = icmp sgt i32 [[END]], 7
905; CHECK-NEXT:    br i1 [[CMP0]], label [[LOOP_HEADER_PREHEADER:%.*]], label [[COMMON_RET:%.*]]
906; CHECK:       loop.header.preheader:
907; CHECK-NEXT:    [[TMP0:%.*]] = add nuw nsw i32 [[N]], 7
908; CHECK-NEXT:    [[SMIN:%.*]] = call i32 @llvm.smin.i32(i32 [[END]], i32 [[TMP0]])
909; CHECK-NEXT:    [[EXIT_MAINLOOP_AT:%.*]] = call i32 @llvm.smax.i32(i32 [[SMIN]], i32 7)
910; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i32 7, [[EXIT_MAINLOOP_AT]]
911; CHECK-NEXT:    br i1 [[TMP1]], label [[LOOP_HEADER_PREHEADER1:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
912; CHECK:       loop.header.preheader1:
913; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
914; CHECK:       loop.header:
915; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[IV_ADD:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_HEADER_PREHEADER1]] ]
916; CHECK-NEXT:    [[CHECK:%.*]] = icmp ult i32 [[IV]], [[N]]
917; CHECK-NEXT:    br i1 true, label [[GUARDED]], label [[DEOPT_LOOPEXIT2:%.*]]
918; CHECK:       guarded:
919; CHECK-NEXT:    [[IV_ADD]] = add i32 [[IV]], 8
920; CHECK-NEXT:    [[IV_OR:%.*]] = or disjoint i32 [[IV_ADD]], 7
921; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[IV_OR]], [[END]]
922; CHECK-NEXT:    [[TMP2:%.*]] = icmp slt i32 [[IV_OR]], [[EXIT_MAINLOOP_AT]]
923; CHECK-NEXT:    br i1 [[TMP2]], label [[LOOP_HEADER]], label [[MAIN_EXIT_SELECTOR:%.*]]
924; CHECK:       main.exit.selector:
925; CHECK-NEXT:    [[IV_ADD_LCSSA:%.*]] = phi i32 [ [[IV_ADD]], [[GUARDED]] ]
926; CHECK-NEXT:    [[IV_OR_LCSSA:%.*]] = phi i32 [ [[IV_OR]], [[GUARDED]] ]
927; CHECK-NEXT:    [[TMP3:%.*]] = icmp slt i32 [[IV_OR_LCSSA]], [[END]]
928; CHECK-NEXT:    br i1 [[TMP3]], label [[MAIN_PSEUDO_EXIT]], label [[COMMON_RET_LOOPEXIT:%.*]]
929; CHECK:       main.pseudo.exit:
930; CHECK-NEXT:    [[IV_COPY:%.*]] = phi i32 [ 0, [[LOOP_HEADER_PREHEADER]] ], [ [[IV_ADD_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
931; CHECK-NEXT:    [[INDVAR_END:%.*]] = phi i32 [ 7, [[LOOP_HEADER_PREHEADER]] ], [ [[IV_OR_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
932; CHECK-NEXT:    br label [[POSTLOOP:%.*]]
933; CHECK:       deopt.loopexit:
934; CHECK-NEXT:    br label [[DEOPT:%.*]]
935; CHECK:       deopt.loopexit2:
936; CHECK-NEXT:    br label [[DEOPT]]
937; CHECK:       deopt:
938; CHECK-NEXT:    [[RV:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 13) [ "deopt"() ]
939; CHECK-NEXT:    ret i32 [[RV]]
940; CHECK:       common.ret.loopexit.loopexit:
941; CHECK-NEXT:    br label [[COMMON_RET_LOOPEXIT]]
942; CHECK:       common.ret.loopexit:
943; CHECK-NEXT:    br label [[COMMON_RET]]
944; CHECK:       common.ret:
945; CHECK-NEXT:    ret i32 [[END]]
946; CHECK:       postloop:
947; CHECK-NEXT:    br label [[LOOP_HEADER_POSTLOOP:%.*]]
948; CHECK:       loop.header.postloop:
949; CHECK-NEXT:    [[IV_POSTLOOP:%.*]] = phi i32 [ [[IV_ADD_POSTLOOP:%.*]], [[GUARDED_POSTLOOP:%.*]] ], [ [[IV_COPY]], [[POSTLOOP]] ]
950; CHECK-NEXT:    [[CHECK_POSTLOOP:%.*]] = icmp ult i32 [[IV_POSTLOOP]], [[N]]
951; CHECK-NEXT:    br i1 [[CHECK_POSTLOOP]], label [[GUARDED_POSTLOOP]], label [[DEOPT_LOOPEXIT:%.*]]
952; CHECK:       guarded.postloop:
953; CHECK-NEXT:    [[IV_ADD_POSTLOOP]] = add i32 [[IV_POSTLOOP]], 8
954; CHECK-NEXT:    [[IV_OR_POSTLOOP:%.*]] = or disjoint i32 [[IV_ADD_POSTLOOP]], 7
955; CHECK-NEXT:    [[CMP_POSTLOOP:%.*]] = icmp slt i32 [[IV_OR_POSTLOOP]], [[END]]
956; CHECK-NEXT:    br i1 [[CMP_POSTLOOP]], label [[LOOP_HEADER_POSTLOOP]], label [[COMMON_RET_LOOPEXIT_LOOPEXIT:%.*]], !llvm.loop [[LOOP21:![0-9]+]], !loop_constrainer.loop.clone !6
957;
958entry:
959  %n = load atomic i32, ptr %p unordered, align 8, !range !1
960  %cmp0 = icmp sgt i32 %end, 7
961  br i1 %cmp0, label %loop.header, label %common.ret
962
963loop.header:
964  %iv = phi i32 [ %iv.add, %guarded ], [ 0, %entry ]
965  %check = icmp ult i32 %iv, %n
966  br i1 %check, label %guarded, label %deopt
967
968guarded:
969  %iv.add = add i32 %iv, 8
970  %iv.or = or disjoint i32 %iv.add, 7
971  %cmp = icmp slt i32 %iv.or, %end
972  br i1 %cmp, label %loop.header, label %common.ret
973
974deopt:
975  %rv = call i32 (...) @llvm.experimental.deoptimize.i32(i32 13) [ "deopt"() ]
976  ret i32 %rv
977
978common.ret:
979  ret i32 %end
980}
981
982declare i32 @llvm.experimental.deoptimize.i32(...)
983
984!0 = !{i32 0, i32 50}
985!1 = !{i32 0, i32 2147483640}
986!2 = !{i32 0, i32 2147483641}
987!3 = !{i32 10, i32 50}
988!4 = !{i32 1, i32 2147483648}
989!5 = !{!"branch_weights", i32 1000, i32 1}
990!6 = !{!"branch_weights", i32 1, i32 1000}
991