Revert "[InstCombine] Support gep nuw in icmp folds" (#118698)
[llvm-project.git] / llvm / test / Transforms / IRCE / stride_more_than_1.ll
blob749c17d118205e86c27d7820321b88116abd6559
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
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>
14 ; IV = 0; IV <s 100; IV += 7; 0 <= Len <= 50. IRCE is allowed.
15 define 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
67 entry:
68   %len = load i32, ptr %a_len_ptr, !range !0
69   br label %loop
71 loop:
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
77 in.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
83 out.of.bounds:
84   ret void
86 exit:
87   ret void
90 ; IV = 0; IV <s MAX_INT - 7; IV += 7; 0 <= Len <= 50. IRCE is allowed.
91 define 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
143 entry:
144   %len = load i32, ptr %a_len_ptr, !range !0
145   br label %loop
147 loop:
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
153 in.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
159 out.of.bounds:
160   ret void
162 exit:
163   ret void
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.
168 define 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
220 entry:
221   %len = load i32, ptr %a_len_ptr, !range !1
222   br label %loop
224 loop:
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
230 in.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
236 out.of.bounds:
237   ret void
239 exit:
240   ret void
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.
246 define 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
300 entry:
301   %len = load i32, ptr %a_len_ptr, !range !2
302   br label %loop
304 loop:
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
310 in.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
316 out.of.bounds:
317   ret void
319 exit:
320   ret void
323 ; IV = 100; IV >s -1; IV -= 7; 0 <= Len <= 50. IRCE is allowed.
324 define 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]]
377 entry:
378   %len = load i32, ptr %a_len_ptr, !range !0
379   br label %loop
381 loop:
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
387 in.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
393 out.of.bounds:
394   ret void
396 exit:
397   ret void
400 ; IV = MAX_INT - 7; IV >u 6; IV -= 7; 10 <= Len <= 50. IRCE is allowed.
401 define 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]]
454 entry:
455   %len = load i32, ptr %a_len_ptr, !range !3
456   br label %loop
458 loop:
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
464 in.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
470 out.of.bounds:
471   ret void
473 exit:
474   ret void
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.
479 define 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
501 entry:
502   %len = load i32, ptr %a_len_ptr, !range !3
503   br label %loop
505 loop:
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
511 in.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
517 out.of.bounds:
518   ret void
520 exit:
521   ret void
524 ; IV = MAX_INT; IV >u 6; IV -= 7; 10 <= Len <= 50. IRCE is allowed.
525 define 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]]
578 entry:
579   %len = load i32, ptr %a_len_ptr, !range !3
580   br label %loop
582 loop:
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
588 in.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
594 out.of.bounds:
595   ret void
597 exit:
598   ret void
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
610 define 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
678 entry:
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
684 loop:
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
689 backedge:
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
697 exit:
698   ret i32 %iv
700 out_of_bounds:
701   ret i32 -1
704 ; Same as test_09 but range check comparison is inversed.
705 ; IRCE is allowed.
706 define 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
774 entry:
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
780 loop:
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
785 backedge:
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
793 exit:
794   ret i32 %iv
796 out_of_bounds:
797   ret i32 -1
800 ; Same as test_09 but range check comparison is non-strict:
801 ; IRCE is allowed.
802 define 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
871 entry:
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
877 loop:
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
882 backedge:
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
890 exit:
891   ret i32 %iv
893 out_of_bounds:
894   ret i32 -1
897 ; Indvar base is non-overflowing binary 'or':
898 ; check that IRCE isn't trying to add NSW flag on it.
899 define 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
958 entry:
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
963 loop.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
968 guarded:
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
974 deopt:
975   %rv = call i32 (...) @llvm.experimental.deoptimize.i32(i32 13) [ "deopt"() ]
976   ret i32 %rv
978 common.ret:
979   ret i32 %end
982 declare i32 @llvm.experimental.deoptimize.i32(...)
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}