1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
2 ; RUN: opt -verify-loop-info -passes=irce -irce-print-scaled-boundary-range-checks -S < %s 2>&1 | FileCheck %s
5 ; CHECK: irce: in function test1, in Loop at depth 1 containing: %loop<header><exiting>,%inbounds<latch><exiting>
6 ; CHECK-NEXT: there is range check with scaled boundary:
7 ; CHECK-NEXT: InductiveRangeCheck:
8 ; CHECK-NEXT: Begin: 0 Step: 1 End: (-1 + (sext i8 %n to i16))<nsw>
9 ; CHECK-NEXT: CheckUse: br i1 %check, label %inbounds, label %out_of_bounds Operand: 0
11 ; CHECK-NEXT: irce: in function test4, in Loop at depth 1 containing: %loop<header><exiting>,%inbounds<latch><exiting>
12 ; CHECK-NEXT: there is range check with scaled boundary:
13 ; CHECK-NEXT: InductiveRangeCheck:
14 ; CHECK-NEXT: Begin: 0 Step: 1 End: (-2 + (sext i8 %n to i16))<nsw>
15 ; CHECK-NEXT: CheckUse: br i1 %check, label %inbounds, label %out_of_bounds Operand: 0
17 ; CHECK-NEXT: irce: in function test_overflow_check_runtime, in Loop at depth 1 containing: %loop<header><exiting>,%inbounds<latch><exiting>
18 ; CHECK-NEXT: there is range check with scaled boundary:
19 ; CHECK-NEXT: InductiveRangeCheck:
20 ; CHECK-NEXT: Begin: 0 Step: 1 End: (3 + (zext i8 %n to i16))<nuw><nsw>
21 ; CHECK-NEXT: CheckUse: br i1 %check, label %inbounds, label %out_of_bounds Operand: 0
23 ; IV = 0; IV <s limit; IV += 1;
26 define i8 @test1(i8 %limit, i8 %n) {
27 ; CHECK-LABEL: define i8 @test1
28 ; CHECK-SAME: (i8 [[LIMIT:%.*]], i8 [[N:%.*]]) {
30 ; CHECK-NEXT: [[PRECHECK:%.*]] = icmp sgt i8 [[LIMIT]], 0
31 ; CHECK-NEXT: br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
32 ; CHECK: loop.preheader:
33 ; CHECK-NEXT: [[TMP0:%.*]] = add i8 [[N]], -1
34 ; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[N]], -128
35 ; CHECK-NEXT: [[SMAX:%.*]] = call i8 @llvm.smax.i8(i8 [[TMP1]], i8 0)
36 ; CHECK-NEXT: [[TMP2:%.*]] = sub i8 [[TMP0]], [[SMAX]]
37 ; CHECK-NEXT: [[SMIN:%.*]] = call i8 @llvm.smin.i8(i8 [[TMP0]], i8 0)
38 ; CHECK-NEXT: [[SMAX2:%.*]] = call i8 @llvm.smax.i8(i8 [[SMIN]], i8 -1)
39 ; CHECK-NEXT: [[TMP3:%.*]] = add nsw i8 [[SMAX2]], 1
40 ; CHECK-NEXT: [[TMP4:%.*]] = mul i8 [[TMP2]], [[TMP3]]
41 ; CHECK-NEXT: [[TMP5:%.*]] = sext i8 [[N]] to i16
42 ; CHECK-NEXT: [[TMP6:%.*]] = add nsw i16 [[TMP5]], 127
43 ; CHECK-NEXT: [[SMIN3:%.*]] = call i16 @llvm.smin.i16(i16 [[TMP6]], i16 0)
44 ; CHECK-NEXT: [[TMP7:%.*]] = trunc i16 [[SMIN3]] to i8
45 ; CHECK-NEXT: [[TMP8:%.*]] = add nsw i8 [[TMP7]], 1
46 ; CHECK-NEXT: [[TMP9:%.*]] = mul i8 [[TMP4]], [[TMP8]]
47 ; CHECK-NEXT: [[SMIN4:%.*]] = call i8 @llvm.smin.i8(i8 [[LIMIT]], i8 [[TMP9]])
48 ; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = call i8 @llvm.smax.i8(i8 [[SMIN4]], i8 0)
49 ; CHECK-NEXT: [[TMP10:%.*]] = icmp slt i8 0, [[EXIT_MAINLOOP_AT]]
50 ; CHECK-NEXT: br i1 [[TMP10]], label [[LOOP_PREHEADER7:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
51 ; CHECK: loop.preheader7:
52 ; CHECK-NEXT: br label [[LOOP:%.*]]
54 ; CHECK-NEXT: [[IDX:%.*]] = phi i8 [ [[IDX_NEXT:%.*]], [[INBOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER7]] ]
55 ; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[N]], [[IDX]]
56 ; CHECK-NEXT: [[CHECK:%.*]] = icmp sge i8 [[SUB]], 2
57 ; CHECK-NEXT: br i1 true, label [[INBOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT8:%.*]]
59 ; CHECK-NEXT: [[IDX_NEXT]] = add nuw nsw i8 [[IDX]], 1
60 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[IDX_NEXT]], [[LIMIT]]
61 ; CHECK-NEXT: [[TMP11:%.*]] = icmp slt i8 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]
62 ; CHECK-NEXT: br i1 [[TMP11]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
63 ; CHECK: main.exit.selector:
64 ; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i8 [ [[IDX_NEXT]], [[INBOUNDS]] ]
65 ; CHECK-NEXT: [[IDX_LCSSA6:%.*]] = phi i8 [ [[IDX]], [[INBOUNDS]] ]
66 ; CHECK-NEXT: [[TMP12:%.*]] = icmp slt i8 [[IDX_NEXT_LCSSA]], [[LIMIT]]
67 ; CHECK-NEXT: br i1 [[TMP12]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT_LOOPEXIT:%.*]]
68 ; CHECK: main.pseudo.exit:
69 ; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i8 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
70 ; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i8 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
71 ; CHECK-NEXT: br label [[POSTLOOP:%.*]]
72 ; CHECK: exit.loopexit.loopexit:
73 ; CHECK-NEXT: [[IDX_LCSSA1_PH:%.*]] = phi i8 [ [[IDX_POSTLOOP:%.*]], [[INBOUNDS_POSTLOOP:%.*]] ]
74 ; CHECK-NEXT: br label [[EXIT_LOOPEXIT]]
75 ; CHECK: exit.loopexit:
76 ; CHECK-NEXT: [[IDX_LCSSA1:%.*]] = phi i8 [ [[IDX_LCSSA6]], [[MAIN_EXIT_SELECTOR]] ], [ [[IDX_LCSSA1_PH]], [[EXIT_LOOPEXIT_LOOPEXIT:%.*]] ]
77 ; CHECK-NEXT: br label [[EXIT]]
79 ; CHECK-NEXT: [[RES:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IDX_LCSSA1]], [[EXIT_LOOPEXIT]] ]
80 ; CHECK-NEXT: ret i8 [[RES]]
81 ; CHECK: out_of_bounds.loopexit:
82 ; CHECK-NEXT: [[IDX_LCSSA_PH:%.*]] = phi i8 [ [[IDX_POSTLOOP]], [[LOOP_POSTLOOP:%.*]] ]
83 ; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]
84 ; CHECK: out_of_bounds.loopexit8:
85 ; CHECK-NEXT: [[IDX_LCSSA_PH9:%.*]] = phi i8 [ [[IDX]], [[LOOP]] ]
86 ; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]
87 ; CHECK: out_of_bounds:
88 ; CHECK-NEXT: [[IDX_LCSSA:%.*]] = phi i8 [ [[IDX_LCSSA_PH]], [[OUT_OF_BOUNDS_LOOPEXIT:%.*]] ], [ [[IDX_LCSSA_PH9]], [[OUT_OF_BOUNDS_LOOPEXIT8]] ]
89 ; CHECK-NEXT: ret i8 [[IDX_LCSSA]]
91 ; CHECK-NEXT: br label [[LOOP_POSTLOOP]]
92 ; CHECK: loop.postloop:
93 ; CHECK-NEXT: [[IDX_POSTLOOP]] = phi i8 [ [[IDX_NEXT_POSTLOOP:%.*]], [[INBOUNDS_POSTLOOP]] ], [ [[IDX_COPY]], [[POSTLOOP]] ]
94 ; CHECK-NEXT: [[SUB_POSTLOOP:%.*]] = sub i8 [[N]], [[IDX_POSTLOOP]]
95 ; CHECK-NEXT: [[CHECK_POSTLOOP:%.*]] = icmp sge i8 [[SUB_POSTLOOP]], 2
96 ; CHECK-NEXT: br i1 [[CHECK_POSTLOOP]], label [[INBOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT]]
97 ; CHECK: inbounds.postloop:
98 ; CHECK-NEXT: [[IDX_NEXT_POSTLOOP]] = add nuw i8 [[IDX_POSTLOOP]], 1
99 ; CHECK-NEXT: [[CMP_POSTLOOP:%.*]] = icmp slt i8 [[IDX_NEXT_POSTLOOP]], [[LIMIT]]
100 ; CHECK-NEXT: br i1 [[CMP_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT]], !llvm.loop [[LOOP0:![0-9]+]], !loop_constrainer.loop.clone !5
103 %precheck = icmp sgt i8 %limit, 0
104 br i1 %precheck, label %loop, label %exit
107 %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ]
108 %sub = sub i8 %n, %idx
109 %check = icmp sge i8 %sub, 2
110 br i1 %check, label %inbounds, label %out_of_bounds
113 %idx.next = add nuw i8 %idx, 1
114 %cmp = icmp slt i8 %idx.next, %limit
115 br i1 %cmp, label %loop, label %exit
118 %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
125 ; IV = 0; IV <s limit; IV += 1;
127 ; N is known to be non-negative.
128 ; TODO: IRCE is allowed.
129 define i8 @test1a(i8 %limit, ptr %p) {
130 ; CHECK-LABEL: define i8 @test1a
131 ; CHECK-SAME: (i8 [[LIMIT:%.*]], ptr [[P:%.*]]) {
133 ; CHECK-NEXT: [[N:%.*]] = load i8, ptr [[P]], align 1, !range [[RNG6:![0-9]+]]
134 ; CHECK-NEXT: [[PRECHECK:%.*]] = icmp sgt i8 [[LIMIT]], 0
135 ; CHECK-NEXT: br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
136 ; CHECK: loop.preheader:
137 ; CHECK-NEXT: [[TMP0:%.*]] = add nsw i8 [[N]], -1
138 ; CHECK-NEXT: [[SMIN:%.*]] = call i8 @llvm.smin.i8(i8 [[TMP0]], i8 0)
139 ; CHECK-NEXT: [[TMP1:%.*]] = add nsw i8 [[SMIN]], 1
140 ; CHECK-NEXT: [[TMP2:%.*]] = mul i8 [[TMP0]], [[TMP1]]
141 ; CHECK-NEXT: [[SMIN2:%.*]] = call i8 @llvm.smin.i8(i8 [[LIMIT]], i8 [[TMP2]])
142 ; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = call i8 @llvm.smax.i8(i8 [[SMIN2]], i8 0)
143 ; CHECK-NEXT: [[TMP3:%.*]] = icmp slt i8 0, [[EXIT_MAINLOOP_AT]]
144 ; CHECK-NEXT: br i1 [[TMP3]], label [[LOOP_PREHEADER4:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
145 ; CHECK: loop.preheader4:
146 ; CHECK-NEXT: br label [[LOOP:%.*]]
148 ; CHECK-NEXT: [[IDX:%.*]] = phi i8 [ [[IDX_NEXT:%.*]], [[INBOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER4]] ]
149 ; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[N]], [[IDX]]
150 ; CHECK-NEXT: [[CHECK:%.*]] = icmp sge i8 [[SUB]], 2
151 ; CHECK-NEXT: br i1 true, label [[INBOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT5:%.*]]
153 ; CHECK-NEXT: [[IDX_NEXT]] = add nuw nsw i8 [[IDX]], 1
154 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[IDX_NEXT]], [[LIMIT]]
155 ; CHECK-NEXT: [[TMP4:%.*]] = icmp slt i8 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]
156 ; CHECK-NEXT: br i1 [[TMP4]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
157 ; CHECK: main.exit.selector:
158 ; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i8 [ [[IDX_NEXT]], [[INBOUNDS]] ]
159 ; CHECK-NEXT: [[IDX_LCSSA3:%.*]] = phi i8 [ [[IDX]], [[INBOUNDS]] ]
160 ; CHECK-NEXT: [[TMP5:%.*]] = icmp slt i8 [[IDX_NEXT_LCSSA]], [[LIMIT]]
161 ; CHECK-NEXT: br i1 [[TMP5]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT_LOOPEXIT:%.*]]
162 ; CHECK: main.pseudo.exit:
163 ; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i8 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
164 ; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i8 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
165 ; CHECK-NEXT: br label [[POSTLOOP:%.*]]
166 ; CHECK: exit.loopexit.loopexit:
167 ; CHECK-NEXT: [[IDX_LCSSA1_PH:%.*]] = phi i8 [ [[IDX_POSTLOOP:%.*]], [[INBOUNDS_POSTLOOP:%.*]] ]
168 ; CHECK-NEXT: br label [[EXIT_LOOPEXIT]]
169 ; CHECK: exit.loopexit:
170 ; CHECK-NEXT: [[IDX_LCSSA1:%.*]] = phi i8 [ [[IDX_LCSSA3]], [[MAIN_EXIT_SELECTOR]] ], [ [[IDX_LCSSA1_PH]], [[EXIT_LOOPEXIT_LOOPEXIT:%.*]] ]
171 ; CHECK-NEXT: br label [[EXIT]]
173 ; CHECK-NEXT: [[RES:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IDX_LCSSA1]], [[EXIT_LOOPEXIT]] ]
174 ; CHECK-NEXT: ret i8 [[RES]]
175 ; CHECK: out_of_bounds.loopexit:
176 ; CHECK-NEXT: [[IDX_LCSSA_PH:%.*]] = phi i8 [ [[IDX_POSTLOOP]], [[LOOP_POSTLOOP:%.*]] ]
177 ; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]
178 ; CHECK: out_of_bounds.loopexit5:
179 ; CHECK-NEXT: [[IDX_LCSSA_PH6:%.*]] = phi i8 [ [[IDX]], [[LOOP]] ]
180 ; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]
181 ; CHECK: out_of_bounds:
182 ; CHECK-NEXT: [[IDX_LCSSA:%.*]] = phi i8 [ [[IDX_LCSSA_PH]], [[OUT_OF_BOUNDS_LOOPEXIT:%.*]] ], [ [[IDX_LCSSA_PH6]], [[OUT_OF_BOUNDS_LOOPEXIT5]] ]
183 ; CHECK-NEXT: ret i8 [[IDX_LCSSA]]
185 ; CHECK-NEXT: br label [[LOOP_POSTLOOP]]
186 ; CHECK: loop.postloop:
187 ; CHECK-NEXT: [[IDX_POSTLOOP]] = phi i8 [ [[IDX_NEXT_POSTLOOP:%.*]], [[INBOUNDS_POSTLOOP]] ], [ [[IDX_COPY]], [[POSTLOOP]] ]
188 ; CHECK-NEXT: [[SUB_POSTLOOP:%.*]] = sub i8 [[N]], [[IDX_POSTLOOP]]
189 ; CHECK-NEXT: [[CHECK_POSTLOOP:%.*]] = icmp sge i8 [[SUB_POSTLOOP]], 2
190 ; CHECK-NEXT: br i1 [[CHECK_POSTLOOP]], label [[INBOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT]]
191 ; CHECK: inbounds.postloop:
192 ; CHECK-NEXT: [[IDX_NEXT_POSTLOOP]] = add nuw i8 [[IDX_POSTLOOP]], 1
193 ; CHECK-NEXT: [[CMP_POSTLOOP:%.*]] = icmp slt i8 [[IDX_NEXT_POSTLOOP]], [[LIMIT]]
194 ; CHECK-NEXT: br i1 [[CMP_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT]], !llvm.loop [[LOOP7:![0-9]+]], !loop_constrainer.loop.clone !5
197 %n = load i8, ptr %p, !range !0
198 %precheck = icmp sgt i8 %limit, 0
199 br i1 %precheck, label %loop, label %exit
202 %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ]
203 %sub = sub i8 %n, %idx
204 %check = icmp sge i8 %sub, 2
205 br i1 %check, label %inbounds, label %out_of_bounds
208 %idx.next = add nuw i8 %idx, 1
209 %cmp = icmp slt i8 %idx.next, %limit
210 br i1 %cmp, label %loop, label %exit
213 %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
220 ; IV = 0; IV <s limit; IV += 1;
221 ; Check(IV - N <= -2)
222 ; TODO: IRCE is allowed.
223 define i8 @test2(i8 %limit, i8 %n) {
224 ; CHECK-LABEL: define i8 @test2
225 ; CHECK-SAME: (i8 [[LIMIT:%.*]], i8 [[N:%.*]]) {
227 ; CHECK-NEXT: [[PRECHECK:%.*]] = icmp sgt i8 [[LIMIT]], 0
228 ; CHECK-NEXT: br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
229 ; CHECK: loop.preheader:
230 ; CHECK-NEXT: br label [[LOOP:%.*]]
232 ; CHECK-NEXT: [[IDX:%.*]] = phi i8 [ [[IDX_NEXT:%.*]], [[INBOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
233 ; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[IDX]], [[N]]
234 ; CHECK-NEXT: [[CHECK:%.*]] = icmp sle i8 [[SUB]], -2
235 ; CHECK-NEXT: br i1 [[CHECK]], label [[INBOUNDS]], label [[OUT_OF_BOUNDS:%.*]]
237 ; CHECK-NEXT: [[IDX_NEXT]] = add nuw i8 [[IDX]], 1
238 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[IDX_NEXT]], [[LIMIT]]
239 ; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
240 ; CHECK: exit.loopexit:
241 ; CHECK-NEXT: [[IDX_LCSSA1:%.*]] = phi i8 [ [[IDX]], [[INBOUNDS]] ]
242 ; CHECK-NEXT: br label [[EXIT]]
244 ; CHECK-NEXT: [[RES:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IDX_LCSSA1]], [[EXIT_LOOPEXIT]] ]
245 ; CHECK-NEXT: ret i8 [[RES]]
246 ; CHECK: out_of_bounds:
247 ; CHECK-NEXT: [[IDX_LCSSA:%.*]] = phi i8 [ [[IDX]], [[LOOP]] ]
248 ; CHECK-NEXT: ret i8 [[IDX_LCSSA]]
251 %precheck = icmp sgt i8 %limit, 0
252 br i1 %precheck, label %loop, label %exit
255 %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ]
256 %sub = sub i8 %idx, %n
257 %check = icmp sle i8 %sub, -2
258 br i1 %check, label %inbounds, label %out_of_bounds
261 %idx.next = add nuw i8 %idx, 1
262 %cmp = icmp slt i8 %idx.next, %limit
263 br i1 %cmp, label %loop, label %exit
266 %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
273 ; IV = 0; IV <s limit; IV += 1;
274 ; Check(IV - N <= -2)
275 ; N is known to be non-negative.
276 ; TODO: IRCE is allowed.
277 define i8 @test2a(i8 %limit, ptr %p) {
278 ; CHECK-LABEL: define i8 @test2a
279 ; CHECK-SAME: (i8 [[LIMIT:%.*]], ptr [[P:%.*]]) {
281 ; CHECK-NEXT: [[N:%.*]] = load i8, ptr [[P]], align 1, !range [[RNG6]]
282 ; CHECK-NEXT: [[PRECHECK:%.*]] = icmp sgt i8 [[LIMIT]], 0
283 ; CHECK-NEXT: br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
284 ; CHECK: loop.preheader:
285 ; CHECK-NEXT: br label [[LOOP:%.*]]
287 ; CHECK-NEXT: [[IDX:%.*]] = phi i8 [ [[IDX_NEXT:%.*]], [[INBOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
288 ; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[IDX]], [[N]]
289 ; CHECK-NEXT: [[CHECK:%.*]] = icmp sle i8 [[SUB]], -2
290 ; CHECK-NEXT: br i1 [[CHECK]], label [[INBOUNDS]], label [[OUT_OF_BOUNDS:%.*]]
292 ; CHECK-NEXT: [[IDX_NEXT]] = add nuw i8 [[IDX]], 1
293 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[IDX_NEXT]], [[LIMIT]]
294 ; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
295 ; CHECK: exit.loopexit:
296 ; CHECK-NEXT: [[IDX_LCSSA1:%.*]] = phi i8 [ [[IDX]], [[INBOUNDS]] ]
297 ; CHECK-NEXT: br label [[EXIT]]
299 ; CHECK-NEXT: [[RES:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IDX_LCSSA1]], [[EXIT_LOOPEXIT]] ]
300 ; CHECK-NEXT: ret i8 [[RES]]
301 ; CHECK: out_of_bounds:
302 ; CHECK-NEXT: [[IDX_LCSSA:%.*]] = phi i8 [ [[IDX]], [[LOOP]] ]
303 ; CHECK-NEXT: ret i8 [[IDX_LCSSA]]
306 %n = load i8, ptr %p, !range !0
307 %precheck = icmp sgt i8 %limit, 0
308 br i1 %precheck, label %loop, label %exit
311 %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ]
312 %sub = sub i8 %idx, %n
313 %check = icmp sle i8 %sub, -2
314 br i1 %check, label %inbounds, label %out_of_bounds
317 %idx.next = add nuw i8 %idx, 1
318 %cmp = icmp slt i8 %idx.next, %limit
319 br i1 %cmp, label %loop, label %exit
322 %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
329 ; IV = 0; IV <s limit; IV += 1;
331 ; TODO: IRCE is allowed.
332 define i8 @test3(i8 %limit, i8 %n) {
333 ; CHECK-LABEL: define i8 @test3
334 ; CHECK-SAME: (i8 [[LIMIT:%.*]], i8 [[N:%.*]]) {
336 ; CHECK-NEXT: [[PRECHECK:%.*]] = icmp sgt i8 [[LIMIT]], 0
337 ; CHECK-NEXT: br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
338 ; CHECK: loop.preheader:
339 ; CHECK-NEXT: br label [[LOOP:%.*]]
341 ; CHECK-NEXT: [[IDX:%.*]] = phi i8 [ [[IDX_NEXT:%.*]], [[INBOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
342 ; CHECK-NEXT: [[ADD:%.*]] = add i8 [[IDX]], 2
343 ; CHECK-NEXT: [[CHECK:%.*]] = icmp sle i8 [[ADD]], [[N]]
344 ; CHECK-NEXT: br i1 [[CHECK]], label [[INBOUNDS]], label [[OUT_OF_BOUNDS:%.*]]
346 ; CHECK-NEXT: [[IDX_NEXT]] = add nuw i8 [[IDX]], 1
347 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[IDX_NEXT]], [[LIMIT]]
348 ; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
349 ; CHECK: exit.loopexit:
350 ; CHECK-NEXT: [[IDX_LCSSA1:%.*]] = phi i8 [ [[IDX]], [[INBOUNDS]] ]
351 ; CHECK-NEXT: br label [[EXIT]]
353 ; CHECK-NEXT: [[RES:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IDX_LCSSA1]], [[EXIT_LOOPEXIT]] ]
354 ; CHECK-NEXT: ret i8 [[RES]]
355 ; CHECK: out_of_bounds:
356 ; CHECK-NEXT: [[IDX_LCSSA:%.*]] = phi i8 [ [[IDX]], [[LOOP]] ]
357 ; CHECK-NEXT: ret i8 [[IDX_LCSSA]]
360 %precheck = icmp sgt i8 %limit, 0
361 br i1 %precheck, label %loop, label %exit
364 %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ]
365 %add = add i8 %idx, 2
366 %check = icmp sle i8 %add, %n
367 br i1 %check, label %inbounds, label %out_of_bounds
370 %idx.next = add nuw i8 %idx, 1
371 %cmp = icmp slt i8 %idx.next, %limit
372 br i1 %cmp, label %loop, label %exit
375 %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
382 ; IV = 0; IV <s limit; IV += 1;
384 ; N is known to be non-negative.
386 define i8 @test3a(i8 %limit, ptr %p) {
387 ; CHECK-LABEL: define i8 @test3a
388 ; CHECK-SAME: (i8 [[LIMIT:%.*]], ptr [[P:%.*]]) {
390 ; CHECK-NEXT: [[N:%.*]] = load i8, ptr [[P]], align 1, !range [[RNG6]]
391 ; CHECK-NEXT: [[PRECHECK:%.*]] = icmp sgt i8 [[LIMIT]], 0
392 ; CHECK-NEXT: br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
393 ; CHECK: loop.preheader:
394 ; CHECK-NEXT: [[TMP0:%.*]] = add nsw i8 [[N]], -1
395 ; CHECK-NEXT: [[SMIN:%.*]] = call i8 @llvm.smin.i8(i8 [[LIMIT]], i8 [[TMP0]])
396 ; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = call i8 @llvm.smax.i8(i8 [[SMIN]], i8 0)
397 ; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i8 0, [[EXIT_MAINLOOP_AT]]
398 ; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP_PREHEADER3:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
399 ; CHECK: loop.preheader3:
400 ; CHECK-NEXT: br label [[LOOP:%.*]]
402 ; CHECK-NEXT: [[IDX:%.*]] = phi i8 [ [[IDX_NEXT:%.*]], [[INBOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER3]] ]
403 ; CHECK-NEXT: [[ADD:%.*]] = add i8 [[IDX]], 2
404 ; CHECK-NEXT: [[CHECK:%.*]] = icmp sle i8 [[ADD]], [[N]]
405 ; CHECK-NEXT: br i1 true, label [[INBOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT4:%.*]]
407 ; CHECK-NEXT: [[IDX_NEXT]] = add nuw nsw i8 [[IDX]], 1
408 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[IDX_NEXT]], [[LIMIT]]
409 ; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i8 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]
410 ; CHECK-NEXT: br i1 [[TMP2]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
411 ; CHECK: main.exit.selector:
412 ; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i8 [ [[IDX_NEXT]], [[INBOUNDS]] ]
413 ; CHECK-NEXT: [[IDX_LCSSA2:%.*]] = phi i8 [ [[IDX]], [[INBOUNDS]] ]
414 ; CHECK-NEXT: [[TMP3:%.*]] = icmp slt i8 [[IDX_NEXT_LCSSA]], [[LIMIT]]
415 ; CHECK-NEXT: br i1 [[TMP3]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT_LOOPEXIT:%.*]]
416 ; CHECK: main.pseudo.exit:
417 ; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i8 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
418 ; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i8 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
419 ; CHECK-NEXT: br label [[POSTLOOP:%.*]]
420 ; CHECK: exit.loopexit.loopexit:
421 ; CHECK-NEXT: [[IDX_LCSSA1_PH:%.*]] = phi i8 [ [[IDX_POSTLOOP:%.*]], [[INBOUNDS_POSTLOOP:%.*]] ]
422 ; CHECK-NEXT: br label [[EXIT_LOOPEXIT]]
423 ; CHECK: exit.loopexit:
424 ; CHECK-NEXT: [[IDX_LCSSA1:%.*]] = phi i8 [ [[IDX_LCSSA2]], [[MAIN_EXIT_SELECTOR]] ], [ [[IDX_LCSSA1_PH]], [[EXIT_LOOPEXIT_LOOPEXIT:%.*]] ]
425 ; CHECK-NEXT: br label [[EXIT]]
427 ; CHECK-NEXT: [[RES:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IDX_LCSSA1]], [[EXIT_LOOPEXIT]] ]
428 ; CHECK-NEXT: ret i8 [[RES]]
429 ; CHECK: out_of_bounds.loopexit:
430 ; CHECK-NEXT: [[IDX_LCSSA_PH:%.*]] = phi i8 [ [[IDX_POSTLOOP]], [[LOOP_POSTLOOP:%.*]] ]
431 ; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]
432 ; CHECK: out_of_bounds.loopexit4:
433 ; CHECK-NEXT: [[IDX_LCSSA_PH5:%.*]] = phi i8 [ [[IDX]], [[LOOP]] ]
434 ; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]
435 ; CHECK: out_of_bounds:
436 ; CHECK-NEXT: [[IDX_LCSSA:%.*]] = phi i8 [ [[IDX_LCSSA_PH]], [[OUT_OF_BOUNDS_LOOPEXIT:%.*]] ], [ [[IDX_LCSSA_PH5]], [[OUT_OF_BOUNDS_LOOPEXIT4]] ]
437 ; CHECK-NEXT: ret i8 [[IDX_LCSSA]]
439 ; CHECK-NEXT: br label [[LOOP_POSTLOOP]]
440 ; CHECK: loop.postloop:
441 ; CHECK-NEXT: [[IDX_POSTLOOP]] = phi i8 [ [[IDX_NEXT_POSTLOOP:%.*]], [[INBOUNDS_POSTLOOP]] ], [ [[IDX_COPY]], [[POSTLOOP]] ]
442 ; CHECK-NEXT: [[ADD_POSTLOOP:%.*]] = add i8 [[IDX_POSTLOOP]], 2
443 ; CHECK-NEXT: [[CHECK_POSTLOOP:%.*]] = icmp sle i8 [[ADD_POSTLOOP]], [[N]]
444 ; CHECK-NEXT: br i1 [[CHECK_POSTLOOP]], label [[INBOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT]]
445 ; CHECK: inbounds.postloop:
446 ; CHECK-NEXT: [[IDX_NEXT_POSTLOOP]] = add nuw i8 [[IDX_POSTLOOP]], 1
447 ; CHECK-NEXT: [[CMP_POSTLOOP:%.*]] = icmp slt i8 [[IDX_NEXT_POSTLOOP]], [[LIMIT]]
448 ; CHECK-NEXT: br i1 [[CMP_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT]], !llvm.loop [[LOOP8:![0-9]+]], !loop_constrainer.loop.clone !5
451 %n = load i8, ptr %p, !range !0
452 %precheck = icmp sgt i8 %limit, 0
453 br i1 %precheck, label %loop, label %exit
456 %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ]
457 %add = add i8 %idx, 2
458 %check = icmp sle i8 %add, %n
459 br i1 %check, label %inbounds, label %out_of_bounds
462 %idx.next = add nuw i8 %idx, 1
463 %cmp = icmp slt i8 %idx.next, %limit
464 br i1 %cmp, label %loop, label %exit
467 %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
474 ; IV = 0; IV <s limit; IV += 1;
477 define i8 @test4(i8 %limit, i8 %n) {
478 ; CHECK-LABEL: define i8 @test4
479 ; CHECK-SAME: (i8 [[LIMIT:%.*]], i8 [[N:%.*]]) {
481 ; CHECK-NEXT: [[PRECHECK:%.*]] = icmp sgt i8 [[LIMIT]], 0
482 ; CHECK-NEXT: br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
483 ; CHECK: loop.preheader:
484 ; CHECK-NEXT: [[TMP0:%.*]] = add i8 [[N]], -2
485 ; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[N]], 127
486 ; CHECK-NEXT: [[SMAX:%.*]] = call i8 @llvm.smax.i8(i8 [[TMP1]], i8 0)
487 ; CHECK-NEXT: [[TMP2:%.*]] = sub i8 [[TMP0]], [[SMAX]]
488 ; CHECK-NEXT: [[SMIN:%.*]] = call i8 @llvm.smin.i8(i8 [[TMP0]], i8 0)
489 ; CHECK-NEXT: [[SMAX2:%.*]] = call i8 @llvm.smax.i8(i8 [[SMIN]], i8 -1)
490 ; CHECK-NEXT: [[TMP3:%.*]] = add nsw i8 [[SMAX2]], 1
491 ; CHECK-NEXT: [[TMP4:%.*]] = mul i8 [[TMP2]], [[TMP3]]
492 ; CHECK-NEXT: [[TMP5:%.*]] = sext i8 [[N]] to i16
493 ; CHECK-NEXT: [[TMP6:%.*]] = add nsw i16 [[TMP5]], 126
494 ; CHECK-NEXT: [[SMIN3:%.*]] = call i16 @llvm.smin.i16(i16 [[TMP6]], i16 0)
495 ; CHECK-NEXT: [[SMAX4:%.*]] = call i16 @llvm.smax.i16(i16 [[SMIN3]], i16 -1)
496 ; CHECK-NEXT: [[TMP7:%.*]] = trunc i16 [[SMAX4]] to i8
497 ; CHECK-NEXT: [[TMP8:%.*]] = add nsw i8 [[TMP7]], 1
498 ; CHECK-NEXT: [[TMP9:%.*]] = mul i8 [[TMP4]], [[TMP8]]
499 ; CHECK-NEXT: [[SMIN5:%.*]] = call i8 @llvm.smin.i8(i8 [[LIMIT]], i8 [[TMP9]])
500 ; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = call i8 @llvm.smax.i8(i8 [[SMIN5]], i8 0)
501 ; CHECK-NEXT: [[TMP10:%.*]] = icmp slt i8 0, [[EXIT_MAINLOOP_AT]]
502 ; CHECK-NEXT: br i1 [[TMP10]], label [[LOOP_PREHEADER8:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
503 ; CHECK: loop.preheader8:
504 ; CHECK-NEXT: br label [[LOOP:%.*]]
506 ; CHECK-NEXT: [[IDX:%.*]] = phi i8 [ [[IDX_NEXT:%.*]], [[INBOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER8]] ]
507 ; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[N]], [[IDX]]
508 ; CHECK-NEXT: [[CHECK:%.*]] = icmp sgt i8 [[SUB]], 2
509 ; CHECK-NEXT: br i1 true, label [[INBOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT9:%.*]]
511 ; CHECK-NEXT: [[IDX_NEXT]] = add nuw nsw i8 [[IDX]], 1
512 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[IDX_NEXT]], [[LIMIT]]
513 ; CHECK-NEXT: [[TMP11:%.*]] = icmp slt i8 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]
514 ; CHECK-NEXT: br i1 [[TMP11]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
515 ; CHECK: main.exit.selector:
516 ; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i8 [ [[IDX_NEXT]], [[INBOUNDS]] ]
517 ; CHECK-NEXT: [[IDX_LCSSA7:%.*]] = phi i8 [ [[IDX]], [[INBOUNDS]] ]
518 ; CHECK-NEXT: [[TMP12:%.*]] = icmp slt i8 [[IDX_NEXT_LCSSA]], [[LIMIT]]
519 ; CHECK-NEXT: br i1 [[TMP12]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT_LOOPEXIT:%.*]]
520 ; CHECK: main.pseudo.exit:
521 ; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i8 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
522 ; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i8 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
523 ; CHECK-NEXT: br label [[POSTLOOP:%.*]]
524 ; CHECK: exit.loopexit.loopexit:
525 ; CHECK-NEXT: [[IDX_LCSSA1_PH:%.*]] = phi i8 [ [[IDX_POSTLOOP:%.*]], [[INBOUNDS_POSTLOOP:%.*]] ]
526 ; CHECK-NEXT: br label [[EXIT_LOOPEXIT]]
527 ; CHECK: exit.loopexit:
528 ; CHECK-NEXT: [[IDX_LCSSA1:%.*]] = phi i8 [ [[IDX_LCSSA7]], [[MAIN_EXIT_SELECTOR]] ], [ [[IDX_LCSSA1_PH]], [[EXIT_LOOPEXIT_LOOPEXIT:%.*]] ]
529 ; CHECK-NEXT: br label [[EXIT]]
531 ; CHECK-NEXT: [[RES:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IDX_LCSSA1]], [[EXIT_LOOPEXIT]] ]
532 ; CHECK-NEXT: ret i8 [[RES]]
533 ; CHECK: out_of_bounds.loopexit:
534 ; CHECK-NEXT: [[IDX_LCSSA_PH:%.*]] = phi i8 [ [[IDX_POSTLOOP]], [[LOOP_POSTLOOP:%.*]] ]
535 ; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]
536 ; CHECK: out_of_bounds.loopexit9:
537 ; CHECK-NEXT: [[IDX_LCSSA_PH10:%.*]] = phi i8 [ [[IDX]], [[LOOP]] ]
538 ; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]
539 ; CHECK: out_of_bounds:
540 ; CHECK-NEXT: [[IDX_LCSSA:%.*]] = phi i8 [ [[IDX_LCSSA_PH]], [[OUT_OF_BOUNDS_LOOPEXIT:%.*]] ], [ [[IDX_LCSSA_PH10]], [[OUT_OF_BOUNDS_LOOPEXIT9]] ]
541 ; CHECK-NEXT: ret i8 [[IDX_LCSSA]]
543 ; CHECK-NEXT: br label [[LOOP_POSTLOOP]]
544 ; CHECK: loop.postloop:
545 ; CHECK-NEXT: [[IDX_POSTLOOP]] = phi i8 [ [[IDX_NEXT_POSTLOOP:%.*]], [[INBOUNDS_POSTLOOP]] ], [ [[IDX_COPY]], [[POSTLOOP]] ]
546 ; CHECK-NEXT: [[SUB_POSTLOOP:%.*]] = sub i8 [[N]], [[IDX_POSTLOOP]]
547 ; CHECK-NEXT: [[CHECK_POSTLOOP:%.*]] = icmp sgt i8 [[SUB_POSTLOOP]], 2
548 ; CHECK-NEXT: br i1 [[CHECK_POSTLOOP]], label [[INBOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT]]
549 ; CHECK: inbounds.postloop:
550 ; CHECK-NEXT: [[IDX_NEXT_POSTLOOP]] = add nuw i8 [[IDX_POSTLOOP]], 1
551 ; CHECK-NEXT: [[CMP_POSTLOOP:%.*]] = icmp slt i8 [[IDX_NEXT_POSTLOOP]], [[LIMIT]]
552 ; CHECK-NEXT: br i1 [[CMP_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT]], !llvm.loop [[LOOP9:![0-9]+]], !loop_constrainer.loop.clone !5
555 %precheck = icmp sgt i8 %limit, 0
556 br i1 %precheck, label %loop, label %exit
559 %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ]
560 %sub = sub i8 %n, %idx
561 %check = icmp sgt i8 %sub, 2
562 br i1 %check, label %inbounds, label %out_of_bounds
565 %idx.next = add nuw i8 %idx, 1
566 %cmp = icmp slt i8 %idx.next, %limit
567 br i1 %cmp, label %loop, label %exit
570 %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
577 ; IV = 0; IV <s limit; IV += 1;
579 ; N is known to be non-negative.
580 ; TODO: IRCE is allowed.
581 define i8 @test4a(i8 %limit, ptr %p) {
582 ; CHECK-LABEL: define i8 @test4a
583 ; CHECK-SAME: (i8 [[LIMIT:%.*]], ptr [[P:%.*]]) {
585 ; CHECK-NEXT: [[N:%.*]] = load i8, ptr [[P]], align 1, !range [[RNG6]]
586 ; CHECK-NEXT: [[PRECHECK:%.*]] = icmp sgt i8 [[LIMIT]], 0
587 ; CHECK-NEXT: br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
588 ; CHECK: loop.preheader:
589 ; CHECK-NEXT: [[TMP0:%.*]] = add i8 [[N]], -2
590 ; CHECK-NEXT: [[TMP1:%.*]] = add nuw i8 [[N]], 127
591 ; CHECK-NEXT: [[SMAX:%.*]] = call i8 @llvm.smax.i8(i8 [[TMP1]], i8 0)
592 ; CHECK-NEXT: [[TMP2:%.*]] = sub i8 [[TMP0]], [[SMAX]]
593 ; CHECK-NEXT: [[TMP3:%.*]] = add nsw i8 [[N]], -2
594 ; CHECK-NEXT: [[SMIN:%.*]] = call i8 @llvm.smin.i8(i8 [[TMP3]], i8 0)
595 ; CHECK-NEXT: [[SMAX2:%.*]] = call i8 @llvm.smax.i8(i8 [[SMIN]], i8 -1)
596 ; CHECK-NEXT: [[TMP4:%.*]] = add nsw i8 [[SMAX2]], 1
597 ; CHECK-NEXT: [[TMP5:%.*]] = mul i8 [[TMP2]], [[TMP4]]
598 ; CHECK-NEXT: [[SMIN3:%.*]] = call i8 @llvm.smin.i8(i8 [[LIMIT]], i8 [[TMP5]])
599 ; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = call i8 @llvm.smax.i8(i8 [[SMIN3]], i8 0)
600 ; CHECK-NEXT: [[TMP6:%.*]] = icmp slt i8 0, [[EXIT_MAINLOOP_AT]]
601 ; CHECK-NEXT: br i1 [[TMP6]], label [[LOOP_PREHEADER6:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
602 ; CHECK: loop.preheader6:
603 ; CHECK-NEXT: br label [[LOOP:%.*]]
605 ; CHECK-NEXT: [[IDX:%.*]] = phi i8 [ [[IDX_NEXT:%.*]], [[INBOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER6]] ]
606 ; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[N]], [[IDX]]
607 ; CHECK-NEXT: [[CHECK:%.*]] = icmp sgt i8 [[SUB]], 2
608 ; CHECK-NEXT: br i1 true, label [[INBOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT7:%.*]]
610 ; CHECK-NEXT: [[IDX_NEXT]] = add nuw nsw i8 [[IDX]], 1
611 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[IDX_NEXT]], [[LIMIT]]
612 ; CHECK-NEXT: [[TMP7:%.*]] = icmp slt i8 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]
613 ; CHECK-NEXT: br i1 [[TMP7]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
614 ; CHECK: main.exit.selector:
615 ; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i8 [ [[IDX_NEXT]], [[INBOUNDS]] ]
616 ; CHECK-NEXT: [[IDX_LCSSA5:%.*]] = phi i8 [ [[IDX]], [[INBOUNDS]] ]
617 ; CHECK-NEXT: [[TMP8:%.*]] = icmp slt i8 [[IDX_NEXT_LCSSA]], [[LIMIT]]
618 ; CHECK-NEXT: br i1 [[TMP8]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT_LOOPEXIT:%.*]]
619 ; CHECK: main.pseudo.exit:
620 ; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i8 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
621 ; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i8 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
622 ; CHECK-NEXT: br label [[POSTLOOP:%.*]]
623 ; CHECK: exit.loopexit.loopexit:
624 ; CHECK-NEXT: [[IDX_LCSSA1_PH:%.*]] = phi i8 [ [[IDX_POSTLOOP:%.*]], [[INBOUNDS_POSTLOOP:%.*]] ]
625 ; CHECK-NEXT: br label [[EXIT_LOOPEXIT]]
626 ; CHECK: exit.loopexit:
627 ; CHECK-NEXT: [[IDX_LCSSA1:%.*]] = phi i8 [ [[IDX_LCSSA5]], [[MAIN_EXIT_SELECTOR]] ], [ [[IDX_LCSSA1_PH]], [[EXIT_LOOPEXIT_LOOPEXIT:%.*]] ]
628 ; CHECK-NEXT: br label [[EXIT]]
630 ; CHECK-NEXT: [[RES:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IDX_LCSSA1]], [[EXIT_LOOPEXIT]] ]
631 ; CHECK-NEXT: ret i8 [[RES]]
632 ; CHECK: out_of_bounds.loopexit:
633 ; CHECK-NEXT: [[IDX_LCSSA_PH:%.*]] = phi i8 [ [[IDX_POSTLOOP]], [[LOOP_POSTLOOP:%.*]] ]
634 ; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]
635 ; CHECK: out_of_bounds.loopexit7:
636 ; CHECK-NEXT: [[IDX_LCSSA_PH8:%.*]] = phi i8 [ [[IDX]], [[LOOP]] ]
637 ; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]
638 ; CHECK: out_of_bounds:
639 ; CHECK-NEXT: [[IDX_LCSSA:%.*]] = phi i8 [ [[IDX_LCSSA_PH]], [[OUT_OF_BOUNDS_LOOPEXIT:%.*]] ], [ [[IDX_LCSSA_PH8]], [[OUT_OF_BOUNDS_LOOPEXIT7]] ]
640 ; CHECK-NEXT: ret i8 [[IDX_LCSSA]]
642 ; CHECK-NEXT: br label [[LOOP_POSTLOOP]]
643 ; CHECK: loop.postloop:
644 ; CHECK-NEXT: [[IDX_POSTLOOP]] = phi i8 [ [[IDX_NEXT_POSTLOOP:%.*]], [[INBOUNDS_POSTLOOP]] ], [ [[IDX_COPY]], [[POSTLOOP]] ]
645 ; CHECK-NEXT: [[SUB_POSTLOOP:%.*]] = sub i8 [[N]], [[IDX_POSTLOOP]]
646 ; CHECK-NEXT: [[CHECK_POSTLOOP:%.*]] = icmp sgt i8 [[SUB_POSTLOOP]], 2
647 ; CHECK-NEXT: br i1 [[CHECK_POSTLOOP]], label [[INBOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT]]
648 ; CHECK: inbounds.postloop:
649 ; CHECK-NEXT: [[IDX_NEXT_POSTLOOP]] = add nuw i8 [[IDX_POSTLOOP]], 1
650 ; CHECK-NEXT: [[CMP_POSTLOOP:%.*]] = icmp slt i8 [[IDX_NEXT_POSTLOOP]], [[LIMIT]]
651 ; CHECK-NEXT: br i1 [[CMP_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT]], !llvm.loop [[LOOP10:![0-9]+]], !loop_constrainer.loop.clone !5
654 %n = load i8, ptr %p, !range !0
655 %precheck = icmp sgt i8 %limit, 0
656 br i1 %precheck, label %loop, label %exit
659 %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ]
660 %sub = sub i8 %n, %idx
661 %check = icmp sgt i8 %sub, 2
662 br i1 %check, label %inbounds, label %out_of_bounds
665 %idx.next = add nuw i8 %idx, 1
666 %cmp = icmp slt i8 %idx.next, %limit
667 br i1 %cmp, label %loop, label %exit
670 %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
677 ; IV = 0; IV <s limit; IV += 1;
679 ; TODO: IRCE is allowed.
680 define i8 @test5(i8 %limit, i8 %n) {
681 ; CHECK-LABEL: define i8 @test5
682 ; CHECK-SAME: (i8 [[LIMIT:%.*]], i8 [[N:%.*]]) {
684 ; CHECK-NEXT: [[PRECHECK:%.*]] = icmp sgt i8 [[LIMIT]], 0
685 ; CHECK-NEXT: br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
686 ; CHECK: loop.preheader:
687 ; CHECK-NEXT: br label [[LOOP:%.*]]
689 ; CHECK-NEXT: [[IDX:%.*]] = phi i8 [ [[IDX_NEXT:%.*]], [[INBOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
690 ; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[IDX]], [[N]]
691 ; CHECK-NEXT: [[CHECK:%.*]] = icmp slt i8 [[SUB]], -2
692 ; CHECK-NEXT: br i1 [[CHECK]], label [[INBOUNDS]], label [[OUT_OF_BOUNDS:%.*]]
694 ; CHECK-NEXT: [[IDX_NEXT]] = add nuw i8 [[IDX]], 1
695 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[IDX_NEXT]], [[LIMIT]]
696 ; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
697 ; CHECK: exit.loopexit:
698 ; CHECK-NEXT: [[IDX_LCSSA1:%.*]] = phi i8 [ [[IDX]], [[INBOUNDS]] ]
699 ; CHECK-NEXT: br label [[EXIT]]
701 ; CHECK-NEXT: [[RES:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IDX_LCSSA1]], [[EXIT_LOOPEXIT]] ]
702 ; CHECK-NEXT: ret i8 [[RES]]
703 ; CHECK: out_of_bounds:
704 ; CHECK-NEXT: [[IDX_LCSSA:%.*]] = phi i8 [ [[IDX]], [[LOOP]] ]
705 ; CHECK-NEXT: ret i8 [[IDX_LCSSA]]
708 %precheck = icmp sgt i8 %limit, 0
709 br i1 %precheck, label %loop, label %exit
712 %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ]
713 %sub = sub i8 %idx, %n
714 %check = icmp slt i8 %sub, -2
715 br i1 %check, label %inbounds, label %out_of_bounds
718 %idx.next = add nuw i8 %idx, 1
719 %cmp = icmp slt i8 %idx.next, %limit
720 br i1 %cmp, label %loop, label %exit
723 %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
730 ; IV = 0; IV <s limit; IV += 1;
732 ; N is known to be non-negative.
733 ; TODO: IRCE is allowed.
734 define i8 @test5a(i8 %limit, ptr %p) {
735 ; CHECK-LABEL: define i8 @test5a
736 ; CHECK-SAME: (i8 [[LIMIT:%.*]], ptr [[P:%.*]]) {
738 ; CHECK-NEXT: [[N:%.*]] = load i8, ptr [[P]], align 1, !range [[RNG6]]
739 ; CHECK-NEXT: [[PRECHECK:%.*]] = icmp sgt i8 [[LIMIT]], 0
740 ; CHECK-NEXT: br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
741 ; CHECK: loop.preheader:
742 ; CHECK-NEXT: br label [[LOOP:%.*]]
744 ; CHECK-NEXT: [[IDX:%.*]] = phi i8 [ [[IDX_NEXT:%.*]], [[INBOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
745 ; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[IDX]], [[N]]
746 ; CHECK-NEXT: [[CHECK:%.*]] = icmp slt i8 [[SUB]], -2
747 ; CHECK-NEXT: br i1 [[CHECK]], label [[INBOUNDS]], label [[OUT_OF_BOUNDS:%.*]]
749 ; CHECK-NEXT: [[IDX_NEXT]] = add nuw i8 [[IDX]], 1
750 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[IDX_NEXT]], [[LIMIT]]
751 ; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
752 ; CHECK: exit.loopexit:
753 ; CHECK-NEXT: [[IDX_LCSSA1:%.*]] = phi i8 [ [[IDX]], [[INBOUNDS]] ]
754 ; CHECK-NEXT: br label [[EXIT]]
756 ; CHECK-NEXT: [[RES:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IDX_LCSSA1]], [[EXIT_LOOPEXIT]] ]
757 ; CHECK-NEXT: ret i8 [[RES]]
758 ; CHECK: out_of_bounds:
759 ; CHECK-NEXT: [[IDX_LCSSA:%.*]] = phi i8 [ [[IDX]], [[LOOP]] ]
760 ; CHECK-NEXT: ret i8 [[IDX_LCSSA]]
763 %n = load i8, ptr %p, !range !0
764 %precheck = icmp sgt i8 %limit, 0
765 br i1 %precheck, label %loop, label %exit
768 %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ]
769 %sub = sub i8 %idx, %n
770 %check = icmp slt i8 %sub, -2
771 br i1 %check, label %inbounds, label %out_of_bounds
774 %idx.next = add nuw i8 %idx, 1
775 %cmp = icmp slt i8 %idx.next, %limit
776 br i1 %cmp, label %loop, label %exit
779 %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
786 ; IV = 0; IV <s limit; IV += 1;
789 define i8 @test6(i8 %limit, i8 %n) {
790 ; CHECK-LABEL: define i8 @test6
791 ; CHECK-SAME: (i8 [[LIMIT:%.*]], i8 [[N:%.*]]) {
793 ; CHECK-NEXT: [[PRECHECK:%.*]] = icmp sgt i8 [[LIMIT]], 0
794 ; CHECK-NEXT: br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
795 ; CHECK: loop.preheader:
796 ; CHECK-NEXT: [[TMP0:%.*]] = add i8 [[N]], -127
797 ; CHECK-NEXT: [[SMAX:%.*]] = call i8 @llvm.smax.i8(i8 [[TMP0]], i8 2)
798 ; CHECK-NEXT: [[TMP1:%.*]] = sub i8 [[N]], [[SMAX]]
799 ; CHECK-NEXT: [[SMIN:%.*]] = call i8 @llvm.smin.i8(i8 [[N]], i8 0)
800 ; CHECK-NEXT: [[SMAX2:%.*]] = call i8 @llvm.smax.i8(i8 [[SMIN]], i8 -1)
801 ; CHECK-NEXT: [[TMP2:%.*]] = add nsw i8 [[SMAX2]], 1
802 ; CHECK-NEXT: [[TMP3:%.*]] = mul i8 [[TMP1]], [[TMP2]]
803 ; CHECK-NEXT: [[SMIN3:%.*]] = call i8 @llvm.smin.i8(i8 [[LIMIT]], i8 [[TMP3]])
804 ; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = call i8 @llvm.smax.i8(i8 [[SMIN3]], i8 0)
805 ; CHECK-NEXT: [[TMP4:%.*]] = icmp slt i8 0, [[EXIT_MAINLOOP_AT]]
806 ; CHECK-NEXT: br i1 [[TMP4]], label [[LOOP_PREHEADER6:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
807 ; CHECK: loop.preheader6:
808 ; CHECK-NEXT: br label [[LOOP:%.*]]
810 ; CHECK-NEXT: [[IDX:%.*]] = phi i8 [ [[IDX_NEXT:%.*]], [[INBOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER6]] ]
811 ; CHECK-NEXT: [[ADD:%.*]] = add i8 [[IDX]], 2
812 ; CHECK-NEXT: [[CHECK:%.*]] = icmp slt i8 [[ADD]], [[N]]
813 ; CHECK-NEXT: br i1 true, label [[INBOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT7:%.*]]
815 ; CHECK-NEXT: [[IDX_NEXT]] = add nuw nsw i8 [[IDX]], 1
816 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[IDX_NEXT]], [[LIMIT]]
817 ; CHECK-NEXT: [[TMP5:%.*]] = icmp slt i8 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]
818 ; CHECK-NEXT: br i1 [[TMP5]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
819 ; CHECK: main.exit.selector:
820 ; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i8 [ [[IDX_NEXT]], [[INBOUNDS]] ]
821 ; CHECK-NEXT: [[IDX_LCSSA5:%.*]] = phi i8 [ [[IDX]], [[INBOUNDS]] ]
822 ; CHECK-NEXT: [[TMP6:%.*]] = icmp slt i8 [[IDX_NEXT_LCSSA]], [[LIMIT]]
823 ; CHECK-NEXT: br i1 [[TMP6]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT_LOOPEXIT:%.*]]
824 ; CHECK: main.pseudo.exit:
825 ; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i8 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
826 ; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i8 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
827 ; CHECK-NEXT: br label [[POSTLOOP:%.*]]
828 ; CHECK: exit.loopexit.loopexit:
829 ; CHECK-NEXT: [[IDX_LCSSA1_PH:%.*]] = phi i8 [ [[IDX_POSTLOOP:%.*]], [[INBOUNDS_POSTLOOP:%.*]] ]
830 ; CHECK-NEXT: br label [[EXIT_LOOPEXIT]]
831 ; CHECK: exit.loopexit:
832 ; CHECK-NEXT: [[IDX_LCSSA1:%.*]] = phi i8 [ [[IDX_LCSSA5]], [[MAIN_EXIT_SELECTOR]] ], [ [[IDX_LCSSA1_PH]], [[EXIT_LOOPEXIT_LOOPEXIT:%.*]] ]
833 ; CHECK-NEXT: br label [[EXIT]]
835 ; CHECK-NEXT: [[RES:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IDX_LCSSA1]], [[EXIT_LOOPEXIT]] ]
836 ; CHECK-NEXT: ret i8 [[RES]]
837 ; CHECK: out_of_bounds.loopexit:
838 ; CHECK-NEXT: [[IDX_LCSSA_PH:%.*]] = phi i8 [ [[IDX_POSTLOOP]], [[LOOP_POSTLOOP:%.*]] ]
839 ; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]
840 ; CHECK: out_of_bounds.loopexit7:
841 ; CHECK-NEXT: [[IDX_LCSSA_PH8:%.*]] = phi i8 [ [[IDX]], [[LOOP]] ]
842 ; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]
843 ; CHECK: out_of_bounds:
844 ; CHECK-NEXT: [[IDX_LCSSA:%.*]] = phi i8 [ [[IDX_LCSSA_PH]], [[OUT_OF_BOUNDS_LOOPEXIT:%.*]] ], [ [[IDX_LCSSA_PH8]], [[OUT_OF_BOUNDS_LOOPEXIT7]] ]
845 ; CHECK-NEXT: ret i8 [[IDX_LCSSA]]
847 ; CHECK-NEXT: br label [[LOOP_POSTLOOP]]
848 ; CHECK: loop.postloop:
849 ; CHECK-NEXT: [[IDX_POSTLOOP]] = phi i8 [ [[IDX_NEXT_POSTLOOP:%.*]], [[INBOUNDS_POSTLOOP]] ], [ [[IDX_COPY]], [[POSTLOOP]] ]
850 ; CHECK-NEXT: [[ADD_POSTLOOP:%.*]] = add i8 [[IDX_POSTLOOP]], 2
851 ; CHECK-NEXT: [[CHECK_POSTLOOP:%.*]] = icmp slt i8 [[ADD_POSTLOOP]], [[N]]
852 ; CHECK-NEXT: br i1 [[CHECK_POSTLOOP]], label [[INBOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT]]
853 ; CHECK: inbounds.postloop:
854 ; CHECK-NEXT: [[IDX_NEXT_POSTLOOP]] = add nuw i8 [[IDX_POSTLOOP]], 1
855 ; CHECK-NEXT: [[CMP_POSTLOOP:%.*]] = icmp slt i8 [[IDX_NEXT_POSTLOOP]], [[LIMIT]]
856 ; CHECK-NEXT: br i1 [[CMP_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT]], !llvm.loop [[LOOP11:![0-9]+]], !loop_constrainer.loop.clone !5
859 %precheck = icmp sgt i8 %limit, 0
860 br i1 %precheck, label %loop, label %exit
863 %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ]
864 %add = add i8 %idx, 2
865 %check = icmp slt i8 %add, %n
866 br i1 %check, label %inbounds, label %out_of_bounds
869 %idx.next = add nuw i8 %idx, 1
870 %cmp = icmp slt i8 %idx.next, %limit
871 br i1 %cmp, label %loop, label %exit
874 %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
881 ; IV = 0; IV <s limit; IV += 1;
883 ; N is known to be non-negative.
885 define i8 @test6a(i8 %limit, ptr %p) {
886 ; CHECK-LABEL: define i8 @test6a
887 ; CHECK-SAME: (i8 [[LIMIT:%.*]], ptr [[P:%.*]]) {
889 ; CHECK-NEXT: [[N:%.*]] = load i8, ptr [[P]], align 1, !range [[RNG6]]
890 ; CHECK-NEXT: [[PRECHECK:%.*]] = icmp sgt i8 [[LIMIT]], 0
891 ; CHECK-NEXT: br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
892 ; CHECK: loop.preheader:
893 ; CHECK-NEXT: [[TMP0:%.*]] = add nsw i8 [[N]], -2
894 ; CHECK-NEXT: [[SMIN:%.*]] = call i8 @llvm.smin.i8(i8 [[LIMIT]], i8 [[TMP0]])
895 ; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = call i8 @llvm.smax.i8(i8 [[SMIN]], i8 0)
896 ; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i8 0, [[EXIT_MAINLOOP_AT]]
897 ; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP_PREHEADER3:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
898 ; CHECK: loop.preheader3:
899 ; CHECK-NEXT: br label [[LOOP:%.*]]
901 ; CHECK-NEXT: [[IDX:%.*]] = phi i8 [ [[IDX_NEXT:%.*]], [[INBOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER3]] ]
902 ; CHECK-NEXT: [[ADD:%.*]] = add i8 [[IDX]], 2
903 ; CHECK-NEXT: [[CHECK:%.*]] = icmp slt i8 [[ADD]], [[N]]
904 ; CHECK-NEXT: br i1 true, label [[INBOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT4:%.*]]
906 ; CHECK-NEXT: [[IDX_NEXT]] = add nuw nsw i8 [[IDX]], 1
907 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[IDX_NEXT]], [[LIMIT]]
908 ; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i8 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]
909 ; CHECK-NEXT: br i1 [[TMP2]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
910 ; CHECK: main.exit.selector:
911 ; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i8 [ [[IDX_NEXT]], [[INBOUNDS]] ]
912 ; CHECK-NEXT: [[IDX_LCSSA2:%.*]] = phi i8 [ [[IDX]], [[INBOUNDS]] ]
913 ; CHECK-NEXT: [[TMP3:%.*]] = icmp slt i8 [[IDX_NEXT_LCSSA]], [[LIMIT]]
914 ; CHECK-NEXT: br i1 [[TMP3]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT_LOOPEXIT:%.*]]
915 ; CHECK: main.pseudo.exit:
916 ; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i8 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
917 ; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i8 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
918 ; CHECK-NEXT: br label [[POSTLOOP:%.*]]
919 ; CHECK: exit.loopexit.loopexit:
920 ; CHECK-NEXT: [[IDX_LCSSA1_PH:%.*]] = phi i8 [ [[IDX_POSTLOOP:%.*]], [[INBOUNDS_POSTLOOP:%.*]] ]
921 ; CHECK-NEXT: br label [[EXIT_LOOPEXIT]]
922 ; CHECK: exit.loopexit:
923 ; CHECK-NEXT: [[IDX_LCSSA1:%.*]] = phi i8 [ [[IDX_LCSSA2]], [[MAIN_EXIT_SELECTOR]] ], [ [[IDX_LCSSA1_PH]], [[EXIT_LOOPEXIT_LOOPEXIT:%.*]] ]
924 ; CHECK-NEXT: br label [[EXIT]]
926 ; CHECK-NEXT: [[RES:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IDX_LCSSA1]], [[EXIT_LOOPEXIT]] ]
927 ; CHECK-NEXT: ret i8 [[RES]]
928 ; CHECK: out_of_bounds.loopexit:
929 ; CHECK-NEXT: [[IDX_LCSSA_PH:%.*]] = phi i8 [ [[IDX_POSTLOOP]], [[LOOP_POSTLOOP:%.*]] ]
930 ; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]
931 ; CHECK: out_of_bounds.loopexit4:
932 ; CHECK-NEXT: [[IDX_LCSSA_PH5:%.*]] = phi i8 [ [[IDX]], [[LOOP]] ]
933 ; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]
934 ; CHECK: out_of_bounds:
935 ; CHECK-NEXT: [[IDX_LCSSA:%.*]] = phi i8 [ [[IDX_LCSSA_PH]], [[OUT_OF_BOUNDS_LOOPEXIT:%.*]] ], [ [[IDX_LCSSA_PH5]], [[OUT_OF_BOUNDS_LOOPEXIT4]] ]
936 ; CHECK-NEXT: ret i8 [[IDX_LCSSA]]
938 ; CHECK-NEXT: br label [[LOOP_POSTLOOP]]
939 ; CHECK: loop.postloop:
940 ; CHECK-NEXT: [[IDX_POSTLOOP]] = phi i8 [ [[IDX_NEXT_POSTLOOP:%.*]], [[INBOUNDS_POSTLOOP]] ], [ [[IDX_COPY]], [[POSTLOOP]] ]
941 ; CHECK-NEXT: [[ADD_POSTLOOP:%.*]] = add i8 [[IDX_POSTLOOP]], 2
942 ; CHECK-NEXT: [[CHECK_POSTLOOP:%.*]] = icmp slt i8 [[ADD_POSTLOOP]], [[N]]
943 ; CHECK-NEXT: br i1 [[CHECK_POSTLOOP]], label [[INBOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT]]
944 ; CHECK: inbounds.postloop:
945 ; CHECK-NEXT: [[IDX_NEXT_POSTLOOP]] = add nuw i8 [[IDX_POSTLOOP]], 1
946 ; CHECK-NEXT: [[CMP_POSTLOOP:%.*]] = icmp slt i8 [[IDX_NEXT_POSTLOOP]], [[LIMIT]]
947 ; CHECK-NEXT: br i1 [[CMP_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT]], !llvm.loop [[LOOP12:![0-9]+]], !loop_constrainer.loop.clone !5
950 %n = load i8, ptr %p, !range !0
951 %precheck = icmp sgt i8 %limit, 0
952 br i1 %precheck, label %loop, label %exit
955 %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ]
956 %add = add i8 %idx, 2
957 %check = icmp slt i8 %add, %n
958 br i1 %check, label %inbounds, label %out_of_bounds
961 %idx.next = add nuw i8 %idx, 1
962 %cmp = icmp slt i8 %idx.next, %limit
963 br i1 %cmp, label %loop, label %exit
966 %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
973 ; IV = 0; IV <s limit; IV += 1;
977 ; IRCE will reassociate this range check to the 'IV < N + 2',
978 ; since N < 126 no-overflow fact is provable at compile time.
979 define i8 @test_overflow_check_compile_time(i8 %limit, ptr %p) {
980 ; CHECK-LABEL: define i8 @test_overflow_check_compile_time
981 ; CHECK-SAME: (i8 [[LIMIT:%.*]], ptr [[P:%.*]]) {
983 ; CHECK-NEXT: [[N:%.*]] = load i8, ptr [[P]], align 1, !range [[RNG13:![0-9]+]]
984 ; CHECK-NEXT: [[PRECHECK:%.*]] = icmp sgt i8 [[LIMIT]], 0
985 ; CHECK-NEXT: br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
986 ; CHECK: loop.preheader:
987 ; CHECK-NEXT: [[TMP0:%.*]] = add nuw nsw i8 [[N]], 2
988 ; CHECK-NEXT: [[SMIN:%.*]] = call i8 @llvm.smin.i8(i8 [[LIMIT]], i8 [[TMP0]])
989 ; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = call i8 @llvm.smax.i8(i8 [[SMIN]], i8 0)
990 ; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i8 0, [[EXIT_MAINLOOP_AT]]
991 ; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP_PREHEADER3:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
992 ; CHECK: loop.preheader3:
993 ; CHECK-NEXT: br label [[LOOP:%.*]]
995 ; CHECK-NEXT: [[IDX:%.*]] = phi i8 [ [[IDX_NEXT:%.*]], [[INBOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER3]] ]
996 ; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[N]], [[IDX]]
997 ; CHECK-NEXT: [[CHECK:%.*]] = icmp sgt i8 [[SUB]], -2
998 ; CHECK-NEXT: br i1 true, label [[INBOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT4:%.*]]
1000 ; CHECK-NEXT: [[IDX_NEXT]] = add nuw nsw i8 [[IDX]], 1
1001 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[IDX_NEXT]], [[LIMIT]]
1002 ; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i8 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]
1003 ; CHECK-NEXT: br i1 [[TMP2]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
1004 ; CHECK: main.exit.selector:
1005 ; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i8 [ [[IDX_NEXT]], [[INBOUNDS]] ]
1006 ; CHECK-NEXT: [[IDX_LCSSA2:%.*]] = phi i8 [ [[IDX]], [[INBOUNDS]] ]
1007 ; CHECK-NEXT: [[TMP3:%.*]] = icmp slt i8 [[IDX_NEXT_LCSSA]], [[LIMIT]]
1008 ; CHECK-NEXT: br i1 [[TMP3]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT_LOOPEXIT:%.*]]
1009 ; CHECK: main.pseudo.exit:
1010 ; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i8 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
1011 ; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i8 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
1012 ; CHECK-NEXT: br label [[POSTLOOP:%.*]]
1013 ; CHECK: exit.loopexit.loopexit:
1014 ; CHECK-NEXT: [[IDX_LCSSA1_PH:%.*]] = phi i8 [ [[IDX_POSTLOOP:%.*]], [[INBOUNDS_POSTLOOP:%.*]] ]
1015 ; CHECK-NEXT: br label [[EXIT_LOOPEXIT]]
1016 ; CHECK: exit.loopexit:
1017 ; CHECK-NEXT: [[IDX_LCSSA1:%.*]] = phi i8 [ [[IDX_LCSSA2]], [[MAIN_EXIT_SELECTOR]] ], [ [[IDX_LCSSA1_PH]], [[EXIT_LOOPEXIT_LOOPEXIT:%.*]] ]
1018 ; CHECK-NEXT: br label [[EXIT]]
1020 ; CHECK-NEXT: [[RES:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IDX_LCSSA1]], [[EXIT_LOOPEXIT]] ]
1021 ; CHECK-NEXT: ret i8 [[RES]]
1022 ; CHECK: out_of_bounds.loopexit:
1023 ; CHECK-NEXT: [[IDX_LCSSA_PH:%.*]] = phi i8 [ [[IDX_POSTLOOP]], [[LOOP_POSTLOOP:%.*]] ]
1024 ; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]
1025 ; CHECK: out_of_bounds.loopexit4:
1026 ; CHECK-NEXT: [[IDX_LCSSA_PH5:%.*]] = phi i8 [ [[IDX]], [[LOOP]] ]
1027 ; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]
1028 ; CHECK: out_of_bounds:
1029 ; CHECK-NEXT: [[IDX_LCSSA:%.*]] = phi i8 [ [[IDX_LCSSA_PH]], [[OUT_OF_BOUNDS_LOOPEXIT:%.*]] ], [ [[IDX_LCSSA_PH5]], [[OUT_OF_BOUNDS_LOOPEXIT4]] ]
1030 ; CHECK-NEXT: ret i8 [[IDX_LCSSA]]
1032 ; CHECK-NEXT: br label [[LOOP_POSTLOOP]]
1033 ; CHECK: loop.postloop:
1034 ; CHECK-NEXT: [[IDX_POSTLOOP]] = phi i8 [ [[IDX_NEXT_POSTLOOP:%.*]], [[INBOUNDS_POSTLOOP]] ], [ [[IDX_COPY]], [[POSTLOOP]] ]
1035 ; CHECK-NEXT: [[SUB_POSTLOOP:%.*]] = sub i8 [[N]], [[IDX_POSTLOOP]]
1036 ; CHECK-NEXT: [[CHECK_POSTLOOP:%.*]] = icmp sgt i8 [[SUB_POSTLOOP]], -2
1037 ; CHECK-NEXT: br i1 [[CHECK_POSTLOOP]], label [[INBOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT]]
1038 ; CHECK: inbounds.postloop:
1039 ; CHECK-NEXT: [[IDX_NEXT_POSTLOOP]] = add nuw i8 [[IDX_POSTLOOP]], 1
1040 ; CHECK-NEXT: [[CMP_POSTLOOP:%.*]] = icmp slt i8 [[IDX_NEXT_POSTLOOP]], [[LIMIT]]
1041 ; CHECK-NEXT: br i1 [[CMP_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT]], !llvm.loop [[LOOP14:![0-9]+]], !loop_constrainer.loop.clone !5
1044 %n = load i8, ptr %p, !range !1
1045 %precheck = icmp sgt i8 %limit, 0
1046 br i1 %precheck, label %loop, label %exit
1049 %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ]
1050 %sub = sub i8 %n, %idx
1051 %check = icmp sgt i8 %sub, -2
1052 br i1 %check, label %inbounds, label %out_of_bounds
1055 %idx.next = add nuw i8 %idx, 1
1056 %cmp = icmp slt i8 %idx.next, %limit
1057 br i1 %cmp, label %loop, label %exit
1060 %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
1067 ; IV = 0; IV <s limit; IV += 1;
1068 ; Check(N - IV >= -2)
1071 ; IRCE will reassociate this range check to the 'IV < (N + 2) + 1',
1072 ; since N < 126 no-overflow fact is NOT provable at compile time and
1073 ; runtime overflow check is required.
1074 define i8 @test_overflow_check_runtime(i8 %limit, ptr %p) {
1075 ; CHECK-LABEL: define i8 @test_overflow_check_runtime
1076 ; CHECK-SAME: (i8 [[LIMIT:%.*]], ptr [[P:%.*]]) {
1077 ; CHECK-NEXT: entry:
1078 ; CHECK-NEXT: [[N:%.*]] = load i8, ptr [[P]], align 1, !range [[RNG13]]
1079 ; CHECK-NEXT: [[PRECHECK:%.*]] = icmp sgt i8 [[LIMIT]], 0
1080 ; CHECK-NEXT: br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
1081 ; CHECK: loop.preheader:
1082 ; CHECK-NEXT: [[TMP0:%.*]] = add i8 [[N]], 3
1083 ; CHECK-NEXT: [[TMP1:%.*]] = add nsw i8 [[N]], -124
1084 ; CHECK-NEXT: [[SMAX:%.*]] = call i8 @llvm.smax.i8(i8 [[TMP1]], i8 0)
1085 ; CHECK-NEXT: [[TMP2:%.*]] = sub i8 [[TMP0]], [[SMAX]]
1086 ; CHECK-NEXT: [[TMP3:%.*]] = add nuw i8 [[N]], 3
1087 ; CHECK-NEXT: [[SMIN:%.*]] = call i8 @llvm.smin.i8(i8 [[TMP3]], i8 0)
1088 ; CHECK-NEXT: [[SMAX2:%.*]] = call i8 @llvm.smax.i8(i8 [[SMIN]], i8 -1)
1089 ; CHECK-NEXT: [[TMP4:%.*]] = add nsw i8 [[SMAX2]], 1
1090 ; CHECK-NEXT: [[TMP5:%.*]] = mul i8 [[TMP2]], [[TMP4]]
1091 ; CHECK-NEXT: [[TMP6:%.*]] = zext nneg i8 [[N]] to i16
1092 ; CHECK-NEXT: [[TMP7:%.*]] = sub i16 124, [[TMP6]]
1093 ; CHECK-NEXT: [[SMIN3:%.*]] = call i16 @llvm.smin.i16(i16 [[TMP7]], i16 0)
1094 ; CHECK-NEXT: [[TMP8:%.*]] = trunc i16 [[SMIN3]] to i8
1095 ; CHECK-NEXT: [[TMP9:%.*]] = add nsw i8 [[TMP8]], 1
1096 ; CHECK-NEXT: [[TMP10:%.*]] = mul i8 [[TMP5]], [[TMP9]]
1097 ; CHECK-NEXT: [[SMIN4:%.*]] = call i8 @llvm.smin.i8(i8 [[LIMIT]], i8 [[TMP10]])
1098 ; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = call i8 @llvm.smax.i8(i8 [[SMIN4]], i8 0)
1099 ; CHECK-NEXT: [[TMP11:%.*]] = icmp slt i8 0, [[EXIT_MAINLOOP_AT]]
1100 ; CHECK-NEXT: br i1 [[TMP11]], label [[LOOP_PREHEADER7:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
1101 ; CHECK: loop.preheader7:
1102 ; CHECK-NEXT: br label [[LOOP:%.*]]
1104 ; CHECK-NEXT: [[IDX:%.*]] = phi i8 [ [[IDX_NEXT:%.*]], [[INBOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER7]] ]
1105 ; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[N]], [[IDX]]
1106 ; CHECK-NEXT: [[CHECK:%.*]] = icmp sge i8 [[SUB]], -2
1107 ; CHECK-NEXT: br i1 true, label [[INBOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT8:%.*]]
1109 ; CHECK-NEXT: [[IDX_NEXT]] = add nuw nsw i8 [[IDX]], 1
1110 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[IDX_NEXT]], [[LIMIT]]
1111 ; CHECK-NEXT: [[TMP12:%.*]] = icmp slt i8 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]
1112 ; CHECK-NEXT: br i1 [[TMP12]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
1113 ; CHECK: main.exit.selector:
1114 ; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i8 [ [[IDX_NEXT]], [[INBOUNDS]] ]
1115 ; CHECK-NEXT: [[IDX_LCSSA6:%.*]] = phi i8 [ [[IDX]], [[INBOUNDS]] ]
1116 ; CHECK-NEXT: [[TMP13:%.*]] = icmp slt i8 [[IDX_NEXT_LCSSA]], [[LIMIT]]
1117 ; CHECK-NEXT: br i1 [[TMP13]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT_LOOPEXIT:%.*]]
1118 ; CHECK: main.pseudo.exit:
1119 ; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i8 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
1120 ; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i8 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
1121 ; CHECK-NEXT: br label [[POSTLOOP:%.*]]
1122 ; CHECK: exit.loopexit.loopexit:
1123 ; CHECK-NEXT: [[IDX_LCSSA1_PH:%.*]] = phi i8 [ [[IDX_POSTLOOP:%.*]], [[INBOUNDS_POSTLOOP:%.*]] ]
1124 ; CHECK-NEXT: br label [[EXIT_LOOPEXIT]]
1125 ; CHECK: exit.loopexit:
1126 ; CHECK-NEXT: [[IDX_LCSSA1:%.*]] = phi i8 [ [[IDX_LCSSA6]], [[MAIN_EXIT_SELECTOR]] ], [ [[IDX_LCSSA1_PH]], [[EXIT_LOOPEXIT_LOOPEXIT:%.*]] ]
1127 ; CHECK-NEXT: br label [[EXIT]]
1129 ; CHECK-NEXT: [[RES:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IDX_LCSSA1]], [[EXIT_LOOPEXIT]] ]
1130 ; CHECK-NEXT: ret i8 [[RES]]
1131 ; CHECK: out_of_bounds.loopexit:
1132 ; CHECK-NEXT: [[IDX_LCSSA_PH:%.*]] = phi i8 [ [[IDX_POSTLOOP]], [[LOOP_POSTLOOP:%.*]] ]
1133 ; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]
1134 ; CHECK: out_of_bounds.loopexit8:
1135 ; CHECK-NEXT: [[IDX_LCSSA_PH9:%.*]] = phi i8 [ [[IDX]], [[LOOP]] ]
1136 ; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]
1137 ; CHECK: out_of_bounds:
1138 ; CHECK-NEXT: [[IDX_LCSSA:%.*]] = phi i8 [ [[IDX_LCSSA_PH]], [[OUT_OF_BOUNDS_LOOPEXIT:%.*]] ], [ [[IDX_LCSSA_PH9]], [[OUT_OF_BOUNDS_LOOPEXIT8]] ]
1139 ; CHECK-NEXT: ret i8 [[IDX_LCSSA]]
1141 ; CHECK-NEXT: br label [[LOOP_POSTLOOP]]
1142 ; CHECK: loop.postloop:
1143 ; CHECK-NEXT: [[IDX_POSTLOOP]] = phi i8 [ [[IDX_NEXT_POSTLOOP:%.*]], [[INBOUNDS_POSTLOOP]] ], [ [[IDX_COPY]], [[POSTLOOP]] ]
1144 ; CHECK-NEXT: [[SUB_POSTLOOP:%.*]] = sub i8 [[N]], [[IDX_POSTLOOP]]
1145 ; CHECK-NEXT: [[CHECK_POSTLOOP:%.*]] = icmp sge i8 [[SUB_POSTLOOP]], -2
1146 ; CHECK-NEXT: br i1 [[CHECK_POSTLOOP]], label [[INBOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT]]
1147 ; CHECK: inbounds.postloop:
1148 ; CHECK-NEXT: [[IDX_NEXT_POSTLOOP]] = add nuw i8 [[IDX_POSTLOOP]], 1
1149 ; CHECK-NEXT: [[CMP_POSTLOOP:%.*]] = icmp slt i8 [[IDX_NEXT_POSTLOOP]], [[LIMIT]]
1150 ; CHECK-NEXT: br i1 [[CMP_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT]], !llvm.loop [[LOOP15:![0-9]+]], !loop_constrainer.loop.clone !5
1153 %n = load i8, ptr %p, !range !1
1154 %precheck = icmp sgt i8 %limit, 0
1155 br i1 %precheck, label %loop, label %exit
1158 %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ]
1159 %sub = sub i8 %n, %idx
1160 %check = icmp sge i8 %sub, -2
1161 br i1 %check, label %inbounds, label %out_of_bounds
1164 %idx.next = add nuw i8 %idx, 1
1165 %cmp = icmp slt i8 %idx.next, %limit
1166 br i1 %cmp, label %loop, label %exit
1169 %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
1176 !0 = !{i8 0, i8 127}
1177 !1 = !{i8 0, i8 126}