xref: /llvm-project/llvm/test/Transforms/IRCE/iv-plus-offset-range-check.ll (revision 483e92468e597b73c646182bd755a0d5ef67d327)
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
3
4
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
10;
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
16;
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
22
23; IV = 0; IV <s limit; IV += 1;
24;   Check(N - IV >= 2)
25; IRCE is allowed.
26define 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
101;
102entry:
103  %precheck = icmp sgt i8 %limit, 0
104  br i1 %precheck, label %loop, label %exit
105
106loop:
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
111
112inbounds:
113  %idx.next = add nuw i8 %idx, 1
114  %cmp = icmp slt i8 %idx.next, %limit
115  br i1 %cmp, label %loop, label %exit
116
117exit:
118  %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
119  ret i8 %res
120
121out_of_bounds:
122  ret i8 %idx;
123}
124
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.
129define 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
195;
196entry:
197  %n = load i8, ptr %p, !range !0
198  %precheck = icmp sgt i8 %limit, 0
199  br i1 %precheck, label %loop, label %exit
200
201loop:
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
206
207inbounds:
208  %idx.next = add nuw i8 %idx, 1
209  %cmp = icmp slt i8 %idx.next, %limit
210  br i1 %cmp, label %loop, label %exit
211
212exit:
213  %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
214  ret i8 %res
215
216out_of_bounds:
217  ret i8 %idx;
218}
219
220; IV = 0; IV <s limit; IV += 1;
221;   Check(IV - N <= -2)
222; TODO: IRCE is allowed.
223define 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]]
249;
250entry:
251  %precheck = icmp sgt i8 %limit, 0
252  br i1 %precheck, label %loop, label %exit
253
254loop:
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
259
260inbounds:
261  %idx.next = add nuw i8 %idx, 1
262  %cmp = icmp slt i8 %idx.next, %limit
263  br i1 %cmp, label %loop, label %exit
264
265exit:
266  %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
267  ret i8 %res
268
269out_of_bounds:
270  ret i8 %idx;
271}
272
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.
277define 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]]
304;
305entry:
306  %n = load i8, ptr %p, !range !0
307  %precheck = icmp sgt i8 %limit, 0
308  br i1 %precheck, label %loop, label %exit
309
310loop:
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
315
316inbounds:
317  %idx.next = add nuw i8 %idx, 1
318  %cmp = icmp slt i8 %idx.next, %limit
319  br i1 %cmp, label %loop, label %exit
320
321exit:
322  %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
323  ret i8 %res
324
325out_of_bounds:
326  ret i8 %idx;
327}
328
329; IV = 0; IV <s limit; IV += 1;
330;   Check(IV + 2 <= N)
331; TODO: IRCE is allowed.
332define 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]]
358;
359entry:
360  %precheck = icmp sgt i8 %limit, 0
361  br i1 %precheck, label %loop, label %exit
362
363loop:
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
368
369inbounds:
370  %idx.next = add nuw i8 %idx, 1
371  %cmp = icmp slt i8 %idx.next, %limit
372  br i1 %cmp, label %loop, label %exit
373
374exit:
375  %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
376  ret i8 %res
377
378out_of_bounds:
379  ret i8 %idx;
380}
381
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.
386define 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
449;
450entry:
451  %n = load i8, ptr %p, !range !0
452  %precheck = icmp sgt i8 %limit, 0
453  br i1 %precheck, label %loop, label %exit
454
455loop:
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
460
461inbounds:
462  %idx.next = add nuw i8 %idx, 1
463  %cmp = icmp slt i8 %idx.next, %limit
464  br i1 %cmp, label %loop, label %exit
465
466exit:
467  %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
468  ret i8 %res
469
470out_of_bounds:
471  ret i8 %idx;
472}
473
474; IV = 0; IV <s limit; IV += 1;
475;   Check(N - IV > 2)
476; IRCE is allowed.
477define 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
553;
554entry:
555  %precheck = icmp sgt i8 %limit, 0
556  br i1 %precheck, label %loop, label %exit
557
558loop:
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
563
564inbounds:
565  %idx.next = add nuw i8 %idx, 1
566  %cmp = icmp slt i8 %idx.next, %limit
567  br i1 %cmp, label %loop, label %exit
568
569exit:
570  %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
571  ret i8 %res
572
573out_of_bounds:
574  ret i8 %idx;
575}
576
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.
581define 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
652;
653entry:
654  %n = load i8, ptr %p, !range !0
655  %precheck = icmp sgt i8 %limit, 0
656  br i1 %precheck, label %loop, label %exit
657
658loop:
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
663
664inbounds:
665  %idx.next = add nuw i8 %idx, 1
666  %cmp = icmp slt i8 %idx.next, %limit
667  br i1 %cmp, label %loop, label %exit
668
669exit:
670  %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
671  ret i8 %res
672
673out_of_bounds:
674  ret i8 %idx;
675}
676
677; IV = 0; IV <s limit; IV += 1;
678;   Check(IV - N < -2)
679; TODO: IRCE is allowed.
680define 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]]
706;
707entry:
708  %precheck = icmp sgt i8 %limit, 0
709  br i1 %precheck, label %loop, label %exit
710
711loop:
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
716
717inbounds:
718  %idx.next = add nuw i8 %idx, 1
719  %cmp = icmp slt i8 %idx.next, %limit
720  br i1 %cmp, label %loop, label %exit
721
722exit:
723  %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
724  ret i8 %res
725
726out_of_bounds:
727  ret i8 %idx;
728}
729
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.
734define 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]]
761;
762entry:
763  %n = load i8, ptr %p, !range !0
764  %precheck = icmp sgt i8 %limit, 0
765  br i1 %precheck, label %loop, label %exit
766
767loop:
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
772
773inbounds:
774  %idx.next = add nuw i8 %idx, 1
775  %cmp = icmp slt i8 %idx.next, %limit
776  br i1 %cmp, label %loop, label %exit
777
778exit:
779  %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
780  ret i8 %res
781
782out_of_bounds:
783  ret i8 %idx;
784}
785
786; IV = 0; IV <s limit; IV += 1;
787;   Check(IV + 2 < N)
788; IRCE is allowed.
789define 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
857;
858entry:
859  %precheck = icmp sgt i8 %limit, 0
860  br i1 %precheck, label %loop, label %exit
861
862loop:
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
867
868inbounds:
869  %idx.next = add nuw i8 %idx, 1
870  %cmp = icmp slt i8 %idx.next, %limit
871  br i1 %cmp, label %loop, label %exit
872
873exit:
874  %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
875  ret i8 %res
876
877out_of_bounds:
878  ret i8 %idx;
879}
880
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.
885define 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
948;
949entry:
950  %n = load i8, ptr %p, !range !0
951  %precheck = icmp sgt i8 %limit, 0
952  br i1 %precheck, label %loop, label %exit
953
954loop:
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
959
960inbounds:
961  %idx.next = add nuw i8 %idx, 1
962  %cmp = icmp slt i8 %idx.next, %limit
963  br i1 %cmp, label %loop, label %exit
964
965exit:
966  %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
967  ret i8 %res
968
969out_of_bounds:
970  ret i8 %idx;
971}
972
973; IV = 0; IV <s limit; IV += 1;
974;   Check(N - IV > -2)
975;
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.
979define 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
1042;
1043entry:
1044  %n = load i8, ptr %p, !range !1
1045  %precheck = icmp sgt i8 %limit, 0
1046  br i1 %precheck, label %loop, label %exit
1047
1048loop:
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
1053
1054inbounds:
1055  %idx.next = add nuw i8 %idx, 1
1056  %cmp = icmp slt i8 %idx.next, %limit
1057  br i1 %cmp, label %loop, label %exit
1058
1059exit:
1060  %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
1061  ret i8 %res
1062
1063out_of_bounds:
1064  ret i8 %idx;
1065}
1066
1067; IV = 0; IV <s limit; IV += 1;
1068;   Check(N - IV >= -2)
1069;
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.
1074define 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
1151;
1152entry:
1153  %n = load i8, ptr %p, !range !1
1154  %precheck = icmp sgt i8 %limit, 0
1155  br i1 %precheck, label %loop, label %exit
1156
1157loop:
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
1162
1163inbounds:
1164  %idx.next = add nuw i8 %idx, 1
1165  %cmp = icmp slt i8 %idx.next, %limit
1166  br i1 %cmp, label %loop, label %exit
1167
1168exit:
1169  %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]
1170  ret i8 %res
1171
1172out_of_bounds:
1173  ret i8 %idx;
1174}
1175
1176!0 = !{i8 0, i8 127}
1177!1 = !{i8 0, i8 126}
1178