[rtsan] Add fork/execve interceptors (#117198)
[llvm-project.git] / llvm / test / Transforms / IRCE / iv-plus-offset-range-check.ll
blobd6d55dd9b10f27dd6dbd961d3635e05013b73768
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;
24 ;   Check(N - IV >= 2)
25 ; IRCE is allowed.
26 define i8 @test1(i8 %limit, i8 %n) {
27 ; CHECK-LABEL: define i8 @test1
28 ; CHECK-SAME: (i8 [[LIMIT:%.*]], i8 [[N:%.*]]) {
29 ; CHECK-NEXT:  entry:
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:%.*]]
53 ; CHECK:       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:%.*]]
58 ; CHECK:       inbounds:
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]]
78 ; CHECK:       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]]
90 ; CHECK:       postloop:
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
102 entry:
103   %precheck = icmp sgt i8 %limit, 0
104   br i1 %precheck, label %loop, label %exit
106 loop:
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
112 inbounds:
113   %idx.next = add nuw i8 %idx, 1
114   %cmp = icmp slt i8 %idx.next, %limit
115   br i1 %cmp, label %loop, label %exit
117 exit:
118   %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
119   ret i8 %res
121 out_of_bounds:
122   ret i8 %idx;
125 ; IV = 0; IV <s limit; IV += 1;
126 ;   Check(N - IV >= 2)
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:%.*]]) {
132 ; CHECK-NEXT:  entry:
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:%.*]]
147 ; CHECK:       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:%.*]]
152 ; CHECK:       inbounds:
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]]
172 ; CHECK:       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]]
184 ; CHECK:       postloop:
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
196 entry:
197   %n = load i8, ptr %p, !range !0
198   %precheck = icmp sgt i8 %limit, 0
199   br i1 %precheck, label %loop, label %exit
201 loop:
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
207 inbounds:
208   %idx.next = add nuw i8 %idx, 1
209   %cmp = icmp slt i8 %idx.next, %limit
210   br i1 %cmp, label %loop, label %exit
212 exit:
213   %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
214   ret i8 %res
216 out_of_bounds:
217   ret i8 %idx;
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:%.*]]) {
226 ; CHECK-NEXT:  entry:
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:%.*]]
231 ; CHECK:       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:%.*]]
236 ; CHECK:       inbounds:
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]]
243 ; CHECK:       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]]
250 entry:
251   %precheck = icmp sgt i8 %limit, 0
252   br i1 %precheck, label %loop, label %exit
254 loop:
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
260 inbounds:
261   %idx.next = add nuw i8 %idx, 1
262   %cmp = icmp slt i8 %idx.next, %limit
263   br i1 %cmp, label %loop, label %exit
265 exit:
266   %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
267   ret i8 %res
269 out_of_bounds:
270   ret i8 %idx;
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:%.*]]) {
280 ; CHECK-NEXT:  entry:
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:%.*]]
286 ; CHECK:       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:%.*]]
291 ; CHECK:       inbounds:
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]]
298 ; CHECK:       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]]
305 entry:
306   %n = load i8, ptr %p, !range !0
307   %precheck = icmp sgt i8 %limit, 0
308   br i1 %precheck, label %loop, label %exit
310 loop:
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
316 inbounds:
317   %idx.next = add nuw i8 %idx, 1
318   %cmp = icmp slt i8 %idx.next, %limit
319   br i1 %cmp, label %loop, label %exit
321 exit:
322   %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
323   ret i8 %res
325 out_of_bounds:
326   ret i8 %idx;
329 ; IV = 0; IV <s limit; IV += 1;
330 ;   Check(IV + 2 <= N)
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:%.*]]) {
335 ; CHECK-NEXT:  entry:
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:%.*]]
340 ; CHECK:       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:%.*]]
345 ; CHECK:       inbounds:
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]]
352 ; CHECK:       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]]
359 entry:
360   %precheck = icmp sgt i8 %limit, 0
361   br i1 %precheck, label %loop, label %exit
363 loop:
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
369 inbounds:
370   %idx.next = add nuw i8 %idx, 1
371   %cmp = icmp slt i8 %idx.next, %limit
372   br i1 %cmp, label %loop, label %exit
374 exit:
375   %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
376   ret i8 %res
378 out_of_bounds:
379   ret i8 %idx;
382 ; IV = 0; IV <s limit; IV += 1;
383 ;   Check(IV + 2 <= N)
384 ; N is known to be non-negative.
385 ; IRCE is allowed.
386 define i8 @test3a(i8 %limit, ptr %p) {
387 ; CHECK-LABEL: define i8 @test3a
388 ; CHECK-SAME: (i8 [[LIMIT:%.*]], ptr [[P:%.*]]) {
389 ; CHECK-NEXT:  entry:
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:%.*]]
401 ; CHECK:       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:%.*]]
406 ; CHECK:       inbounds:
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]]
426 ; CHECK:       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]]
438 ; CHECK:       postloop:
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
450 entry:
451   %n = load i8, ptr %p, !range !0
452   %precheck = icmp sgt i8 %limit, 0
453   br i1 %precheck, label %loop, label %exit
455 loop:
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
461 inbounds:
462   %idx.next = add nuw i8 %idx, 1
463   %cmp = icmp slt i8 %idx.next, %limit
464   br i1 %cmp, label %loop, label %exit
466 exit:
467   %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
468   ret i8 %res
470 out_of_bounds:
471   ret i8 %idx;
474 ; IV = 0; IV <s limit; IV += 1;
475 ;   Check(N - IV > 2)
476 ; IRCE is allowed.
477 define i8 @test4(i8 %limit, i8 %n) {
478 ; CHECK-LABEL: define i8 @test4
479 ; CHECK-SAME: (i8 [[LIMIT:%.*]], i8 [[N:%.*]]) {
480 ; CHECK-NEXT:  entry:
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:%.*]]
505 ; CHECK:       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:%.*]]
510 ; CHECK:       inbounds:
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]]
530 ; CHECK:       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]]
542 ; CHECK:       postloop:
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
554 entry:
555   %precheck = icmp sgt i8 %limit, 0
556   br i1 %precheck, label %loop, label %exit
558 loop:
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
564 inbounds:
565   %idx.next = add nuw i8 %idx, 1
566   %cmp = icmp slt i8 %idx.next, %limit
567   br i1 %cmp, label %loop, label %exit
569 exit:
570   %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
571   ret i8 %res
573 out_of_bounds:
574   ret i8 %idx;
577 ; IV = 0; IV <s limit; IV += 1;
578 ;   Check(N - IV > 2)
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:%.*]]) {
584 ; CHECK-NEXT:  entry:
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:%.*]]
604 ; CHECK:       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:%.*]]
609 ; CHECK:       inbounds:
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]]
629 ; CHECK:       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]]
641 ; CHECK:       postloop:
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
653 entry:
654   %n = load i8, ptr %p, !range !0
655   %precheck = icmp sgt i8 %limit, 0
656   br i1 %precheck, label %loop, label %exit
658 loop:
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
664 inbounds:
665   %idx.next = add nuw i8 %idx, 1
666   %cmp = icmp slt i8 %idx.next, %limit
667   br i1 %cmp, label %loop, label %exit
669 exit:
670   %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
671   ret i8 %res
673 out_of_bounds:
674   ret i8 %idx;
677 ; IV = 0; IV <s limit; IV += 1;
678 ;   Check(IV - N < -2)
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:%.*]]) {
683 ; CHECK-NEXT:  entry:
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:%.*]]
688 ; CHECK:       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:%.*]]
693 ; CHECK:       inbounds:
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]]
700 ; CHECK:       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]]
707 entry:
708   %precheck = icmp sgt i8 %limit, 0
709   br i1 %precheck, label %loop, label %exit
711 loop:
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
717 inbounds:
718   %idx.next = add nuw i8 %idx, 1
719   %cmp = icmp slt i8 %idx.next, %limit
720   br i1 %cmp, label %loop, label %exit
722 exit:
723   %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
724   ret i8 %res
726 out_of_bounds:
727   ret i8 %idx;
730 ; IV = 0; IV <s limit; IV += 1;
731 ;   Check(IV - N < -2)
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:%.*]]) {
737 ; CHECK-NEXT:  entry:
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:%.*]]
743 ; CHECK:       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:%.*]]
748 ; CHECK:       inbounds:
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]]
755 ; CHECK:       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]]
762 entry:
763   %n = load i8, ptr %p, !range !0
764   %precheck = icmp sgt i8 %limit, 0
765   br i1 %precheck, label %loop, label %exit
767 loop:
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
773 inbounds:
774   %idx.next = add nuw i8 %idx, 1
775   %cmp = icmp slt i8 %idx.next, %limit
776   br i1 %cmp, label %loop, label %exit
778 exit:
779   %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
780   ret i8 %res
782 out_of_bounds:
783   ret i8 %idx;
786 ; IV = 0; IV <s limit; IV += 1;
787 ;   Check(IV + 2 < N)
788 ; IRCE is allowed.
789 define i8 @test6(i8 %limit, i8 %n) {
790 ; CHECK-LABEL: define i8 @test6
791 ; CHECK-SAME: (i8 [[LIMIT:%.*]], i8 [[N:%.*]]) {
792 ; CHECK-NEXT:  entry:
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:%.*]]
809 ; CHECK:       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:%.*]]
814 ; CHECK:       inbounds:
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]]
834 ; CHECK:       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]]
846 ; CHECK:       postloop:
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
858 entry:
859   %precheck = icmp sgt i8 %limit, 0
860   br i1 %precheck, label %loop, label %exit
862 loop:
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
868 inbounds:
869   %idx.next = add nuw i8 %idx, 1
870   %cmp = icmp slt i8 %idx.next, %limit
871   br i1 %cmp, label %loop, label %exit
873 exit:
874   %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
875   ret i8 %res
877 out_of_bounds:
878   ret i8 %idx;
881 ; IV = 0; IV <s limit; IV += 1;
882 ;   Check(IV + 2 < N)
883 ; N is known to be non-negative.
884 ; IRCE is allowed.
885 define i8 @test6a(i8 %limit, ptr %p) {
886 ; CHECK-LABEL: define i8 @test6a
887 ; CHECK-SAME: (i8 [[LIMIT:%.*]], ptr [[P:%.*]]) {
888 ; CHECK-NEXT:  entry:
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:%.*]]
900 ; CHECK:       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:%.*]]
905 ; CHECK:       inbounds:
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]]
925 ; CHECK:       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]]
937 ; CHECK:       postloop:
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
949 entry:
950   %n = load i8, ptr %p, !range !0
951   %precheck = icmp sgt i8 %limit, 0
952   br i1 %precheck, label %loop, label %exit
954 loop:
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
960 inbounds:
961   %idx.next = add nuw i8 %idx, 1
962   %cmp = icmp slt i8 %idx.next, %limit
963   br i1 %cmp, label %loop, label %exit
965 exit:
966   %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
967   ret i8 %res
969 out_of_bounds:
970   ret i8 %idx;
973 ; IV = 0; IV <s limit; IV += 1;
974 ;   Check(N - IV > -2)
976 ; IRCE is allowed.
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:%.*]]) {
982 ; CHECK-NEXT:  entry:
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:%.*]]
994 ; CHECK:       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:%.*]]
999 ; CHECK:       inbounds:
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]]
1019 ; CHECK:       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]]
1031 ; CHECK:       postloop:
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
1043 entry:
1044   %n = load i8, ptr %p, !range !1
1045   %precheck = icmp sgt i8 %limit, 0
1046   br i1 %precheck, label %loop, label %exit
1048 loop:
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
1054 inbounds:
1055   %idx.next = add nuw i8 %idx, 1
1056   %cmp = icmp slt i8 %idx.next, %limit
1057   br i1 %cmp, label %loop, label %exit
1059 exit:
1060   %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
1061   ret i8 %res
1063 out_of_bounds:
1064   ret i8 %idx;
1067 ; IV = 0; IV <s limit; IV += 1;
1068 ;   Check(N - IV >= -2)
1070 ; IRCE is allowed.
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:%.*]]
1103 ; CHECK:       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:%.*]]
1108 ; CHECK:       inbounds:
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]]
1128 ; CHECK:       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]]
1140 ; CHECK:       postloop:
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
1152 entry:
1153   %n = load i8, ptr %p, !range !1
1154   %precheck = icmp sgt i8 %limit, 0
1155   br i1 %precheck, label %loop, label %exit
1157 loop:
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
1163 inbounds:
1164   %idx.next = add nuw i8 %idx, 1
1165   %cmp = icmp slt i8 %idx.next, %limit
1166   br i1 %cmp, label %loop, label %exit
1168 exit:
1169   %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
1170   ret i8 %res
1172 out_of_bounds:
1173   ret i8 %idx;
1176 !0 = !{i8 0, i8 127}
1177 !1 = !{i8 0, i8 126}