[clang][modules] Don't prevent translation of FW_Private includes when explicitly...
[llvm-project.git] / llvm / test / Transforms / IRCE / unsigned_comparisons_ult.ll
blob546e1b0faa1c34432267ae5970a336052bce214d
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 3
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>
13 ; CHECK-NOT: irce: in function test_09: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
15 ; ULT condition for increasing loop.
16 define void @test_01(ptr %arr, ptr %a_len_ptr) #0 {
17 ; CHECK-LABEL: define void @test_01
18 ; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
19 ; CHECK-NEXT:  entry:
20 ; CHECK-NEXT:    [[EXIT_MAINLOOP_AT:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0:![0-9]+]]
21 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i32 0, [[EXIT_MAINLOOP_AT]]
22 ; CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
23 ; CHECK:       loop.preheader:
24 ; CHECK-NEXT:    br label [[LOOP:%.*]]
25 ; CHECK:       loop:
26 ; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
27 ; CHECK-NEXT:    [[IDX_NEXT]] = add nuw nsw i32 [[IDX]], 1
28 ; CHECK-NEXT:    [[ABC:%.*]] = icmp ult i32 [[IDX]], [[EXIT_MAINLOOP_AT]]
29 ; CHECK-NEXT:    br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]]
30 ; CHECK:       in.bounds:
31 ; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]
32 ; CHECK-NEXT:    store i32 0, ptr [[ADDR]], align 4
33 ; CHECK-NEXT:    [[NEXT:%.*]] = icmp ult i32 [[IDX_NEXT]], 100
34 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]
35 ; CHECK-NEXT:    br i1 [[TMP1]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
36 ; CHECK:       main.exit.selector:
37 ; CHECK-NEXT:    [[IDX_NEXT_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT]], [[IN_BOUNDS]] ]
38 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i32 [[IDX_NEXT_LCSSA]], 100
39 ; CHECK-NEXT:    br i1 [[TMP2]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT:%.*]]
40 ; CHECK:       main.pseudo.exit:
41 ; CHECK-NEXT:    [[IDX_COPY:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
42 ; CHECK-NEXT:    [[INDVAR_END:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
43 ; CHECK-NEXT:    br label [[POSTLOOP:%.*]]
44 ; CHECK:       out.of.bounds.loopexit:
45 ; CHECK-NEXT:    br label [[OUT_OF_BOUNDS:%.*]]
46 ; CHECK:       out.of.bounds.loopexit1:
47 ; CHECK-NEXT:    br label [[OUT_OF_BOUNDS]]
48 ; CHECK:       out.of.bounds:
49 ; CHECK-NEXT:    ret void
50 ; CHECK:       exit.loopexit:
51 ; CHECK-NEXT:    br label [[EXIT]]
52 ; CHECK:       exit:
53 ; CHECK-NEXT:    ret void
54 ; CHECK:       postloop:
55 ; CHECK-NEXT:    br label [[LOOP_POSTLOOP:%.*]]
56 ; CHECK:       loop.postloop:
57 ; CHECK-NEXT:    [[IDX_POSTLOOP:%.*]] = phi i32 [ [[IDX_COPY]], [[POSTLOOP]] ], [ [[IDX_NEXT_POSTLOOP:%.*]], [[IN_BOUNDS_POSTLOOP:%.*]] ]
58 ; CHECK-NEXT:    [[IDX_NEXT_POSTLOOP]] = add nuw nsw i32 [[IDX_POSTLOOP]], 1
59 ; CHECK-NEXT:    [[ABC_POSTLOOP:%.*]] = icmp ult i32 [[IDX_POSTLOOP]], [[EXIT_MAINLOOP_AT]]
60 ; CHECK-NEXT:    br i1 [[ABC_POSTLOOP]], label [[IN_BOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]]
61 ; CHECK:       in.bounds.postloop:
62 ; CHECK-NEXT:    [[ADDR_POSTLOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_POSTLOOP]]
63 ; CHECK-NEXT:    store i32 0, ptr [[ADDR_POSTLOOP]], align 4
64 ; CHECK-NEXT:    [[NEXT_POSTLOOP:%.*]] = icmp ult i32 [[IDX_NEXT_POSTLOOP]], 100
65 ; CHECK-NEXT:    br i1 [[NEXT_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT:%.*]], !llvm.loop [[LOOP1:![0-9]+]], !loop_constrainer.loop.clone [[META6:![0-9]+]]
68 entry:
69   %len = load i32, ptr %a_len_ptr, !range !0
70   br label %loop
72 loop:
73   %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
74   %idx.next = add nsw nuw i32 %idx, 1
75   %abc = icmp ult i32 %idx, %len
76   br i1 %abc, label %in.bounds, label %out.of.bounds
78 in.bounds:
79   %addr = getelementptr i32, ptr %arr, i32 %idx
80   store i32 0, ptr %addr
81   %next = icmp ult i32 %idx.next, 100
82   br i1 %next, label %loop, label %exit
84 out.of.bounds:
85   ret void
87 exit:
88   ret void
91 ; ULT condition for decreasing loops.
92 define void @test_02(ptr %arr, ptr %a_len_ptr) #0 {
93 ; CHECK-LABEL: define void @test_02
94 ; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
95 ; CHECK-NEXT:  entry:
96 ; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0]]
97 ; CHECK-NEXT:    [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[LEN]], i32 1)
98 ; CHECK-NEXT:    [[EXIT_PRELOOP_AT:%.*]] = add nsw i32 [[UMAX]], -1
99 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp ugt i32 100, [[EXIT_PRELOOP_AT]]
100 ; CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP_PRELOOP_PREHEADER:%.*]], label [[PRELOOP_PSEUDO_EXIT:%.*]]
101 ; CHECK:       loop.preloop.preheader:
102 ; CHECK-NEXT:    br label [[LOOP_PRELOOP:%.*]]
103 ; CHECK:       mainloop:
104 ; CHECK-NEXT:    br label [[LOOP:%.*]]
105 ; CHECK:       loop:
106 ; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ [[IDX_PRELOOP_COPY:%.*]], [[MAINLOOP:%.*]] ], [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ]
107 ; CHECK-NEXT:    [[IDX_NEXT]] = add i32 [[IDX]], -1
108 ; CHECK-NEXT:    [[ABC:%.*]] = icmp ult i32 [[IDX]], [[LEN]]
109 ; CHECK-NEXT:    br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]]
110 ; CHECK:       in.bounds:
111 ; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]
112 ; CHECK-NEXT:    store i32 0, ptr [[ADDR]], align 4
113 ; CHECK-NEXT:    [[NEXT:%.*]] = icmp ult i32 [[IDX_NEXT]], 1
114 ; CHECK-NEXT:    br i1 [[NEXT]], label [[EXIT_LOOPEXIT:%.*]], label [[LOOP]]
115 ; CHECK:       out.of.bounds.loopexit:
116 ; CHECK-NEXT:    br label [[OUT_OF_BOUNDS:%.*]]
117 ; CHECK:       out.of.bounds.loopexit1:
118 ; CHECK-NEXT:    br label [[OUT_OF_BOUNDS]]
119 ; CHECK:       out.of.bounds:
120 ; CHECK-NEXT:    ret void
121 ; CHECK:       exit.loopexit:
122 ; CHECK-NEXT:    br label [[EXIT:%.*]]
123 ; CHECK:       exit:
124 ; CHECK-NEXT:    ret void
125 ; CHECK:       loop.preloop:
126 ; CHECK-NEXT:    [[IDX_PRELOOP:%.*]] = phi i32 [ [[IDX_NEXT_PRELOOP:%.*]], [[IN_BOUNDS_PRELOOP:%.*]] ], [ 100, [[LOOP_PRELOOP_PREHEADER]] ]
127 ; CHECK-NEXT:    [[IDX_NEXT_PRELOOP]] = add i32 [[IDX_PRELOOP]], -1
128 ; CHECK-NEXT:    [[ABC_PRELOOP:%.*]] = icmp ult i32 [[IDX_PRELOOP]], [[LEN]]
129 ; CHECK-NEXT:    br i1 [[ABC_PRELOOP]], label [[IN_BOUNDS_PRELOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]]
130 ; CHECK:       in.bounds.preloop:
131 ; CHECK-NEXT:    [[ADDR_PRELOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_PRELOOP]]
132 ; CHECK-NEXT:    store i32 0, ptr [[ADDR_PRELOOP]], align 4
133 ; CHECK-NEXT:    [[NEXT_PRELOOP:%.*]] = icmp ult i32 [[IDX_NEXT_PRELOOP]], 1
134 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP]], [[EXIT_PRELOOP_AT]]
135 ; CHECK-NEXT:    [[TMP2:%.*]] = xor i1 [[TMP1]], true
136 ; CHECK-NEXT:    br i1 [[TMP2]], label [[PRELOOP_EXIT_SELECTOR:%.*]], label [[LOOP_PRELOOP]], !llvm.loop [[LOOP7:![0-9]+]], !loop_constrainer.loop.clone [[META6]]
137 ; CHECK:       preloop.exit.selector:
138 ; CHECK-NEXT:    [[IDX_NEXT_PRELOOP_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT_PRELOOP]], [[IN_BOUNDS_PRELOOP]] ]
139 ; CHECK-NEXT:    [[TMP3:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP_LCSSA]], 0
140 ; CHECK-NEXT:    br i1 [[TMP3]], label [[PRELOOP_PSEUDO_EXIT]], label [[EXIT]]
141 ; CHECK:       preloop.pseudo.exit:
142 ; CHECK-NEXT:    [[IDX_PRELOOP_COPY]] = phi i32 [ 100, [[ENTRY:%.*]] ], [ [[IDX_NEXT_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ]
143 ; CHECK-NEXT:    [[INDVAR_END:%.*]] = phi i32 [ 100, [[ENTRY]] ], [ [[IDX_NEXT_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ]
144 ; CHECK-NEXT:    br label [[MAINLOOP]]
147 entry:
148   %len = load i32, ptr %a_len_ptr, !range !0
149   br label %loop
151 loop:
152   %idx = phi i32 [ 100, %entry ], [ %idx.next, %in.bounds ]
153   %idx.next = add i32 %idx, -1
154   %abc = icmp ult i32 %idx, %len
155   br i1 %abc, label %in.bounds, label %out.of.bounds
157 in.bounds:
158   %addr = getelementptr i32, ptr %arr, i32 %idx
159   store i32 0, ptr %addr
160   %next = icmp ult i32 %idx.next, 1
161   br i1 %next, label %exit, label %loop
163 out.of.bounds:
164   ret void
166 exit:
167   ret void
170 ; Check SINT_MAX.
171 define void @test_03(ptr %arr, ptr %a_len_ptr) #0 {
172 ; CHECK-LABEL: define void @test_03
173 ; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
174 ; CHECK-NEXT:  entry:
175 ; CHECK-NEXT:    [[EXIT_MAINLOOP_AT:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0]]
176 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i32 0, [[EXIT_MAINLOOP_AT]]
177 ; CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
178 ; CHECK:       loop.preheader:
179 ; CHECK-NEXT:    br label [[LOOP:%.*]]
180 ; CHECK:       loop:
181 ; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
182 ; CHECK-NEXT:    [[IDX_NEXT]] = add nuw nsw i32 [[IDX]], 1
183 ; CHECK-NEXT:    [[ABC:%.*]] = icmp ult i32 [[IDX]], [[EXIT_MAINLOOP_AT]]
184 ; CHECK-NEXT:    br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]]
185 ; CHECK:       in.bounds:
186 ; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]
187 ; CHECK-NEXT:    store i32 0, ptr [[ADDR]], align 4
188 ; CHECK-NEXT:    [[NEXT:%.*]] = icmp ult i32 [[IDX_NEXT]], 2147483647
189 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]
190 ; CHECK-NEXT:    br i1 [[TMP1]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
191 ; CHECK:       main.exit.selector:
192 ; CHECK-NEXT:    [[IDX_NEXT_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT]], [[IN_BOUNDS]] ]
193 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i32 [[IDX_NEXT_LCSSA]], 2147483647
194 ; CHECK-NEXT:    br i1 [[TMP2]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT:%.*]]
195 ; CHECK:       main.pseudo.exit:
196 ; CHECK-NEXT:    [[IDX_COPY:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
197 ; CHECK-NEXT:    [[INDVAR_END:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
198 ; CHECK-NEXT:    br label [[POSTLOOP:%.*]]
199 ; CHECK:       out.of.bounds.loopexit:
200 ; CHECK-NEXT:    br label [[OUT_OF_BOUNDS:%.*]]
201 ; CHECK:       out.of.bounds.loopexit1:
202 ; CHECK-NEXT:    br label [[OUT_OF_BOUNDS]]
203 ; CHECK:       out.of.bounds:
204 ; CHECK-NEXT:    ret void
205 ; CHECK:       exit.loopexit:
206 ; CHECK-NEXT:    br label [[EXIT]]
207 ; CHECK:       exit:
208 ; CHECK-NEXT:    ret void
209 ; CHECK:       postloop:
210 ; CHECK-NEXT:    br label [[LOOP_POSTLOOP:%.*]]
211 ; CHECK:       loop.postloop:
212 ; CHECK-NEXT:    [[IDX_POSTLOOP:%.*]] = phi i32 [ [[IDX_COPY]], [[POSTLOOP]] ], [ [[IDX_NEXT_POSTLOOP:%.*]], [[IN_BOUNDS_POSTLOOP:%.*]] ]
213 ; CHECK-NEXT:    [[IDX_NEXT_POSTLOOP]] = add nuw nsw i32 [[IDX_POSTLOOP]], 1
214 ; CHECK-NEXT:    [[ABC_POSTLOOP:%.*]] = icmp ult i32 [[IDX_POSTLOOP]], [[EXIT_MAINLOOP_AT]]
215 ; CHECK-NEXT:    br i1 [[ABC_POSTLOOP]], label [[IN_BOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]]
216 ; CHECK:       in.bounds.postloop:
217 ; CHECK-NEXT:    [[ADDR_POSTLOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_POSTLOOP]]
218 ; CHECK-NEXT:    store i32 0, ptr [[ADDR_POSTLOOP]], align 4
219 ; CHECK-NEXT:    [[NEXT_POSTLOOP:%.*]] = icmp ult i32 [[IDX_NEXT_POSTLOOP]], 2147483647
220 ; CHECK-NEXT:    br i1 [[NEXT_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT:%.*]], !llvm.loop [[LOOP8:![0-9]+]], !loop_constrainer.loop.clone [[META6]]
223 entry:
224   %len = load i32, ptr %a_len_ptr, !range !0
225   br label %loop
227 loop:
228   %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
229   %idx.next = add nsw nuw i32 %idx, 1
230   %abc = icmp ult i32 %idx, %len
231   br i1 %abc, label %in.bounds, label %out.of.bounds
233 in.bounds:
234   %addr = getelementptr i32, ptr %arr, i32 %idx
235   store i32 0, ptr %addr
236   %next = icmp ult i32 %idx.next, 2147483647
237   br i1 %next, label %loop, label %exit
239 out.of.bounds:
240   ret void
242 exit:
243   ret void
246 ; Check SINT_MAX + 1, test is similar to test_01.
247 define void @test_04(ptr %arr, ptr %a_len_ptr) #0 {
248 ; CHECK-LABEL: define void @test_04
249 ; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
250 ; CHECK-NEXT:  entry:
251 ; CHECK-NEXT:    [[EXIT_MAINLOOP_AT:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0]]
252 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i32 0, [[EXIT_MAINLOOP_AT]]
253 ; CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
254 ; CHECK:       loop.preheader:
255 ; CHECK-NEXT:    br label [[LOOP:%.*]]
256 ; CHECK:       loop:
257 ; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
258 ; CHECK-NEXT:    [[IDX_NEXT]] = add nuw nsw i32 [[IDX]], 1
259 ; CHECK-NEXT:    [[ABC:%.*]] = icmp ult i32 [[IDX]], [[EXIT_MAINLOOP_AT]]
260 ; CHECK-NEXT:    br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]]
261 ; CHECK:       in.bounds:
262 ; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]
263 ; CHECK-NEXT:    store i32 0, ptr [[ADDR]], align 4
264 ; CHECK-NEXT:    [[NEXT:%.*]] = icmp ult i32 [[IDX_NEXT]], -2147483648
265 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]
266 ; CHECK-NEXT:    br i1 [[TMP1]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
267 ; CHECK:       main.exit.selector:
268 ; CHECK-NEXT:    [[IDX_NEXT_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT]], [[IN_BOUNDS]] ]
269 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i32 [[IDX_NEXT_LCSSA]], -2147483648
270 ; CHECK-NEXT:    br i1 [[TMP2]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT:%.*]]
271 ; CHECK:       main.pseudo.exit:
272 ; CHECK-NEXT:    [[IDX_COPY:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
273 ; CHECK-NEXT:    [[INDVAR_END:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
274 ; CHECK-NEXT:    br label [[POSTLOOP:%.*]]
275 ; CHECK:       out.of.bounds.loopexit:
276 ; CHECK-NEXT:    br label [[OUT_OF_BOUNDS:%.*]]
277 ; CHECK:       out.of.bounds.loopexit1:
278 ; CHECK-NEXT:    br label [[OUT_OF_BOUNDS]]
279 ; CHECK:       out.of.bounds:
280 ; CHECK-NEXT:    ret void
281 ; CHECK:       exit.loopexit:
282 ; CHECK-NEXT:    br label [[EXIT]]
283 ; CHECK:       exit:
284 ; CHECK-NEXT:    ret void
285 ; CHECK:       postloop:
286 ; CHECK-NEXT:    br label [[LOOP_POSTLOOP:%.*]]
287 ; CHECK:       loop.postloop:
288 ; CHECK-NEXT:    [[IDX_POSTLOOP:%.*]] = phi i32 [ [[IDX_COPY]], [[POSTLOOP]] ], [ [[IDX_NEXT_POSTLOOP:%.*]], [[IN_BOUNDS_POSTLOOP:%.*]] ]
289 ; CHECK-NEXT:    [[IDX_NEXT_POSTLOOP]] = add nuw nsw i32 [[IDX_POSTLOOP]], 1
290 ; CHECK-NEXT:    [[ABC_POSTLOOP:%.*]] = icmp ult i32 [[IDX_POSTLOOP]], [[EXIT_MAINLOOP_AT]]
291 ; CHECK-NEXT:    br i1 [[ABC_POSTLOOP]], label [[IN_BOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]]
292 ; CHECK:       in.bounds.postloop:
293 ; CHECK-NEXT:    [[ADDR_POSTLOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_POSTLOOP]]
294 ; CHECK-NEXT:    store i32 0, ptr [[ADDR_POSTLOOP]], align 4
295 ; CHECK-NEXT:    [[NEXT_POSTLOOP:%.*]] = icmp ult i32 [[IDX_NEXT_POSTLOOP]], -2147483648
296 ; CHECK-NEXT:    br i1 [[NEXT_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT:%.*]], !llvm.loop [[LOOP9:![0-9]+]], !loop_constrainer.loop.clone [[META6]]
299 entry:
300   %len = load i32, ptr %a_len_ptr, !range !0
301   br label %loop
303 loop:
304   %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
305   %idx.next = add nsw nuw i32 %idx, 1
306   %abc = icmp ult i32 %idx, %len
307   br i1 %abc, label %in.bounds, label %out.of.bounds
309 in.bounds:
310   %addr = getelementptr i32, ptr %arr, i32 %idx
311   store i32 0, ptr %addr
312   %next = icmp ult i32 %idx.next, 2147483648
313   br i1 %next, label %loop, label %exit
315 out.of.bounds:
316   ret void
318 exit:
319   ret void
322 ; Check SINT_MAX + 1, test is similar to test_02.
323 define void @test_05(ptr %arr, ptr %a_len_ptr) #0 {
324 ; CHECK-LABEL: define void @test_05
325 ; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
326 ; CHECK-NEXT:  entry:
327 ; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0]]
328 ; CHECK-NEXT:    [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[LEN]], i32 1)
329 ; CHECK-NEXT:    [[EXIT_PRELOOP_AT:%.*]] = add nsw i32 [[UMAX]], -1
330 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp ugt i32 -2147483648, [[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 i32 [[IDX]], -1
339 ; CHECK-NEXT:    [[ABC:%.*]] = icmp ult 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 ult i32 [[IDX_NEXT]], 1
345 ; CHECK-NEXT:    br i1 [[NEXT]], label [[EXIT_LOOPEXIT:%.*]], label [[LOOP]]
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:%.*]] ], [ -2147483648, [[LOOP_PRELOOP_PREHEADER]] ]
358 ; CHECK-NEXT:    [[IDX_NEXT_PRELOOP]] = add i32 [[IDX_PRELOOP]], -1
359 ; CHECK-NEXT:    [[ABC_PRELOOP:%.*]] = icmp ult 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 ult i32 [[IDX_NEXT_PRELOOP]], 1
365 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP]], [[EXIT_PRELOOP_AT]]
366 ; CHECK-NEXT:    [[TMP2:%.*]] = xor i1 [[TMP1]], true
367 ; CHECK-NEXT:    br i1 [[TMP2]], label [[PRELOOP_EXIT_SELECTOR:%.*]], label [[LOOP_PRELOOP]], !llvm.loop [[LOOP10:![0-9]+]], !loop_constrainer.loop.clone [[META6]]
368 ; CHECK:       preloop.exit.selector:
369 ; CHECK-NEXT:    [[IDX_NEXT_PRELOOP_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT_PRELOOP]], [[IN_BOUNDS_PRELOOP]] ]
370 ; CHECK-NEXT:    [[TMP3:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP_LCSSA]], 0
371 ; CHECK-NEXT:    br i1 [[TMP3]], label [[PRELOOP_PSEUDO_EXIT]], label [[EXIT]]
372 ; CHECK:       preloop.pseudo.exit:
373 ; CHECK-NEXT:    [[IDX_PRELOOP_COPY]] = phi i32 [ -2147483648, [[ENTRY:%.*]] ], [ [[IDX_NEXT_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ]
374 ; CHECK-NEXT:    [[INDVAR_END:%.*]] = phi i32 [ -2147483648, [[ENTRY]] ], [ [[IDX_NEXT_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ]
375 ; CHECK-NEXT:    br label [[MAINLOOP]]
378 entry:
379   %len = load i32, ptr %a_len_ptr, !range !0
380   br label %loop
382 loop:
383   %idx = phi i32 [ 2147483648, %entry ], [ %idx.next, %in.bounds ]
384   %idx.next = add i32 %idx, -1
385   %abc = icmp ult i32 %idx, %len
386   br i1 %abc, label %in.bounds, label %out.of.bounds
388 in.bounds:
389   %addr = getelementptr i32, ptr %arr, i32 %idx
390   store i32 0, ptr %addr
391   %next = icmp ult i32 %idx.next, 1
392   br i1 %next, label %exit, label %loop
394 out.of.bounds:
395   ret void
397 exit:
398   ret void
401 ; Increasing loop, UINT_MAX. Positive test.
402 define void @test_06(ptr %arr, ptr %a_len_ptr) #0 {
403 ; CHECK-LABEL: define void @test_06
404 ; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
405 ; CHECK-NEXT:  entry:
406 ; CHECK-NEXT:    [[EXIT_MAINLOOP_AT:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0]]
407 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i32 0, [[EXIT_MAINLOOP_AT]]
408 ; CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
409 ; CHECK:       loop.preheader:
410 ; CHECK-NEXT:    br label [[LOOP:%.*]]
411 ; CHECK:       loop:
412 ; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
413 ; CHECK-NEXT:    [[IDX_NEXT]] = add nuw nsw i32 [[IDX]], 1
414 ; CHECK-NEXT:    [[ABC:%.*]] = icmp ult i32 [[IDX]], [[EXIT_MAINLOOP_AT]]
415 ; CHECK-NEXT:    br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]]
416 ; CHECK:       in.bounds:
417 ; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]
418 ; CHECK-NEXT:    store i32 0, ptr [[ADDR]], align 4
419 ; CHECK-NEXT:    [[NEXT:%.*]] = icmp ult i32 [[IDX_NEXT]], -1
420 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]
421 ; CHECK-NEXT:    br i1 [[TMP1]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
422 ; CHECK:       main.exit.selector:
423 ; CHECK-NEXT:    [[IDX_NEXT_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT]], [[IN_BOUNDS]] ]
424 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i32 [[IDX_NEXT_LCSSA]], -1
425 ; CHECK-NEXT:    br i1 [[TMP2]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT:%.*]]
426 ; CHECK:       main.pseudo.exit:
427 ; CHECK-NEXT:    [[IDX_COPY:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
428 ; CHECK-NEXT:    [[INDVAR_END:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
429 ; CHECK-NEXT:    br label [[POSTLOOP:%.*]]
430 ; CHECK:       out.of.bounds.loopexit:
431 ; CHECK-NEXT:    br label [[OUT_OF_BOUNDS:%.*]]
432 ; CHECK:       out.of.bounds.loopexit1:
433 ; CHECK-NEXT:    br label [[OUT_OF_BOUNDS]]
434 ; CHECK:       out.of.bounds:
435 ; CHECK-NEXT:    ret void
436 ; CHECK:       exit.loopexit:
437 ; CHECK-NEXT:    br label [[EXIT]]
438 ; CHECK:       exit:
439 ; CHECK-NEXT:    ret void
440 ; CHECK:       postloop:
441 ; CHECK-NEXT:    br label [[LOOP_POSTLOOP:%.*]]
442 ; CHECK:       loop.postloop:
443 ; CHECK-NEXT:    [[IDX_POSTLOOP:%.*]] = phi i32 [ [[IDX_COPY]], [[POSTLOOP]] ], [ [[IDX_NEXT_POSTLOOP:%.*]], [[IN_BOUNDS_POSTLOOP:%.*]] ]
444 ; CHECK-NEXT:    [[IDX_NEXT_POSTLOOP]] = add nuw nsw i32 [[IDX_POSTLOOP]], 1
445 ; CHECK-NEXT:    [[ABC_POSTLOOP:%.*]] = icmp ult i32 [[IDX_POSTLOOP]], [[EXIT_MAINLOOP_AT]]
446 ; CHECK-NEXT:    br i1 [[ABC_POSTLOOP]], label [[IN_BOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]]
447 ; CHECK:       in.bounds.postloop:
448 ; CHECK-NEXT:    [[ADDR_POSTLOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_POSTLOOP]]
449 ; CHECK-NEXT:    store i32 0, ptr [[ADDR_POSTLOOP]], align 4
450 ; CHECK-NEXT:    [[NEXT_POSTLOOP:%.*]] = icmp ult i32 [[IDX_NEXT_POSTLOOP]], -1
451 ; CHECK-NEXT:    br i1 [[NEXT_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT:%.*]], !llvm.loop [[LOOP11:![0-9]+]], !loop_constrainer.loop.clone [[META6]]
454 entry:
455   %len = load i32, ptr %a_len_ptr, !range !0
456   br label %loop
458 loop:
459   %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
460   %idx.next = add nsw nuw i32 %idx, 1
461   %abc = icmp ult 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 ult i32 %idx.next, 4294967295
468   br i1 %next, label %loop, label %exit
470 out.of.bounds:
471   ret void
473 exit:
474   ret void
477 ; Decreasing loop, UINT_MAX. Negative test: we cannot substract -1 from 0.
478 define void @test_07(ptr %arr, ptr %a_len_ptr) #0 {
479 ; CHECK-LABEL: define void @test_07
480 ; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
481 ; CHECK-NEXT:  entry:
482 ; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0]]
483 ; CHECK-NEXT:    br label [[LOOP:%.*]]
484 ; CHECK:       loop:
485 ; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ]
486 ; CHECK-NEXT:    [[IDX_NEXT]] = add nuw i32 [[IDX]], -1
487 ; CHECK-NEXT:    [[ABC:%.*]] = icmp ult i32 [[IDX]], [[LEN]]
488 ; CHECK-NEXT:    br i1 [[ABC]], label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS:%.*]]
489 ; CHECK:       in.bounds:
490 ; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]
491 ; CHECK-NEXT:    store i32 0, ptr [[ADDR]], align 4
492 ; CHECK-NEXT:    [[NEXT:%.*]] = icmp ult i32 [[IDX_NEXT]], 0
493 ; CHECK-NEXT:    br i1 [[NEXT]], label [[EXIT:%.*]], label [[LOOP]]
494 ; CHECK:       out.of.bounds:
495 ; CHECK-NEXT:    ret void
496 ; CHECK:       exit:
497 ; CHECK-NEXT:    ret void
500 entry:
501   %len = load i32, ptr %a_len_ptr, !range !0
502   br label %loop
504 loop:
505   %idx = phi i32 [ 4294967295, %entry ], [ %idx.next, %in.bounds ]
506   %idx.next = add nuw i32 %idx, -1
507   %abc = icmp ult i32 %idx, %len
508   br i1 %abc, label %in.bounds, label %out.of.bounds
510 in.bounds:
511   %addr = getelementptr i32, ptr %arr, i32 %idx
512   store i32 0, ptr %addr
513   %next = icmp ult i32 %idx.next, 0
514   br i1 %next, label %exit, label %loop
516 out.of.bounds:
517   ret void
519 exit:
520   ret void
523 ; Unsigned walking through signed border is allowed.
524 ; Iteration space [0; UINT_MAX - 99), the fact that SINT_MAX is within this
525 ; range does not prevent us from performing IRCE.
527 define void @test_08(ptr %arr, ptr %a_len_ptr) #0 {
528 ; CHECK-LABEL: define void @test_08
529 ; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
530 ; CHECK-NEXT:  entry:
531 ; CHECK-NEXT:    [[EXIT_MAINLOOP_AT:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0]]
532 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i32 0, [[EXIT_MAINLOOP_AT]]
533 ; CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
534 ; CHECK:       loop.preheader:
535 ; CHECK-NEXT:    br label [[LOOP:%.*]]
536 ; CHECK:       loop:
537 ; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
538 ; CHECK-NEXT:    [[IDX_NEXT]] = add i32 [[IDX]], 1
539 ; CHECK-NEXT:    [[ABC:%.*]] = icmp ult i32 [[IDX]], [[EXIT_MAINLOOP_AT]]
540 ; CHECK-NEXT:    br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]]
541 ; CHECK:       in.bounds:
542 ; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]
543 ; CHECK-NEXT:    store i32 0, ptr [[ADDR]], align 4
544 ; CHECK-NEXT:    [[NEXT:%.*]] = icmp ult i32 [[IDX_NEXT]], -100
545 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]
546 ; CHECK-NEXT:    br i1 [[TMP1]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
547 ; CHECK:       main.exit.selector:
548 ; CHECK-NEXT:    [[IDX_NEXT_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT]], [[IN_BOUNDS]] ]
549 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i32 [[IDX_NEXT_LCSSA]], -100
550 ; CHECK-NEXT:    br i1 [[TMP2]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT:%.*]]
551 ; CHECK:       main.pseudo.exit:
552 ; CHECK-NEXT:    [[IDX_COPY:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
553 ; CHECK-NEXT:    [[INDVAR_END:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
554 ; CHECK-NEXT:    br label [[POSTLOOP:%.*]]
555 ; CHECK:       out.of.bounds.loopexit:
556 ; CHECK-NEXT:    br label [[OUT_OF_BOUNDS:%.*]]
557 ; CHECK:       out.of.bounds.loopexit1:
558 ; CHECK-NEXT:    br label [[OUT_OF_BOUNDS]]
559 ; CHECK:       out.of.bounds:
560 ; CHECK-NEXT:    ret void
561 ; CHECK:       exit.loopexit:
562 ; CHECK-NEXT:    br label [[EXIT]]
563 ; CHECK:       exit:
564 ; CHECK-NEXT:    ret void
565 ; CHECK:       postloop:
566 ; CHECK-NEXT:    br label [[LOOP_POSTLOOP:%.*]]
567 ; CHECK:       loop.postloop:
568 ; CHECK-NEXT:    [[IDX_POSTLOOP:%.*]] = phi i32 [ [[IDX_COPY]], [[POSTLOOP]] ], [ [[IDX_NEXT_POSTLOOP:%.*]], [[IN_BOUNDS_POSTLOOP:%.*]] ]
569 ; CHECK-NEXT:    [[IDX_NEXT_POSTLOOP]] = add i32 [[IDX_POSTLOOP]], 1
570 ; CHECK-NEXT:    [[ABC_POSTLOOP:%.*]] = icmp ult i32 [[IDX_POSTLOOP]], [[EXIT_MAINLOOP_AT]]
571 ; CHECK-NEXT:    br i1 [[ABC_POSTLOOP]], label [[IN_BOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]]
572 ; CHECK:       in.bounds.postloop:
573 ; CHECK-NEXT:    [[ADDR_POSTLOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_POSTLOOP]]
574 ; CHECK-NEXT:    store i32 0, ptr [[ADDR_POSTLOOP]], align 4
575 ; CHECK-NEXT:    [[NEXT_POSTLOOP:%.*]] = icmp ult i32 [[IDX_NEXT_POSTLOOP]], -100
576 ; CHECK-NEXT:    br i1 [[NEXT_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT:%.*]], !llvm.loop [[LOOP12:![0-9]+]], !loop_constrainer.loop.clone [[META6]]
579 entry:
580   %len = load i32, ptr %a_len_ptr, !range !0
581   br label %loop
583 loop:
584   %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
585   %idx.next = add i32 %idx, 1
586   %abc = icmp ult i32 %idx, %len
587   br i1 %abc, label %in.bounds, label %out.of.bounds
589 in.bounds:
590   %addr = getelementptr i32, ptr %arr, i32 %idx
591   store i32 0, ptr %addr
592   %next = icmp ult i32 %idx.next, -100
593   br i1 %next, label %loop, label %exit
595 out.of.bounds:
596   ret void
598 exit:
599   ret void
602 ; Walking through the border of unsigned range is not allowed
603 ; (iteration space [-100; 100)). Negative test.
605 define void @test_09(ptr %arr, ptr %a_len_ptr) #0 {
606 ; CHECK-LABEL: define void @test_09
607 ; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
608 ; CHECK-NEXT:  entry:
609 ; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0]]
610 ; CHECK-NEXT:    br label [[LOOP:%.*]]
611 ; CHECK:       loop:
612 ; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ -100, [[ENTRY:%.*]] ], [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ]
613 ; CHECK-NEXT:    [[IDX_NEXT]] = add i32 [[IDX]], 1
614 ; CHECK-NEXT:    [[ABC:%.*]] = icmp ult i32 [[IDX]], [[LEN]]
615 ; CHECK-NEXT:    br i1 [[ABC]], label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS:%.*]]
616 ; CHECK:       in.bounds:
617 ; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]
618 ; CHECK-NEXT:    store i32 0, ptr [[ADDR]], align 4
619 ; CHECK-NEXT:    [[NEXT:%.*]] = icmp ult i32 [[IDX_NEXT]], 100
620 ; CHECK-NEXT:    br i1 [[NEXT]], label [[LOOP]], label [[EXIT:%.*]]
621 ; CHECK:       out.of.bounds:
622 ; CHECK-NEXT:    ret void
623 ; CHECK:       exit:
624 ; CHECK-NEXT:    ret void
627 entry:
628   %len = load i32, ptr %a_len_ptr, !range !0
629   br label %loop
631 loop:
632   %idx = phi i32 [ -100, %entry ], [ %idx.next, %in.bounds ]
633   %idx.next = add i32 %idx, 1
634   %abc = icmp ult i32 %idx, %len
635   br i1 %abc, label %in.bounds, label %out.of.bounds
637 in.bounds:
638   %addr = getelementptr i32, ptr %arr, i32 %idx
639   store i32 0, ptr %addr
640   %next = icmp ult i32 %idx.next, 100
641   br i1 %next, label %loop, label %exit
643 out.of.bounds:
644   ret void
646 exit:
647   ret void
650 !0 = !{i32 0, i32 50}
652 ; CHECK: [[RNG0]] = !{i32 0, i32 50}
653 ; CHECK: [[LOOP1]] = distinct !{[[LOOP1]], [[META2:![0-9]+]], [[META3:![0-9]+]], [[META4:![0-9]+]], [[META5:![0-9]+]]}
654 ; CHECK: [[META2]] = !{!"llvm.loop.unroll.disable"}
655 ; CHECK: [[META3]] = !{!"llvm.loop.vectorize.enable", i1 false}
656 ; CHECK: [[META4]] = !{!"llvm.loop.licm_versioning.disable"}
657 ; CHECK: [[META5]] = !{!"llvm.loop.distribute.enable", i1 false}
658 ; CHECK: [[META6]] = !{}
659 ; CHECK: [[LOOP7]] = distinct !{[[LOOP7]], [[META2]], [[META3]], [[META4]], [[META5]]}
660 ; CHECK: [[LOOP8]] = distinct !{[[LOOP8]], [[META2]], [[META3]], [[META4]], [[META5]]}
661 ; CHECK: [[LOOP9]] = distinct !{[[LOOP9]], [[META2]], [[META3]], [[META4]], [[META5]]}
662 ; CHECK: [[LOOP10]] = distinct !{[[LOOP10]], [[META2]], [[META3]], [[META4]], [[META5]]}
663 ; CHECK: [[LOOP11]] = distinct !{[[LOOP11]], [[META2]], [[META3]], [[META4]], [[META5]]}
664 ; CHECK: [[LOOP12]] = distinct !{[[LOOP12]], [[META2]], [[META3]], [[META4]], [[META5]]}