1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s
3
4declare void @llvm.assume(i1 noundef) #0
5
6define i1 @n_unknown(ptr %dst, i32 %n, i32 %i) {
7; CHECK-LABEL: @n_unknown(
8; CHECK-NEXT:  entry:
9; CHECK-NEXT:    [[SUB:%.*]] = add i32 [[N:%.*]], -1
10; CHECK-NEXT:    [[IDXPROM:%.*]] = zext i32 [[SUB]] to i64
11; CHECK-NEXT:    [[PTR_N_SUB_1:%.*]] = getelementptr i32, ptr [[DST:%.*]], i64 [[IDXPROM]]
12; CHECK-NEXT:    [[CMP_PTR_DST:%.*]] = icmp sge ptr [[PTR_N_SUB_1]], [[DST]]
13; CHECK-NEXT:    br i1 [[CMP_PTR_DST]], label [[PRE_BB_2:%.*]], label [[EXIT:%.*]]
14; CHECK:       exit:
15; CHECK-NEXT:    ret i1 false
16; CHECK:       pre.bb.2:
17; CHECK-NEXT:    [[PRE_2:%.*]] = icmp sge i32 [[I:%.*]], 0
18; CHECK-NEXT:    br i1 [[PRE_2]], label [[TGT_BB:%.*]], label [[EXIT]]
19; CHECK:       tgt.bb:
20; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[I]], [[N]]
21; CHECK-NEXT:    ret i1 [[CMP1]]
22;
23entry:
24  %sub = add i32 %n, -1
25  %idxprom = zext i32 %sub to i64
26  %ptr.n.sub.1 = getelementptr i32, ptr %dst, i64 %idxprom
27  %cmp.ptr.dst = icmp sge ptr %ptr.n.sub.1, %dst
28  br i1 %cmp.ptr.dst, label %pre.bb.2, label %exit
29
30exit:
31  ret i1 false
32
33pre.bb.2:
34  %pre.2 = icmp sge i32 %i, 0
35  br i1 %pre.2, label %tgt.bb, label %exit
36
37tgt.bb:
38  %cmp1 = icmp slt i32 %i, %n
39  ret i1 %cmp1
40}
41
42define i1 @n_known_zero_due_to_nuw(ptr %dst, i32 %n, i32 %i) {
43; CHECK-LABEL: @n_known_zero_due_to_nuw(
44; CHECK-NEXT:  entry:
45; CHECK-NEXT:    [[SUB:%.*]] = add i32 [[N:%.*]], -1
46; CHECK-NEXT:    [[IDXPROM:%.*]] = zext i32 [[SUB]] to i64
47; CHECK-NEXT:    [[PTR_N_SUB_1:%.*]] = getelementptr i32, ptr [[DST:%.*]], i64 [[IDXPROM]]
48; CHECK-NEXT:    [[CMP_PTR_DST:%.*]] = icmp sge ptr [[PTR_N_SUB_1]], [[DST]]
49; CHECK-NEXT:    br i1 [[CMP_PTR_DST]], label [[PRE_BB_2:%.*]], label [[EXIT:%.*]]
50; CHECK:       exit:
51; CHECK-NEXT:    ret i1 false
52; CHECK:       pre.bb.2:
53; CHECK-NEXT:    [[PRE_2:%.*]] = icmp sge i32 [[I:%.*]], 0
54; CHECK-NEXT:    br i1 [[PRE_2]], label [[TGT_BB:%.*]], label [[EXIT]]
55; CHECK:       tgt.bb:
56; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[I]], [[N]]
57; CHECK-NEXT:    ret i1 [[CMP1]]
58;
59entry:
60  %sub = add i32 %n, -1
61  %idxprom = zext i32 %sub to i64
62  %ptr.n.sub.1 = getelementptr i32, ptr %dst, i64 %idxprom
63  %cmp.ptr.dst = icmp sge ptr %ptr.n.sub.1, %dst
64  br i1 %cmp.ptr.dst, label %pre.bb.2, label %exit
65
66exit:
67  ret i1 false
68
69pre.bb.2:
70  %pre.2 = icmp sge i32 %i, 0
71  br i1 %pre.2, label %tgt.bb, label %exit
72
73tgt.bb:
74  %cmp1 = icmp slt i32 %i, %n
75  ret i1 %cmp1
76}
77
78define i4 @inc_ptr_N_could_be_negative(ptr %src, ptr %lower, ptr %upper, i8 %N, i8 %step) {
79; CHECK-LABEL: @inc_ptr_N_could_be_negative(
80; CHECK-NEXT:  entry:
81; CHECK-NEXT:    [[SRC_END:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i8 [[N:%.*]]
82; CHECK-NEXT:    [[CMP_SRC_START:%.*]] = icmp slt ptr [[SRC]], [[LOWER:%.*]]
83; CHECK-NEXT:    [[CMP_SRC_END:%.*]] = icmp sge ptr [[SRC_END]], [[UPPER:%.*]]
84; CHECK-NEXT:    [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]]
85; CHECK-NEXT:    br i1 [[OR_PRECOND_0]], label [[TRAP_BB:%.*]], label [[STEP_CHECK:%.*]]
86; CHECK:       trap.bb:
87; CHECK-NEXT:    ret i4 2
88; CHECK:       step.check:
89; CHECK-NEXT:    [[STEP_POS:%.*]] = icmp sge i8 [[STEP:%.*]], 0
90; CHECK-NEXT:    [[NEXT:%.*]] = add nuw nsw i8 [[STEP]], 2
91; CHECK-NEXT:    [[STEP_SLT_N:%.*]] = icmp slt i8 [[NEXT]], [[N]]
92; CHECK-NEXT:    [[AND_STEP:%.*]] = and i1 [[STEP_POS]], [[STEP_SLT_N]]
93; CHECK-NEXT:    br i1 [[AND_STEP]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]]
94; CHECK:       ptr.check:
95; CHECK-NEXT:    [[SRC_STEP:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i8 [[STEP]]
96; CHECK-NEXT:    [[CMP_STEP_START:%.*]] = icmp slt ptr [[SRC_STEP]], [[LOWER]]
97; CHECK-NEXT:    [[CMP_STEP_END:%.*]] = icmp sge ptr [[SRC_STEP]], [[UPPER]]
98; CHECK-NEXT:    [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], [[CMP_STEP_END]]
99; CHECK-NEXT:    br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]]
100; CHECK:       exit:
101; CHECK-NEXT:    ret i4 3
102;
103entry:
104  %src.end = getelementptr inbounds i8, ptr %src, i8 %N
105  %cmp.src.start = icmp slt ptr %src, %lower
106  %cmp.src.end = icmp sge ptr %src.end, %upper
107  %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end
108  br i1 %or.precond.0, label %trap.bb, label %step.check
109
110trap.bb:
111  ret i4 2
112
113step.check:
114  %step.pos = icmp sge i8 %step, 0
115  %next = add nuw nsw i8 %step, 2
116  %step.slt.N = icmp slt i8 %next, %N
117  %and.step = and i1 %step.pos, %step.slt.N
118  br i1 %and.step, label %ptr.check, label %exit
119
120ptr.check:
121  %src.step = getelementptr inbounds i8, ptr %src, i8 %step
122  %cmp.step.start = icmp slt ptr %src.step, %lower
123  %cmp.step.end = icmp sge ptr %src.step, %upper
124  %or.check = or i1 %cmp.step.start, %cmp.step.end
125  br i1 %or.check, label %trap.bb, label %exit
126
127exit:
128  ret i4 3
129}
130
131define i4 @inc_ptr_src_sge_end(ptr %src, ptr %lower, ptr %upper, i16 %N, i16 %step) {
132; CHECK-LABEL: @inc_ptr_src_sge_end(
133; CHECK-NEXT:  entry:
134; CHECK-NEXT:    [[SRC_END:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i16 [[N:%.*]]
135; CHECK-NEXT:    [[CMP_SRC_START:%.*]] = icmp slt ptr [[SRC]], [[LOWER:%.*]]
136; CHECK-NEXT:    [[CMP_SRC_END:%.*]] = icmp sge ptr [[SRC_END]], [[UPPER:%.*]]
137; CHECK-NEXT:    [[CMP_OVERFLOW:%.*]] = icmp sgt ptr [[SRC]], [[SRC_END]]
138; CHECK-NEXT:    [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]]
139; CHECK-NEXT:    [[OR_PRECOND_1:%.*]] = or i1 [[OR_PRECOND_0]], [[CMP_OVERFLOW]]
140; CHECK-NEXT:    br i1 [[OR_PRECOND_1]], label [[TRAP_BB:%.*]], label [[STEP_CHECK:%.*]]
141; CHECK:       trap.bb:
142; CHECK-NEXT:    ret i4 2
143; CHECK:       step.check:
144; CHECK-NEXT:    [[STEP_POS:%.*]] = icmp sge i16 [[STEP:%.*]], 0
145; CHECK-NEXT:    [[NEXT:%.*]] = add nuw nsw i16 [[STEP]], 2
146; CHECK-NEXT:    [[STEP_SLT_N:%.*]] = icmp slt i16 [[NEXT]], [[N]]
147; CHECK-NEXT:    [[AND_STEP:%.*]] = and i1 [[STEP_POS]], [[STEP_SLT_N]]
148; CHECK-NEXT:    br i1 [[AND_STEP]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]]
149; CHECK:       ptr.check:
150; CHECK-NEXT:    [[SRC_STEP:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i16 [[STEP]]
151; CHECK-NEXT:    [[CMP_STEP_START:%.*]] = icmp slt ptr [[SRC_STEP]], [[LOWER]]
152; CHECK-NEXT:    [[CMP_STEP_END:%.*]] = icmp sge ptr [[SRC_STEP]], [[UPPER]]
153; CHECK-NEXT:    [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], [[CMP_STEP_END]]
154; CHECK-NEXT:    br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]]
155; CHECK:       exit:
156; CHECK-NEXT:    ret i4 3
157;
158entry:
159  %src.end = getelementptr inbounds i8, ptr %src, i16 %N
160  %cmp.src.start = icmp slt ptr %src, %lower
161  %cmp.src.end = icmp sge ptr %src.end, %upper
162  %cmp.overflow = icmp sgt ptr %src, %src.end
163  %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end
164  %or.precond.1 = or i1 %or.precond.0, %cmp.overflow
165  br i1 %or.precond.1, label %trap.bb, label %step.check
166
167trap.bb:
168  ret i4 2
169
170step.check:
171  %step.pos = icmp sge i16 %step, 0
172  %next = add nuw nsw i16 %step, 2
173  %step.slt.N = icmp slt i16 %next, %N
174  %and.step = and i1 %step.pos, %step.slt.N
175  br i1 %and.step, label %ptr.check, label %exit
176
177ptr.check:
178  %src.step = getelementptr inbounds i8, ptr %src, i16 %step
179  %cmp.step.start = icmp slt ptr %src.step, %lower
180  %cmp.step.end = icmp sge ptr %src.step, %upper
181  %or.check = or i1 %cmp.step.start, %cmp.step.end
182  br i1 %or.check, label %trap.bb, label %exit
183
184exit:
185  ret i4 3
186}
187
188define i4 @inc_ptr_src_sge_end_no_nsw_add(ptr %src, ptr %lower, ptr %upper, i16 %idx, i16 %N, i16 %step) {
189; CHECK-LABEL: @inc_ptr_src_sge_end_no_nsw_add(
190; CHECK-NEXT:  entry.1:
191; CHECK-NEXT:    [[IDX_POS:%.*]] = icmp sge i16 [[IDX:%.*]], 0
192; CHECK-NEXT:    br i1 [[IDX_POS]], label [[ENTRY:%.*]], label [[TRAP_BB:%.*]]
193; CHECK:       entry:
194; CHECK-NEXT:    [[SRC_IDX:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i16 [[IDX]]
195; CHECK-NEXT:    [[CMP_SRC_START:%.*]] = icmp slt ptr [[SRC_IDX]], [[LOWER:%.*]]
196; CHECK-NEXT:    br i1 [[CMP_SRC_START]], label [[TRAP_BB]], label [[STEP_CHECK:%.*]]
197; CHECK:       trap.bb:
198; CHECK-NEXT:    ret i4 2
199; CHECK:       step.check:
200; CHECK-NEXT:    [[NEXT:%.*]] = add i16 [[IDX]], 2
201; CHECK-NEXT:    [[SRC_STEP:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i16 [[NEXT]]
202; CHECK-NEXT:    [[CMP_STEP_START:%.*]] = icmp slt ptr [[SRC_STEP]], [[LOWER]]
203; CHECK-NEXT:    [[CMP_STEP_END:%.*]] = icmp sge ptr [[SRC_STEP]], [[UPPER:%.*]]
204; CHECK-NEXT:    [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], [[CMP_STEP_END]]
205; CHECK-NEXT:    br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT:%.*]]
206; CHECK:       exit:
207; CHECK-NEXT:    ret i4 3
208;
209entry.1:
210  %idx.pos = icmp sge i16 %idx, 0
211  br i1 %idx.pos, label %entry, label %trap.bb
212
213entry:
214  %src.idx = getelementptr inbounds i8, ptr %src, i16 %idx
215  %cmp.src.start = icmp slt ptr %src.idx, %lower
216  br i1 %cmp.src.start, label %trap.bb, label %step.check
217
218trap.bb:
219  ret i4 2
220
221step.check:
222  %next = add i16 %idx, 2
223  %src.step = getelementptr inbounds i8, ptr %src, i16 %next
224  %cmp.step.start = icmp slt ptr %src.step, %lower
225  %cmp.step.end = icmp sge ptr %src.step, %upper
226  %or.check = or i1 %cmp.step.start, %cmp.step.end
227  br i1 %or.check, label %trap.bb, label %exit
228
229exit:
230  ret i4 3
231}
232
233define i4 @inc_ptr_src_sge_end_no_nsw_add_sge_0(ptr %src, ptr %lower, ptr %upper, i16 %idx, i16 %N, i16 %step) {
234; CHECK-LABEL: @inc_ptr_src_sge_end_no_nsw_add_sge_0(
235; CHECK-NEXT:  entry.1:
236; CHECK-NEXT:    [[IDX_POS:%.*]] = icmp sge i16 [[IDX:%.*]], 0
237; CHECK-NEXT:    br i1 [[IDX_POS]], label [[ENTRY:%.*]], label [[TRAP_BB:%.*]]
238; CHECK:       entry:
239; CHECK-NEXT:    [[SRC_IDX:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i16 [[IDX]]
240; CHECK-NEXT:    [[CMP_SRC_START:%.*]] = icmp slt ptr [[SRC_IDX]], [[LOWER:%.*]]
241; CHECK-NEXT:    br i1 [[CMP_SRC_START]], label [[TRAP_BB]], label [[STEP_CHECK:%.*]]
242; CHECK:       trap.bb:
243; CHECK-NEXT:    ret i4 2
244; CHECK:       step.check:
245; CHECK-NEXT:    [[NEXT:%.*]] = add i16 [[IDX]], 2
246; CHECK-NEXT:    [[SRC_STEP:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i16 [[NEXT]]
247; CHECK-NEXT:    [[CMP_STEP_START:%.*]] = icmp slt ptr [[SRC_STEP]], [[LOWER]]
248; CHECK-NEXT:    [[CMP_STEP_END:%.*]] = icmp sge ptr [[SRC_STEP]], [[UPPER:%.*]]
249; CHECK-NEXT:    [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], [[CMP_STEP_END]]
250; CHECK-NEXT:    br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT:%.*]]
251; CHECK:       exit:
252; CHECK-NEXT:    ret i4 3
253;
254entry.1:
255  %idx.pos = icmp sge i16 %idx, 0
256  br i1 %idx.pos, label %entry, label %trap.bb
257
258entry:
259  %src.idx = getelementptr inbounds i8, ptr %src, i16 %idx
260  %cmp.src.start = icmp slt ptr %src.idx, %lower
261  br i1 %cmp.src.start, label %trap.bb, label %step.check
262
263trap.bb:
264  ret i4 2
265
266step.check:
267  %next = add i16 %idx, 2
268  %src.step = getelementptr inbounds i8, ptr %src, i16 %next
269  %cmp.step.start = icmp slt ptr %src.step, %lower
270  %cmp.step.end = icmp sge ptr %src.step, %upper
271  %or.check = or i1 %cmp.step.start, %cmp.step.end
272  br i1 %or.check, label %trap.bb, label %exit
273
274exit:
275  ret i4 3
276}
277define i4 @ptr_N_step_zext_n_zext(ptr %src, ptr %lower, ptr %upper, i16 %N, i16 %step) {
278; CHECK-LABEL: @ptr_N_step_zext_n_zext(
279; CHECK-NEXT:  entry:
280; CHECK-NEXT:    [[N_ADD_1:%.*]] = add nuw nsw i16 [[N:%.*]], 1
281; CHECK-NEXT:    [[N_ADD_1_EXT:%.*]] = zext i16 [[N_ADD_1]] to i32
282; CHECK-NEXT:    [[SRC_END:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i32 [[N_ADD_1_EXT]]
283; CHECK-NEXT:    [[CMP_SRC_START:%.*]] = icmp slt ptr [[SRC]], [[LOWER:%.*]]
284; CHECK-NEXT:    [[CMP_SRC_END:%.*]] = icmp sge ptr [[SRC_END]], [[UPPER:%.*]]
285; CHECK-NEXT:    [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]]
286; CHECK-NEXT:    br i1 [[OR_PRECOND_0]], label [[TRAP_BB:%.*]], label [[STEP_CHECK:%.*]]
287; CHECK:       trap.bb:
288; CHECK-NEXT:    ret i4 2
289; CHECK:       step.check:
290; CHECK-NEXT:    [[STEP_ADD_1:%.*]] = add nuw nsw i16 [[STEP:%.*]], 1
291; CHECK-NEXT:    [[STEP_ADD_1_EXT:%.*]] = zext i16 [[STEP_ADD_1]] to i32
292; CHECK-NEXT:    [[STEP_SLT_N:%.*]] = icmp slt i32 [[STEP_ADD_1_EXT]], [[N_ADD_1_EXT]]
293; CHECK-NEXT:    br i1 [[STEP_SLT_N]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]]
294; CHECK:       ptr.check:
295; CHECK-NEXT:    [[SRC_STEP:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i32 [[STEP_ADD_1_EXT]]
296; CHECK-NEXT:    [[CMP_STEP_START:%.*]] = icmp slt ptr [[SRC_STEP]], [[LOWER]]
297; CHECK-NEXT:    [[CMP_STEP_END:%.*]] = icmp sge ptr [[SRC_STEP]], [[UPPER]]
298; CHECK-NEXT:    [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], [[CMP_STEP_END]]
299; CHECK-NEXT:    br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]]
300; CHECK:       exit:
301; CHECK-NEXT:    ret i4 3
302;
303entry:
304  %N.add.1 = add nuw nsw i16 %N, 1
305  %N.add.1.ext = zext i16 %N.add.1 to i32
306  %src.end = getelementptr inbounds i8, ptr %src, i32 %N.add.1.ext
307  %cmp.src.start = icmp slt ptr %src, %lower
308  %cmp.src.end = icmp sge ptr %src.end, %upper
309  %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end
310  br i1 %or.precond.0, label %trap.bb, label %step.check
311
312trap.bb:
313  ret i4 2
314
315step.check:
316  %step.add.1 = add nuw nsw i16 %step, 1
317  %step.add.1.ext = zext i16 %step.add.1 to i32
318  %step.slt.N = icmp slt i32 %step.add.1.ext, %N.add.1.ext
319  br i1 %step.slt.N, label %ptr.check, label %exit
320
321ptr.check:
322  %src.step = getelementptr inbounds i8, ptr %src, i32 %step.add.1.ext
323  %cmp.step.start = icmp slt ptr %src.step, %lower
324  %cmp.step.end = icmp sge ptr %src.step, %upper
325  %or.check = or i1 %cmp.step.start, %cmp.step.end
326  br i1 %or.check, label %trap.bb, label %exit
327
328exit:
329  ret i4 3
330}
331
332define i4 @ptr_N_step_zext_n_zext_out_of_bounds(ptr %src, ptr %lower, ptr %upper, i16 %N, i16 %step) {
333; CHECK-LABEL: @ptr_N_step_zext_n_zext_out_of_bounds(
334; CHECK-NEXT:  entry:
335; CHECK-NEXT:    [[N_ADD_2:%.*]] = add nuw nsw i16 [[N:%.*]], 2
336; CHECK-NEXT:    [[N_ADD_2_EXT:%.*]] = zext i16 [[N_ADD_2]] to i32
337; CHECK-NEXT:    [[SRC_END:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i32 [[N_ADD_2_EXT]]
338; CHECK-NEXT:    [[CMP_SRC_START:%.*]] = icmp slt ptr [[SRC]], [[LOWER:%.*]]
339; CHECK-NEXT:    [[CMP_SRC_END:%.*]] = icmp sge ptr [[SRC_END]], [[UPPER:%.*]]
340; CHECK-NEXT:    [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]]
341; CHECK-NEXT:    br i1 [[OR_PRECOND_0]], label [[TRAP_BB:%.*]], label [[STEP_CHECK:%.*]]
342; CHECK:       trap.bb:
343; CHECK-NEXT:    ret i4 2
344; CHECK:       step.check:
345; CHECK-NEXT:    [[STEP_ADD_2:%.*]] = add nuw nsw i16 [[STEP:%.*]], 2
346; CHECK-NEXT:    [[STEP_ADD_2_EXT:%.*]] = zext i16 [[STEP_ADD_2]] to i32
347; CHECK-NEXT:    [[STEP_EXT:%.*]] = zext i16 [[STEP]] to i32
348; CHECK-NEXT:    [[STEP_SLT_N:%.*]] = icmp slt i32 [[STEP_EXT]], [[N_ADD_2_EXT]]
349; CHECK-NEXT:    br i1 [[STEP_SLT_N]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]]
350; CHECK:       ptr.check:
351; CHECK-NEXT:    [[SRC_STEP:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i32 [[STEP_ADD_2_EXT]]
352; CHECK-NEXT:    [[CMP_STEP_START:%.*]] = icmp slt ptr [[SRC_STEP]], [[LOWER]]
353; CHECK-NEXT:    [[CMP_STEP_END:%.*]] = icmp sge ptr [[SRC_STEP]], [[UPPER]]
354; CHECK-NEXT:    [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], [[CMP_STEP_END]]
355; CHECK-NEXT:    br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]]
356; CHECK:       exit:
357; CHECK-NEXT:    ret i4 3
358;
359entry:
360  %N.add.2 = add nuw nsw i16 %N, 2
361  %N.add.2.ext = zext i16 %N.add.2 to i32
362  %src.end = getelementptr inbounds i8, ptr %src, i32 %N.add.2.ext
363  %cmp.src.start = icmp slt ptr %src, %lower
364  %cmp.src.end = icmp sge ptr %src.end, %upper
365  %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end
366  br i1 %or.precond.0, label %trap.bb, label %step.check
367
368trap.bb:
369  ret i4 2
370
371step.check:
372  %step.add.2 = add nuw nsw i16 %step, 2
373  %step.add.2.ext = zext i16 %step.add.2 to i32
374  %step.ext = zext i16 %step to i32
375  %step.slt.N = icmp slt i32 %step.ext, %N.add.2.ext
376  br i1 %step.slt.N, label %ptr.check, label %exit
377
378ptr.check:
379  %src.step = getelementptr inbounds i8, ptr %src, i32 %step.add.2.ext
380  %cmp.step.start = icmp slt ptr %src.step, %lower
381  %cmp.step.end = icmp sge ptr %src.step, %upper
382  %or.check = or i1 %cmp.step.start, %cmp.step.end
383  br i1 %or.check, label %trap.bb, label %exit
384
385exit:
386  ret i4 3
387}
388
389define i1 @gep_count_add_1_sge_known_slt_1(i32 %count, ptr %p) {
390; CHECK-LABEL: @gep_count_add_1_sge_known_slt_1(
391; CHECK-NEXT:  entry:
392; CHECK-NEXT:    [[SGE:%.*]] = icmp sge i32 [[COUNT:%.*]], 1
393; CHECK-NEXT:    call void @llvm.assume(i1 [[SGE]])
394; CHECK-NEXT:    [[COUNT_EXT:%.*]] = zext i32 [[COUNT]] to i64
395; CHECK-NEXT:    [[GEP_COUNT:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 [[COUNT_EXT]]
396; CHECK-NEXT:    [[SUB:%.*]] = add nsw i32 [[COUNT]], -1
397; CHECK-NEXT:    [[SUB_EXT:%.*]] = zext i32 [[SUB]] to i64
398; CHECK-NEXT:    [[GEP_SUB:%.*]] = getelementptr inbounds i32, ptr [[P]], i64 [[SUB_EXT]]
399; CHECK-NEXT:    [[C:%.*]] = icmp slt ptr [[GEP_SUB]], [[GEP_COUNT]]
400; CHECK-NEXT:    ret i1 [[C]]
401;
402entry:
403  %sge = icmp sge i32 %count, 1
404  call void @llvm.assume(i1 %sge)
405  %count.ext = zext i32 %count to i64
406  %gep.count = getelementptr inbounds i32, ptr %p, i64 %count.ext
407  %sub = add nsw i32 %count, -1
408  %sub.ext = zext i32 %sub to i64
409  %gep.sub = getelementptr inbounds i32, ptr %p, i64 %sub.ext
410  %c = icmp slt ptr %gep.sub, %gep.count
411  ;%2 = icmp sge ptr %0, %p
412  ret i1 %c
413}
414
415define i1 @gep_count_add_1_sge_known_sge_1(i32 %count, ptr %p) {
416; CHECK-LABEL: @gep_count_add_1_sge_known_sge_1(
417; CHECK-NEXT:  entry:
418; CHECK-NEXT:    [[SGE:%.*]] = icmp sge i32 [[COUNT:%.*]], 1
419; CHECK-NEXT:    call void @llvm.assume(i1 [[SGE]])
420; CHECK-NEXT:    [[COUNT_EXT:%.*]] = zext i32 [[COUNT]] to i64
421; CHECK-NEXT:    [[GEP_COUNT:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 [[COUNT_EXT]]
422; CHECK-NEXT:    [[SUB:%.*]] = add nsw i32 [[COUNT]], -1
423; CHECK-NEXT:    [[SUB_EXT:%.*]] = zext i32 [[SUB]] to i64
424; CHECK-NEXT:    [[GEP_SUB:%.*]] = getelementptr inbounds i32, ptr [[P]], i64 [[SUB_EXT]]
425; CHECK-NEXT:    [[C:%.*]] = icmp sge ptr [[GEP_SUB]], [[P]]
426; CHECK-NEXT:    ret i1 [[C]]
427;
428entry:
429  %sge = icmp sge i32 %count, 1
430  call void @llvm.assume(i1 %sge)
431  %count.ext = zext i32 %count to i64
432  %gep.count = getelementptr inbounds i32, ptr %p, i64 %count.ext
433  %sub = add nsw i32 %count, -1
434  %sub.ext = zext i32 %sub to i64
435  %gep.sub = getelementptr inbounds i32, ptr %p, i64 %sub.ext
436  %c = icmp sge ptr %gep.sub, %p
437  ret i1 %c
438}
439
440define i1 @gep_count_add_2_sge_not_known_slt_1(i32 %count, ptr %p) {
441; CHECK-LABEL: @gep_count_add_2_sge_not_known_slt_1(
442; CHECK-NEXT:  entry:
443; CHECK-NEXT:    [[SGE:%.*]] = icmp sge i32 [[COUNT:%.*]], 1
444; CHECK-NEXT:    call void @llvm.assume(i1 [[SGE]])
445; CHECK-NEXT:    [[COUNT_EXT:%.*]] = zext i32 [[COUNT]] to i64
446; CHECK-NEXT:    [[GEP_COUNT:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 [[COUNT_EXT]]
447; CHECK-NEXT:    [[SUB:%.*]] = add nsw i32 [[COUNT]], -2
448; CHECK-NEXT:    [[SUB_EXT:%.*]] = zext i32 [[SUB]] to i64
449; CHECK-NEXT:    [[GEP_SUB:%.*]] = getelementptr inbounds i32, ptr [[P]], i64 [[SUB_EXT]]
450; CHECK-NEXT:    [[C:%.*]] = icmp slt ptr [[GEP_SUB]], [[GEP_COUNT]]
451; CHECK-NEXT:    ret i1 [[C]]
452;
453entry:
454  %sge = icmp sge i32 %count, 1
455  call void @llvm.assume(i1 %sge)
456  %count.ext = zext i32 %count to i64
457  %gep.count = getelementptr inbounds i32, ptr %p, i64 %count.ext
458  %sub = add nsw i32 %count, -2
459  %sub.ext = zext i32 %sub to i64
460  %gep.sub = getelementptr inbounds i32, ptr %p, i64 %sub.ext
461  %c = icmp slt ptr %gep.sub, %gep.count
462  ret i1 %c
463}
464
465define i1 @gep_count_add_2_sge_not_known_sge_1(i32 %count, ptr %p) {
466; CHECK-LABEL: @gep_count_add_2_sge_not_known_sge_1(
467; CHECK-NEXT:  entry:
468; CHECK-NEXT:    [[SGE:%.*]] = icmp sge i32 [[COUNT:%.*]], 1
469; CHECK-NEXT:    call void @llvm.assume(i1 [[SGE]])
470; CHECK-NEXT:    [[COUNT_EXT:%.*]] = zext i32 [[COUNT]] to i64
471; CHECK-NEXT:    [[GEP_COUNT:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 [[COUNT_EXT]]
472; CHECK-NEXT:    [[SUB:%.*]] = add nsw i32 [[COUNT]], -2
473; CHECK-NEXT:    [[SUB_EXT:%.*]] = zext i32 [[SUB]] to i64
474; CHECK-NEXT:    [[GEP_SUB:%.*]] = getelementptr inbounds i32, ptr [[P]], i64 [[SUB_EXT]]
475; CHECK-NEXT:    [[C:%.*]] = icmp sge ptr [[GEP_SUB]], [[P]]
476; CHECK-NEXT:    ret i1 [[C]]
477;
478entry:
479  %sge = icmp sge i32 %count, 1
480  call void @llvm.assume(i1 %sge)
481  %count.ext = zext i32 %count to i64
482  %gep.count = getelementptr inbounds i32, ptr %p, i64 %count.ext
483  %sub = add nsw i32 %count, -2
484  %sub.ext = zext i32 %sub to i64
485  %gep.sub = getelementptr inbounds i32, ptr %p, i64 %sub.ext
486  %c = icmp sge ptr %gep.sub, %p
487  ret i1 %c
488}
489