Revert "[InstCombine] Support gep nuw in icmp folds" (#118698)
[llvm-project.git] / llvm / test / Transforms / IRCE / unsigned_comparisons_ugt.ll
blob7236cf4817adee369e0ecd3b1a03b9746db00a41
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:%.*]]) {
16 ; CHECK-NEXT:  entry:
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:%.*]]
22 ; CHECK:       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:%.*]]
27 ; CHECK:       in.bounds:
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]]
50 ; CHECK:       exit:
51 ; CHECK-NEXT:    ret void
52 ; CHECK:       postloop:
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]+]]
66 entry:
67   %len = load i32, ptr %a_len_ptr, !range !0
68   br label %loop
70 loop:
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
76 in.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
82 out.of.bounds:
83   ret void
85 exit:
86   ret void
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:%.*]]) {
93 ; CHECK-NEXT:  entry:
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:%.*]]
101 ; CHECK:       mainloop:
102 ; CHECK-NEXT:    br label [[LOOP:%.*]]
103 ; CHECK:       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:%.*]]
108 ; CHECK:       in.bounds:
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:%.*]]
121 ; CHECK:       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]]
144 entry:
145   %len = load i32, ptr %a_len_ptr, !range !0
146   br label %loop
148 loop:
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
154 in.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
160 out.of.bounds:
161   ret void
163 exit:
164   ret void
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:%.*]]) {
171 ; CHECK-NEXT:  entry:
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:%.*]]
177 ; CHECK:       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:%.*]]
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 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]]
205 ; CHECK:       exit:
206 ; CHECK-NEXT:    ret void
207 ; CHECK:       postloop:
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]]
221 entry:
222   %len = load i32, ptr %a_len_ptr, !range !0
223   br label %loop
225 loop:
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
231 in.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
237 out.of.bounds:
238   ret void
240 exit:
241   ret void
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:%.*]]) {
248 ; CHECK-NEXT:  entry:
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:%.*]]
256 ; CHECK:       mainloop:
257 ; CHECK-NEXT:    br label [[LOOP:%.*]]
258 ; CHECK:       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:%.*]]
263 ; CHECK:       in.bounds:
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:%.*]]
276 ; CHECK:       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]]
299 entry:
300   %len = load i32, ptr %a_len_ptr, !range !0
301   br label %loop
303 loop:
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
309 in.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
315 out.of.bounds:
316   ret void
318 exit:
319   ret void
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:%.*]]) {
326 ; CHECK-NEXT:  entry:
327 ; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0]]
328 ; CHECK-NEXT:    br label [[LOOP:%.*]]
329 ; CHECK:       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:%.*]]
334 ; CHECK:       in.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
341 ; CHECK:       exit:
342 ; CHECK-NEXT:    ret void
345 entry:
346   %len = load i32, ptr %a_len_ptr, !range !0
347   br label %loop
349 loop:
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
355 in.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
361 out.of.bounds:
362   ret void
364 exit:
365   ret void
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:%.*]]) {
372 ; CHECK-NEXT:  entry:
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:%.*]]
377 ; CHECK:       mainloop:
378 ; CHECK-NEXT:    br label [[LOOP:%.*]]
379 ; CHECK:       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:%.*]]
384 ; CHECK:       in.bounds:
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:%.*]]
397 ; CHECK:       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]]
420 entry:
421   %len = load i32, ptr %a_len_ptr, !range !0
422   br label %loop
424 loop:
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
430 in.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
436 out.of.bounds:
437   ret void
439 exit:
440   ret void
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]]}