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-NOT: 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>
12 ; UGT condition for increasing loop.
13 define void @test_01(ptr %arr, ptr %a_len_ptr) #0 {
14 ; CHECK-LABEL: define void @test_01
15 ; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
17 ; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0:![0-9]+]]
18 ; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 0, [[EXIT_MAINLOOP_AT]]
19 ; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
20 ; CHECK: loop.preheader:
21 ; CHECK-NEXT: br label [[LOOP:%.*]]
23 ; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
24 ; CHECK-NEXT: [[IDX_NEXT]] = add nuw nsw i32 [[IDX]], 1
25 ; CHECK-NEXT: [[ABC:%.*]] = icmp ult i32 [[IDX]], [[EXIT_MAINLOOP_AT]]
26 ; CHECK-NEXT: br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]]
28 ; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]
29 ; CHECK-NEXT: store i32 0, ptr [[ADDR]], align 4
30 ; CHECK-NEXT: [[NEXT:%.*]] = icmp ugt i32 [[IDX_NEXT]], 100
31 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]
32 ; CHECK-NEXT: [[TMP2:%.*]] = xor i1 [[TMP1]], true
33 ; CHECK-NEXT: br i1 [[TMP2]], label [[MAIN_EXIT_SELECTOR:%.*]], label [[LOOP]]
34 ; CHECK: main.exit.selector:
35 ; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT]], [[IN_BOUNDS]] ]
36 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ult i32 [[IDX_NEXT_LCSSA]], 101
37 ; CHECK-NEXT: br i1 [[TMP3]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT:%.*]]
38 ; CHECK: main.pseudo.exit:
39 ; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
40 ; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
41 ; CHECK-NEXT: br label [[POSTLOOP:%.*]]
42 ; CHECK: out.of.bounds.loopexit:
43 ; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]
44 ; CHECK: out.of.bounds.loopexit1:
45 ; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]
46 ; CHECK: out.of.bounds:
47 ; CHECK-NEXT: ret void
48 ; CHECK: exit.loopexit:
49 ; CHECK-NEXT: br label [[EXIT]]
51 ; CHECK-NEXT: ret void
53 ; CHECK-NEXT: br label [[LOOP_POSTLOOP:%.*]]
54 ; CHECK: loop.postloop:
55 ; CHECK-NEXT: [[IDX_POSTLOOP:%.*]] = phi i32 [ [[IDX_COPY]], [[POSTLOOP]] ], [ [[IDX_NEXT_POSTLOOP:%.*]], [[IN_BOUNDS_POSTLOOP:%.*]] ]
56 ; CHECK-NEXT: [[IDX_NEXT_POSTLOOP]] = add nuw nsw i32 [[IDX_POSTLOOP]], 1
57 ; CHECK-NEXT: [[ABC_POSTLOOP:%.*]] = icmp ult i32 [[IDX_POSTLOOP]], [[EXIT_MAINLOOP_AT]]
58 ; CHECK-NEXT: br i1 [[ABC_POSTLOOP]], label [[IN_BOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]]
59 ; CHECK: in.bounds.postloop:
60 ; CHECK-NEXT: [[ADDR_POSTLOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_POSTLOOP]]
61 ; CHECK-NEXT: store i32 0, ptr [[ADDR_POSTLOOP]], align 4
62 ; CHECK-NEXT: [[NEXT_POSTLOOP:%.*]] = icmp ugt i32 [[IDX_NEXT_POSTLOOP]], 100
63 ; CHECK-NEXT: br i1 [[NEXT_POSTLOOP]], label [[EXIT_LOOPEXIT:%.*]], label [[LOOP_POSTLOOP]], !llvm.loop [[LOOP1:![0-9]+]], !loop_constrainer.loop.clone [[META6:![0-9]+]]
67 %len = load i32, ptr %a_len_ptr, !range !0
71 %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
72 %idx.next = add nsw nuw i32 %idx, 1
73 %abc = icmp ult i32 %idx, %len
74 br i1 %abc, label %in.bounds, label %out.of.bounds
77 %addr = getelementptr i32, ptr %arr, i32 %idx
78 store i32 0, ptr %addr
79 %next = icmp ugt i32 %idx.next, 100
80 br i1 %next, label %exit, label %loop
89 ; UGT condition for decreasing loop.
90 define void @test_02(ptr %arr, ptr %a_len_ptr) #0 {
91 ; CHECK-LABEL: define void @test_02
92 ; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
94 ; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0]]
95 ; CHECK-NEXT: [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[LEN]], i32 1)
96 ; CHECK-NEXT: [[EXIT_PRELOOP_AT:%.*]] = add nsw i32 [[UMAX]], -1
97 ; CHECK-NEXT: [[TMP0:%.*]] = icmp ugt i32 100, [[EXIT_PRELOOP_AT]]
98 ; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP_PRELOOP_PREHEADER:%.*]], label [[PRELOOP_PSEUDO_EXIT:%.*]]
99 ; CHECK: loop.preloop.preheader:
100 ; CHECK-NEXT: br label [[LOOP_PRELOOP:%.*]]
102 ; CHECK-NEXT: br label [[LOOP:%.*]]
104 ; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_PRELOOP_COPY:%.*]], [[MAINLOOP:%.*]] ], [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ]
105 ; CHECK-NEXT: [[IDX_NEXT]] = add i32 [[IDX]], -1
106 ; CHECK-NEXT: [[ABC:%.*]] = icmp ult i32 [[IDX]], [[LEN]]
107 ; CHECK-NEXT: br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]]
109 ; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]
110 ; CHECK-NEXT: store i32 0, ptr [[ADDR]], align 4
111 ; CHECK-NEXT: [[NEXT:%.*]] = icmp ugt i32 [[IDX_NEXT]], 0
112 ; CHECK-NEXT: br i1 [[NEXT]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
113 ; CHECK: out.of.bounds.loopexit:
114 ; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]
115 ; CHECK: out.of.bounds.loopexit1:
116 ; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]
117 ; CHECK: out.of.bounds:
118 ; CHECK-NEXT: ret void
119 ; CHECK: exit.loopexit:
120 ; CHECK-NEXT: br label [[EXIT:%.*]]
122 ; CHECK-NEXT: ret void
123 ; CHECK: loop.preloop:
124 ; CHECK-NEXT: [[IDX_PRELOOP:%.*]] = phi i32 [ [[IDX_NEXT_PRELOOP:%.*]], [[IN_BOUNDS_PRELOOP:%.*]] ], [ 100, [[LOOP_PRELOOP_PREHEADER]] ]
125 ; CHECK-NEXT: [[IDX_NEXT_PRELOOP]] = add i32 [[IDX_PRELOOP]], -1
126 ; CHECK-NEXT: [[ABC_PRELOOP:%.*]] = icmp ult i32 [[IDX_PRELOOP]], [[LEN]]
127 ; CHECK-NEXT: br i1 [[ABC_PRELOOP]], label [[IN_BOUNDS_PRELOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]]
128 ; CHECK: in.bounds.preloop:
129 ; CHECK-NEXT: [[ADDR_PRELOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_PRELOOP]]
130 ; CHECK-NEXT: store i32 0, ptr [[ADDR_PRELOOP]], align 4
131 ; CHECK-NEXT: [[NEXT_PRELOOP:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP]], 0
132 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP]], [[EXIT_PRELOOP_AT]]
133 ; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP_PRELOOP]], label [[PRELOOP_EXIT_SELECTOR:%.*]], !llvm.loop [[LOOP7:![0-9]+]], !loop_constrainer.loop.clone [[META6]]
134 ; CHECK: preloop.exit.selector:
135 ; CHECK-NEXT: [[IDX_NEXT_PRELOOP_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT_PRELOOP]], [[IN_BOUNDS_PRELOOP]] ]
136 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP_LCSSA]], 0
137 ; CHECK-NEXT: br i1 [[TMP2]], label [[PRELOOP_PSEUDO_EXIT]], label [[EXIT]]
138 ; CHECK: preloop.pseudo.exit:
139 ; CHECK-NEXT: [[IDX_PRELOOP_COPY]] = phi i32 [ 100, [[ENTRY:%.*]] ], [ [[IDX_NEXT_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ]
140 ; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 100, [[ENTRY]] ], [ [[IDX_NEXT_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ]
141 ; CHECK-NEXT: br label [[MAINLOOP]]
145 %len = load i32, ptr %a_len_ptr, !range !0
149 %idx = phi i32 [ 100, %entry ], [ %idx.next, %in.bounds ]
150 %idx.next = add i32 %idx, -1
151 %abc = icmp ult i32 %idx, %len
152 br i1 %abc, label %in.bounds, label %out.of.bounds
155 %addr = getelementptr i32, ptr %arr, i32 %idx
156 store i32 0, ptr %addr
157 %next = icmp ugt i32 %idx.next, 0
158 br i1 %next, label %loop, label %exit
167 ; Check SINT_MAX + 1, test is similar to test_01.
168 define void @test_03(ptr %arr, ptr %a_len_ptr) #0 {
169 ; CHECK-LABEL: define void @test_03
170 ; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
172 ; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0]]
173 ; CHECK-NEXT: [[TMP0:%.*]] = icmp ult 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:%.*]]
178 ; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
179 ; CHECK-NEXT: [[IDX_NEXT]] = add nuw nsw i32 [[IDX]], 1
180 ; CHECK-NEXT: [[ABC:%.*]] = icmp ult i32 [[IDX]], [[EXIT_MAINLOOP_AT]]
181 ; CHECK-NEXT: br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]]
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 ugt i32 [[IDX_NEXT]], -2147483648
186 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]
187 ; CHECK-NEXT: [[TMP2:%.*]] = xor i1 [[TMP1]], true
188 ; CHECK-NEXT: br i1 [[TMP2]], label [[MAIN_EXIT_SELECTOR:%.*]], label [[LOOP]]
189 ; CHECK: main.exit.selector:
190 ; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT]], [[IN_BOUNDS]] ]
191 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ult i32 [[IDX_NEXT_LCSSA]], -2147483647
192 ; CHECK-NEXT: br i1 [[TMP3]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT:%.*]]
193 ; CHECK: main.pseudo.exit:
194 ; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
195 ; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
196 ; CHECK-NEXT: br label [[POSTLOOP:%.*]]
197 ; CHECK: out.of.bounds.loopexit:
198 ; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]
199 ; CHECK: out.of.bounds.loopexit1:
200 ; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]
201 ; CHECK: out.of.bounds:
202 ; CHECK-NEXT: ret void
203 ; CHECK: exit.loopexit:
204 ; CHECK-NEXT: br label [[EXIT]]
206 ; CHECK-NEXT: ret void
208 ; CHECK-NEXT: br label [[LOOP_POSTLOOP:%.*]]
209 ; CHECK: loop.postloop:
210 ; CHECK-NEXT: [[IDX_POSTLOOP:%.*]] = phi i32 [ [[IDX_COPY]], [[POSTLOOP]] ], [ [[IDX_NEXT_POSTLOOP:%.*]], [[IN_BOUNDS_POSTLOOP:%.*]] ]
211 ; CHECK-NEXT: [[IDX_NEXT_POSTLOOP]] = add nuw nsw i32 [[IDX_POSTLOOP]], 1
212 ; CHECK-NEXT: [[ABC_POSTLOOP:%.*]] = icmp ult i32 [[IDX_POSTLOOP]], [[EXIT_MAINLOOP_AT]]
213 ; CHECK-NEXT: br i1 [[ABC_POSTLOOP]], label [[IN_BOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]]
214 ; CHECK: in.bounds.postloop:
215 ; CHECK-NEXT: [[ADDR_POSTLOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_POSTLOOP]]
216 ; CHECK-NEXT: store i32 0, ptr [[ADDR_POSTLOOP]], align 4
217 ; CHECK-NEXT: [[NEXT_POSTLOOP:%.*]] = icmp ugt i32 [[IDX_NEXT_POSTLOOP]], -2147483648
218 ; CHECK-NEXT: br i1 [[NEXT_POSTLOOP]], label [[EXIT_LOOPEXIT:%.*]], label [[LOOP_POSTLOOP]], !llvm.loop [[LOOP8:![0-9]+]], !loop_constrainer.loop.clone [[META6]]
222 %len = load i32, ptr %a_len_ptr, !range !0
226 %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
227 %idx.next = add nsw nuw i32 %idx, 1
228 %abc = icmp ult i32 %idx, %len
229 br i1 %abc, label %in.bounds, label %out.of.bounds
232 %addr = getelementptr i32, ptr %arr, i32 %idx
233 store i32 0, ptr %addr
234 %next = icmp ugt i32 %idx.next, 2147483648
235 br i1 %next, label %exit, label %loop
244 ; Check SINT_MAX + 1, test is similar to test_02.
245 define void @test_04(ptr %arr, ptr %a_len_ptr) #0 {
246 ; CHECK-LABEL: define void @test_04
247 ; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
249 ; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0]]
250 ; CHECK-NEXT: [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[LEN]], i32 1)
251 ; CHECK-NEXT: [[EXIT_PRELOOP_AT:%.*]] = add nsw i32 [[UMAX]], -1
252 ; CHECK-NEXT: [[TMP0:%.*]] = icmp ugt i32 -2147483648, [[EXIT_PRELOOP_AT]]
253 ; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP_PRELOOP_PREHEADER:%.*]], label [[PRELOOP_PSEUDO_EXIT:%.*]]
254 ; CHECK: loop.preloop.preheader:
255 ; CHECK-NEXT: br label [[LOOP_PRELOOP:%.*]]
257 ; CHECK-NEXT: br label [[LOOP:%.*]]
259 ; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_PRELOOP_COPY:%.*]], [[MAINLOOP:%.*]] ], [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ]
260 ; CHECK-NEXT: [[IDX_NEXT]] = add i32 [[IDX]], -1
261 ; CHECK-NEXT: [[ABC:%.*]] = icmp ult i32 [[IDX]], [[LEN]]
262 ; CHECK-NEXT: br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]]
264 ; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]
265 ; CHECK-NEXT: store i32 0, ptr [[ADDR]], align 4
266 ; CHECK-NEXT: [[NEXT:%.*]] = icmp ugt i32 [[IDX_NEXT]], 0
267 ; CHECK-NEXT: br i1 [[NEXT]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
268 ; CHECK: out.of.bounds.loopexit:
269 ; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]
270 ; CHECK: out.of.bounds.loopexit1:
271 ; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]
272 ; CHECK: out.of.bounds:
273 ; CHECK-NEXT: ret void
274 ; CHECK: exit.loopexit:
275 ; CHECK-NEXT: br label [[EXIT:%.*]]
277 ; CHECK-NEXT: ret void
278 ; CHECK: loop.preloop:
279 ; CHECK-NEXT: [[IDX_PRELOOP:%.*]] = phi i32 [ [[IDX_NEXT_PRELOOP:%.*]], [[IN_BOUNDS_PRELOOP:%.*]] ], [ -2147483648, [[LOOP_PRELOOP_PREHEADER]] ]
280 ; CHECK-NEXT: [[IDX_NEXT_PRELOOP]] = add i32 [[IDX_PRELOOP]], -1
281 ; CHECK-NEXT: [[ABC_PRELOOP:%.*]] = icmp ult i32 [[IDX_PRELOOP]], [[LEN]]
282 ; CHECK-NEXT: br i1 [[ABC_PRELOOP]], label [[IN_BOUNDS_PRELOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]]
283 ; CHECK: in.bounds.preloop:
284 ; CHECK-NEXT: [[ADDR_PRELOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_PRELOOP]]
285 ; CHECK-NEXT: store i32 0, ptr [[ADDR_PRELOOP]], align 4
286 ; CHECK-NEXT: [[NEXT_PRELOOP:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP]], 0
287 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP]], [[EXIT_PRELOOP_AT]]
288 ; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP_PRELOOP]], label [[PRELOOP_EXIT_SELECTOR:%.*]], !llvm.loop [[LOOP9:![0-9]+]], !loop_constrainer.loop.clone [[META6]]
289 ; CHECK: preloop.exit.selector:
290 ; CHECK-NEXT: [[IDX_NEXT_PRELOOP_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT_PRELOOP]], [[IN_BOUNDS_PRELOOP]] ]
291 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP_LCSSA]], 0
292 ; CHECK-NEXT: br i1 [[TMP2]], label [[PRELOOP_PSEUDO_EXIT]], label [[EXIT]]
293 ; CHECK: preloop.pseudo.exit:
294 ; CHECK-NEXT: [[IDX_PRELOOP_COPY]] = phi i32 [ -2147483648, [[ENTRY:%.*]] ], [ [[IDX_NEXT_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ]
295 ; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ -2147483648, [[ENTRY]] ], [ [[IDX_NEXT_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ]
296 ; CHECK-NEXT: br label [[MAINLOOP]]
300 %len = load i32, ptr %a_len_ptr, !range !0
304 %idx = phi i32 [ 2147483648, %entry ], [ %idx.next, %in.bounds ]
305 %idx.next = add i32 %idx, -1
306 %abc = icmp ult i32 %idx, %len
307 br i1 %abc, label %in.bounds, label %out.of.bounds
310 %addr = getelementptr i32, ptr %arr, i32 %idx
311 store i32 0, ptr %addr
312 %next = icmp ugt i32 %idx.next, 0
313 br i1 %next, label %loop, label %exit
322 ; Increasing loop, UINT_MAX. Negative test: we cannot add 1 to UINT_MAX.
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:%.*]]) {
327 ; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0]]
328 ; CHECK-NEXT: br label [[LOOP:%.*]]
330 ; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ]
331 ; CHECK-NEXT: [[IDX_NEXT]] = add nuw nsw i32 [[IDX]], 1
332 ; CHECK-NEXT: [[ABC:%.*]] = icmp ult i32 [[IDX]], [[LEN]]
333 ; CHECK-NEXT: br i1 [[ABC]], label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS:%.*]]
335 ; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]
336 ; CHECK-NEXT: store i32 0, ptr [[ADDR]], align 4
337 ; CHECK-NEXT: [[NEXT:%.*]] = icmp ugt i32 [[IDX_NEXT]], -1
338 ; CHECK-NEXT: br i1 [[NEXT]], label [[EXIT:%.*]], label [[LOOP]]
339 ; CHECK: out.of.bounds:
340 ; CHECK-NEXT: ret void
342 ; CHECK-NEXT: ret void
346 %len = load i32, ptr %a_len_ptr, !range !0
350 %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
351 %idx.next = add nsw nuw i32 %idx, 1
352 %abc = icmp ult i32 %idx, %len
353 br i1 %abc, label %in.bounds, label %out.of.bounds
356 %addr = getelementptr i32, ptr %arr, i32 %idx
357 store i32 0, ptr %addr
358 %next = icmp ugt i32 %idx.next, 4294967295
359 br i1 %next, label %exit, label %loop
368 ; Decreasing loop, UINT_MAX. Positive test.
369 define void @test_06(ptr %arr, ptr %a_len_ptr) #0 {
370 ; CHECK-LABEL: define void @test_06
371 ; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
373 ; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0]]
374 ; CHECK-NEXT: br i1 true, label [[LOOP_PRELOOP_PREHEADER:%.*]], label [[PRELOOP_PSEUDO_EXIT:%.*]]
375 ; CHECK: loop.preloop.preheader:
376 ; CHECK-NEXT: br label [[LOOP_PRELOOP:%.*]]
378 ; CHECK-NEXT: br label [[LOOP:%.*]]
380 ; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_PRELOOP_COPY:%.*]], [[MAINLOOP:%.*]] ], [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ]
381 ; CHECK-NEXT: [[IDX_NEXT]] = add nuw i32 [[IDX]], -1
382 ; CHECK-NEXT: [[ABC:%.*]] = icmp ult i32 [[IDX]], [[LEN]]
383 ; CHECK-NEXT: br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]]
385 ; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]
386 ; CHECK-NEXT: store i32 0, ptr [[ADDR]], align 4
387 ; CHECK-NEXT: [[NEXT:%.*]] = icmp ugt i32 [[IDX_NEXT]], 0
388 ; CHECK-NEXT: br i1 [[NEXT]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
389 ; CHECK: out.of.bounds.loopexit:
390 ; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]
391 ; CHECK: out.of.bounds.loopexit1:
392 ; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]
393 ; CHECK: out.of.bounds:
394 ; CHECK-NEXT: ret void
395 ; CHECK: exit.loopexit:
396 ; CHECK-NEXT: br label [[EXIT:%.*]]
398 ; CHECK-NEXT: ret void
399 ; CHECK: loop.preloop:
400 ; CHECK-NEXT: [[IDX_PRELOOP:%.*]] = phi i32 [ [[IDX_NEXT_PRELOOP:%.*]], [[IN_BOUNDS_PRELOOP:%.*]] ], [ -1, [[LOOP_PRELOOP_PREHEADER]] ]
401 ; CHECK-NEXT: [[IDX_NEXT_PRELOOP]] = add nuw i32 [[IDX_PRELOOP]], -1
402 ; CHECK-NEXT: [[ABC_PRELOOP:%.*]] = icmp ult i32 [[IDX_PRELOOP]], [[LEN]]
403 ; CHECK-NEXT: br i1 [[ABC_PRELOOP]], label [[IN_BOUNDS_PRELOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]]
404 ; CHECK: in.bounds.preloop:
405 ; CHECK-NEXT: [[ADDR_PRELOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_PRELOOP]]
406 ; CHECK-NEXT: store i32 0, ptr [[ADDR_PRELOOP]], align 4
407 ; CHECK-NEXT: [[NEXT_PRELOOP:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP]], 0
408 ; CHECK-NEXT: [[TMP0:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP]], 0
409 ; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP_PRELOOP]], label [[PRELOOP_EXIT_SELECTOR:%.*]], !llvm.loop [[LOOP10:![0-9]+]], !loop_constrainer.loop.clone [[META6]]
410 ; CHECK: preloop.exit.selector:
411 ; CHECK-NEXT: [[IDX_NEXT_PRELOOP_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT_PRELOOP]], [[IN_BOUNDS_PRELOOP]] ]
412 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP_LCSSA]], 0
413 ; CHECK-NEXT: br i1 [[TMP1]], label [[PRELOOP_PSEUDO_EXIT]], label [[EXIT]]
414 ; CHECK: preloop.pseudo.exit:
415 ; CHECK-NEXT: [[IDX_PRELOOP_COPY]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ [[IDX_NEXT_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ]
416 ; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ -1, [[ENTRY]] ], [ [[IDX_NEXT_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ]
417 ; CHECK-NEXT: br label [[MAINLOOP]]
421 %len = load i32, ptr %a_len_ptr, !range !0
425 %idx = phi i32 [ 4294967295, %entry ], [ %idx.next, %in.bounds ]
426 %idx.next = add nuw i32 %idx, -1
427 %abc = icmp ult i32 %idx, %len
428 br i1 %abc, label %in.bounds, label %out.of.bounds
431 %addr = getelementptr i32, ptr %arr, i32 %idx
432 store i32 0, ptr %addr
433 %next = icmp ugt i32 %idx.next, 0
434 br i1 %next, label %loop, label %exit
443 !0 = !{i32 0, i32 50}
445 ; CHECK: [[RNG0]] = !{i32 0, i32 50}
446 ; CHECK: [[LOOP1]] = distinct !{[[LOOP1]], [[META2:![0-9]+]], [[META3:![0-9]+]], [[META4:![0-9]+]], [[META5:![0-9]+]]}
447 ; CHECK: [[META2]] = !{!"llvm.loop.unroll.disable"}
448 ; CHECK: [[META3]] = !{!"llvm.loop.vectorize.enable", i1 false}
449 ; CHECK: [[META4]] = !{!"llvm.loop.licm_versioning.disable"}
450 ; CHECK: [[META5]] = !{!"llvm.loop.distribute.enable", i1 false}
451 ; CHECK: [[META6]] = !{}
452 ; CHECK: [[LOOP7]] = distinct !{[[LOOP7]], [[META2]], [[META3]], [[META4]], [[META5]]}
453 ; CHECK: [[LOOP8]] = distinct !{[[LOOP8]], [[META2]], [[META3]], [[META4]], [[META5]]}
454 ; CHECK: [[LOOP9]] = distinct !{[[LOOP9]], [[META2]], [[META3]], [[META4]], [[META5]]}
455 ; CHECK: [[LOOP10]] = distinct !{[[LOOP10]], [[META2]], [[META3]], [[META4]], [[META5]]}