[ORC] Add std::tuple support to SimplePackedSerialization.
[llvm-project.git] / llvm / test / Transforms / ConstraintElimination / gep-arithmetic.ll
blob220c8fa14402a69cd3436e337b5db1b052a0431e
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -constraint-elimination -S %s | FileCheck %s
4 declare void @llvm.assume(i1)
6 define i1 @n_unknown(i32* %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, i32* [[DST:%.*]], i64 [[IDXPROM]]
12 ; CHECK-NEXT:    [[CMP_PTR_DST:%.*]] = icmp uge i32* [[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 uge i32 [[I:%.*]], 0
18 ; CHECK-NEXT:    br i1 [[PRE_2]], label [[TGT_BB:%.*]], label [[EXIT]]
19 ; CHECK:       tgt.bb:
20 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i32 [[I]], [[N]]
21 ; CHECK-NEXT:    ret i1 [[CMP1]]
23 entry:
24   %sub = add i32 %n, -1
25   %idxprom = zext i32 %sub to i64
26   %ptr.n.sub.1 = getelementptr i32, i32* %dst, i64 %idxprom
27   %cmp.ptr.dst = icmp uge i32* %ptr.n.sub.1, %dst
28   br i1 %cmp.ptr.dst, label %pre.bb.2, label %exit
30 exit:
31   ret i1 false
33 pre.bb.2:
34   %pre.2 = icmp uge i32 %i, 0
35   br i1 %pre.2, label %tgt.bb, label %exit
37 tgt.bb:
38   %cmp1 = icmp ult i32 %i, %n
39   ret i1 %cmp1
42 define i1 @n_known_zero_due_to_nuw(i32* %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, i32* [[DST:%.*]], i64 [[IDXPROM]]
48 ; CHECK-NEXT:    [[CMP_PTR_DST:%.*]] = icmp uge i32* [[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 uge i32 [[I:%.*]], 0
54 ; CHECK-NEXT:    br i1 [[PRE_2]], label [[TGT_BB:%.*]], label [[EXIT]]
55 ; CHECK:       tgt.bb:
56 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i32 [[I]], [[N]]
57 ; CHECK-NEXT:    ret i1 [[CMP1]]
59 entry:
60   %sub = add i32 %n, -1
61   %idxprom = zext i32 %sub to i64
62   %ptr.n.sub.1 = getelementptr i32, i32* %dst, i64 %idxprom
63   %cmp.ptr.dst = icmp uge i32* %ptr.n.sub.1, %dst
64   br i1 %cmp.ptr.dst, label %pre.bb.2, label %exit
66 exit:
67   ret i1 false
69 pre.bb.2:
70   %pre.2 = icmp uge i32 %i, 0
71   br i1 %pre.2, label %tgt.bb, label %exit
73 tgt.bb:
74   %cmp1 = icmp ult i32 %i, %n
75   ret i1 %cmp1
78 define i4 @ptr_N_signed_positive_explicit_check_constant_step(i8* %src, i8* %lower, i8* %upper, i16 %N) {
79 ; CHECK-LABEL: @ptr_N_signed_positive_explicit_check_constant_step(
80 ; CHECK-NEXT:  entry:
81 ; CHECK-NEXT:    [[N_POS:%.*]] = icmp sge i16 [[N:%.*]], 0
82 ; CHECK-NEXT:    br i1 [[N_POS]], label [[ENTRY_1:%.*]], label [[TRAP_BB:%.*]]
83 ; CHECK:       entry.1:
84 ; CHECK-NEXT:    [[SRC_END:%.*]] = getelementptr inbounds i8, i8* [[SRC:%.*]], i16 [[N]]
85 ; CHECK-NEXT:    [[CMP_SRC_START:%.*]] = icmp ult i8* [[SRC]], [[LOWER:%.*]]
86 ; CHECK-NEXT:    [[CMP_SRC_END:%.*]] = icmp uge i8* [[SRC_END]], [[UPPER:%.*]]
87 ; CHECK-NEXT:    [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]]
88 ; CHECK-NEXT:    br i1 [[OR_PRECOND_0]], label [[TRAP_BB]], label [[STEP_CHECK:%.*]]
89 ; CHECK:       trap.bb:
90 ; CHECK-NEXT:    ret i4 2
91 ; CHECK:       step.check:
92 ; CHECK-NEXT:    [[STEP_ULT_N:%.*]] = icmp ult i16 1, [[N]]
93 ; CHECK-NEXT:    br i1 [[STEP_ULT_N]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]]
94 ; CHECK:       ptr.check:
95 ; CHECK-NEXT:    [[SRC_STEP:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i16 1
96 ; CHECK-NEXT:    [[CMP_STEP_START:%.*]] = icmp ult i8* [[SRC_STEP]], [[LOWER]]
97 ; CHECK-NEXT:    [[CMP_STEP_END:%.*]] = icmp uge i8* [[SRC_STEP]], [[UPPER]]
98 ; CHECK-NEXT:    [[OR_CHECK:%.*]] = or i1 false, false
99 ; CHECK-NEXT:    br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]]
100 ; CHECK:       exit:
101 ; CHECK-NEXT:    ret i4 3
104 entry:
105   %N.pos = icmp sge i16 %N, 0
106   br i1 %N.pos, label %entry.1, label %trap.bb
108 entry.1:
109   %src.end = getelementptr inbounds i8, i8* %src, i16 %N
110   %cmp.src.start = icmp ult i8* %src, %lower
111   %cmp.src.end = icmp uge i8* %src.end, %upper
112   %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end
113   br i1 %or.precond.0, label %trap.bb, label %step.check
115 trap.bb:
116   ret i4 2
118 step.check:
119   %step.ult.N = icmp ult i16 1, %N
120   br i1 %step.ult.N, label %ptr.check, label %exit
122 ptr.check:
123   %src.step = getelementptr inbounds i8, i8* %src, i16 1
124   %cmp.step.start = icmp ult i8* %src.step, %lower
125   %cmp.step.end = icmp uge i8* %src.step, %upper
126   %or.check = or i1 %cmp.step.start, %cmp.step.end
127   br i1 %or.check, label %trap.bb, label %exit
129 exit:
130   ret i4 3
133 ; Same as ptr_N_signed_positive_explicit_check_constant_step, but without inbounds.
134 define i4 @ptr_N_signed_positive_explicit_check_constant_step_no_inbonds(i8* %src, i8* %lower, i8* %upper, i16 %N) {
135 ; CHECK-LABEL: @ptr_N_signed_positive_explicit_check_constant_step_no_inbonds(
136 ; CHECK-NEXT:  entry:
137 ; CHECK-NEXT:    [[N_POS:%.*]] = icmp sge i16 [[N:%.*]], 0
138 ; CHECK-NEXT:    br i1 [[N_POS]], label [[ENTRY_1:%.*]], label [[TRAP_BB:%.*]]
139 ; CHECK:       entry.1:
140 ; CHECK-NEXT:    [[SRC_END:%.*]] = getelementptr i8, i8* [[SRC:%.*]], i16 [[N]]
141 ; CHECK-NEXT:    [[CMP_SRC_START:%.*]] = icmp ult i8* [[SRC]], [[LOWER:%.*]]
142 ; CHECK-NEXT:    [[CMP_SRC_END:%.*]] = icmp uge i8* [[SRC_END]], [[UPPER:%.*]]
143 ; CHECK-NEXT:    [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]]
144 ; CHECK-NEXT:    br i1 [[OR_PRECOND_0]], label [[TRAP_BB]], label [[STEP_CHECK:%.*]]
145 ; CHECK:       trap.bb:
146 ; CHECK-NEXT:    ret i4 2
147 ; CHECK:       step.check:
148 ; CHECK-NEXT:    [[STEP_ULT_N:%.*]] = icmp ult i16 1, [[N]]
149 ; CHECK-NEXT:    br i1 [[STEP_ULT_N]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]]
150 ; CHECK:       ptr.check:
151 ; CHECK-NEXT:    [[SRC_STEP:%.*]] = getelementptr i8, i8* [[SRC]], i16 1
152 ; CHECK-NEXT:    [[CMP_STEP_START:%.*]] = icmp ult i8* [[SRC_STEP]], [[LOWER]]
153 ; CHECK-NEXT:    [[CMP_STEP_END:%.*]] = icmp uge i8* [[SRC_STEP]], [[UPPER]]
154 ; CHECK-NEXT:    [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], [[CMP_STEP_END]]
155 ; CHECK-NEXT:    br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]]
156 ; CHECK:       exit:
157 ; CHECK-NEXT:    ret i4 3
160 entry:
161   %N.pos = icmp sge i16 %N, 0
162   br i1 %N.pos, label %entry.1, label %trap.bb
164 entry.1:
165   %src.end = getelementptr i8, i8* %src, i16 %N
166   %cmp.src.start = icmp ult i8* %src, %lower
167   %cmp.src.end = icmp uge i8* %src.end, %upper
168   %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end
169   br i1 %or.precond.0, label %trap.bb, label %step.check
171 trap.bb:
172   ret i4 2
174 step.check:
175   %step.ult.N = icmp ult i16 1, %N
176   br i1 %step.ult.N, label %ptr.check, label %exit
178 ptr.check:
179   %src.step = getelementptr i8, i8* %src, i16 1
180   %cmp.step.start = icmp ult i8* %src.step, %lower
181   %cmp.step.end = icmp uge i8* %src.step, %upper
182   %or.check = or i1 %cmp.step.start, %cmp.step.end
183   br i1 %or.check, label %trap.bb, label %exit
185 exit:
186   ret i4 3
189 define i4 @ptr_N_and_step_signed_positive_explicit_check_constant_step(i8* %src, i8* %lower, i8* %upper, i16 %N, i16 %step) {
190 ; CHECK-LABEL: @ptr_N_and_step_signed_positive_explicit_check_constant_step(
191 ; CHECK-NEXT:  entry:
192 ; CHECK-NEXT:    [[N_POS:%.*]] = icmp sge i16 [[N:%.*]], 0
193 ; CHECK-NEXT:    [[STEP_POS:%.*]] = icmp sge i16 [[STEP:%.*]], 0
194 ; CHECK-NEXT:    [[AND_1:%.*]] = and i1 [[N_POS]], [[STEP_POS]]
195 ; CHECK-NEXT:    br i1 [[AND_1]], label [[ENTRY_1:%.*]], label [[TRAP_BB:%.*]]
196 ; CHECK:       entry.1:
197 ; CHECK-NEXT:    [[SRC_END:%.*]] = getelementptr inbounds i8, i8* [[SRC:%.*]], i16 [[N]]
198 ; CHECK-NEXT:    [[CMP_SRC_START:%.*]] = icmp ult i8* [[SRC]], [[LOWER:%.*]]
199 ; CHECK-NEXT:    [[CMP_SRC_END:%.*]] = icmp uge i8* [[SRC_END]], [[UPPER:%.*]]
200 ; CHECK-NEXT:    [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]]
201 ; CHECK-NEXT:    br i1 [[OR_PRECOND_0]], label [[TRAP_BB]], label [[STEP_CHECK:%.*]]
202 ; CHECK:       trap.bb:
203 ; CHECK-NEXT:    ret i4 2
204 ; CHECK:       step.check:
205 ; CHECK-NEXT:    [[STEP_UGE_0:%.*]] = icmp uge i16 [[STEP]], 0
206 ; CHECK-NEXT:    [[STEP_ULT_N:%.*]] = icmp ult i16 [[STEP]], [[N]]
207 ; CHECK-NEXT:    [[AND_2:%.*]] = and i1 [[STEP_UGE_0]], [[STEP_ULT_N]]
208 ; CHECK-NEXT:    br i1 [[AND_2]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]]
209 ; CHECK:       ptr.check:
210 ; CHECK-NEXT:    [[SRC_STEP:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i16 1
211 ; CHECK-NEXT:    [[CMP_STEP_START:%.*]] = icmp ult i8* [[SRC_STEP]], [[LOWER]]
212 ; CHECK-NEXT:    [[CMP_STEP_END:%.*]] = icmp uge i8* [[SRC_STEP]], [[UPPER]]
213 ; CHECK-NEXT:    [[OR_CHECK:%.*]] = or i1 false, false
214 ; CHECK-NEXT:    br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]]
215 ; CHECK:       exit:
216 ; CHECK-NEXT:    ret i4 3
219 entry:
220   %N.pos = icmp sge i16 %N, 0
221   %step.pos = icmp sge i16 %step, 0
222   %and.1 = and i1 %N.pos, %step.pos
223   br i1 %and.1, label %entry.1, label %trap.bb
225 entry.1:
226   %src.end = getelementptr inbounds i8, i8* %src, i16 %N
227   %cmp.src.start = icmp ult i8* %src, %lower
228   %cmp.src.end = icmp uge i8* %src.end, %upper
229   %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end
230   br i1 %or.precond.0, label %trap.bb, label %step.check
232 trap.bb:
233   ret i4 2
235 step.check:
236   %step.uge.0 = icmp uge i16 %step, 0
237   %step.ult.N = icmp ult i16 %step, %N
238   %and.2 = and i1 %step.uge.0, %step.ult.N
239   br i1 %and.2, label %ptr.check, label %exit
241 ptr.check:
242   %src.step = getelementptr inbounds i8, i8* %src, i16 1
243   %cmp.step.start = icmp ult i8* %src.step, %lower
244   %cmp.step.end = icmp uge i8* %src.step, %upper
245   %or.check = or i1 %cmp.step.start, %cmp.step.end
246   br i1 %or.check, label %trap.bb, label %exit
248 exit:
249   ret i4 3
252 define i4 @ptr_N_and_step_signed_positive_unsigned_checks_only(i8* %src, i8* %lower, i8* %upper, i16 %N, i16 %step) {
253 ; CHECK-LABEL: @ptr_N_and_step_signed_positive_unsigned_checks_only(
254 ; CHECK-NEXT:  entry:
255 ; CHECK-NEXT:    [[SRC_END:%.*]] = getelementptr inbounds i8, i8* [[SRC:%.*]], i16 [[N:%.*]]
256 ; CHECK-NEXT:    [[NO_OVERFLOW:%.*]] = icmp ule i8* [[SRC]], [[SRC_END]]
257 ; CHECK-NEXT:    br i1 [[NO_OVERFLOW]], label [[ENTRY_1:%.*]], label [[TRAP_BB:%.*]]
258 ; CHECK:       entry.1:
259 ; CHECK-NEXT:    [[CMP_SRC_START:%.*]] = icmp ult i8* [[SRC]], [[LOWER:%.*]]
260 ; CHECK-NEXT:    [[CMP_SRC_END:%.*]] = icmp uge i8* [[SRC_END]], [[UPPER:%.*]]
261 ; CHECK-NEXT:    [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]]
262 ; CHECK-NEXT:    br i1 [[OR_PRECOND_0]], label [[TRAP_BB]], label [[STEP_CHECK:%.*]]
263 ; CHECK:       trap.bb:
264 ; CHECK-NEXT:    ret i4 2
265 ; CHECK:       step.check:
266 ; CHECK-NEXT:    [[STEP_UGE_0:%.*]] = icmp uge i16 [[STEP:%.*]], 0
267 ; CHECK-NEXT:    [[STEP_ULT_N:%.*]] = icmp ult i16 [[STEP]], [[N]]
268 ; CHECK-NEXT:    [[AND_2:%.*]] = and i1 [[STEP_UGE_0]], [[STEP_ULT_N]]
269 ; CHECK-NEXT:    br i1 [[AND_2]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]]
270 ; CHECK:       ptr.check:
271 ; CHECK-NEXT:    [[SRC_STEP:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i16 1
272 ; CHECK-NEXT:    [[CMP_STEP_START:%.*]] = icmp ult i8* [[SRC_STEP]], [[LOWER]]
273 ; CHECK-NEXT:    [[CMP_STEP_END:%.*]] = icmp uge i8* [[SRC_STEP]], [[UPPER]]
274 ; CHECK-NEXT:    [[OR_CHECK:%.*]] = or i1 false, false
275 ; CHECK-NEXT:    br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]]
276 ; CHECK:       exit:
277 ; CHECK-NEXT:    ret i4 3
279 entry:
280   %src.end = getelementptr inbounds i8, i8* %src, i16 %N
281   %no.overflow = icmp ule i8* %src, %src.end
282   br i1 %no.overflow, label %entry.1, label %trap.bb
284 entry.1:
285   %cmp.src.start = icmp ult i8* %src, %lower
286   %cmp.src.end = icmp uge i8* %src.end, %upper
287   %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end
288   br i1 %or.precond.0, label %trap.bb, label %step.check
290 trap.bb:
291   ret i4 2
293 step.check:
294   %step.uge.0 = icmp uge i16 %step, 0
295   %step.ult.N = icmp ult i16 %step, %N
296   %and.2 = and i1 %step.uge.0, %step.ult.N
297   br i1 %and.2, label %ptr.check, label %exit
299 ptr.check:
300   %src.step = getelementptr inbounds i8, i8* %src, i16 1
301   %cmp.step.start = icmp ult i8* %src.step, %lower
302   %cmp.step.end = icmp uge i8* %src.step, %upper
303   %or.check = or i1 %cmp.step.start, %cmp.step.end
304   br i1 %or.check, label %trap.bb, label %exit
306 exit:
307   ret i4 3
310 define i4 @ptr_N_signed_positive(i8* %src, i8* %lower, i8* %upper, i16 %N, i16 %step) {
311 ; CHECK-LABEL: @ptr_N_signed_positive(
312 ; CHECK-NEXT:  entry:
313 ; CHECK-NEXT:    [[SRC_END:%.*]] = getelementptr inbounds i8, i8* [[SRC:%.*]], i16 [[N:%.*]]
314 ; CHECK-NEXT:    [[CMP_SRC_START:%.*]] = icmp ult i8* [[SRC]], [[LOWER:%.*]]
315 ; CHECK-NEXT:    [[CMP_SRC_END:%.*]] = icmp uge i8* [[SRC_END]], [[UPPER:%.*]]
316 ; CHECK-NEXT:    [[N_NEG:%.*]] = icmp slt i16 [[N]], 0
317 ; CHECK-NEXT:    [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]]
318 ; CHECK-NEXT:    [[OR_PRECOND_1:%.*]] = or i1 [[OR_PRECOND_0]], [[N_NEG]]
319 ; CHECK-NEXT:    br i1 [[OR_PRECOND_1]], label [[TRAP_BB:%.*]], label [[STEP_CHECK:%.*]]
320 ; CHECK:       trap.bb:
321 ; CHECK-NEXT:    ret i4 2
322 ; CHECK:       step.check:
323 ; CHECK-NEXT:    [[STEP_POS:%.*]] = icmp uge i16 [[STEP:%.*]], 0
324 ; CHECK-NEXT:    [[STEP_ULT_N:%.*]] = icmp ult i16 [[STEP]], [[N]]
325 ; CHECK-NEXT:    [[AND_STEP:%.*]] = and i1 [[STEP_POS]], [[STEP_ULT_N]]
326 ; CHECK-NEXT:    br i1 [[AND_STEP]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]]
327 ; CHECK:       ptr.check:
328 ; CHECK-NEXT:    [[SRC_STEP:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i16 [[STEP]]
329 ; CHECK-NEXT:    [[CMP_STEP_START:%.*]] = icmp ult i8* [[SRC_STEP]], [[LOWER]]
330 ; CHECK-NEXT:    [[CMP_STEP_END:%.*]] = icmp uge i8* [[SRC_STEP]], [[UPPER]]
331 ; CHECK-NEXT:    [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], [[CMP_STEP_END]]
332 ; CHECK-NEXT:    br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]]
333 ; CHECK:       exit:
334 ; CHECK-NEXT:    ret i4 3
336 entry:
337   %src.end = getelementptr inbounds i8, i8* %src, i16 %N
338   %cmp.src.start = icmp ult i8* %src, %lower
339   %cmp.src.end = icmp uge i8* %src.end, %upper
340   %N.neg = icmp slt i16 %N, 0
341   %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end
342   %or.precond.1 = or i1 %or.precond.0, %N.neg
343   br i1 %or.precond.1, label %trap.bb, label %step.check
345 trap.bb:
346   ret i4 2
348 step.check:
349   %step.pos = icmp uge i16 %step, 0
350   %step.ult.N = icmp ult i16 %step, %N
351   %and.step = and i1 %step.pos, %step.ult.N
352   br i1 %and.step, label %ptr.check, label %exit
354 ptr.check:
355   %src.step = getelementptr inbounds i8, i8* %src, i16 %step
356   %cmp.step.start = icmp ult i8* %src.step, %lower
357   %cmp.step.end = icmp uge i8* %src.step, %upper
358   %or.check = or i1 %cmp.step.start, %cmp.step.end
359   br i1 %or.check, label %trap.bb, label %exit
361 exit:
362   ret i4 3
365 define i4 @ptr_N_could_be_negative(i8* %src, i8* %lower, i8* %upper, i16 %N, i16 %step) {
366 ; CHECK-LABEL: @ptr_N_could_be_negative(
367 ; CHECK-NEXT:  entry:
368 ; CHECK-NEXT:    [[SRC_END:%.*]] = getelementptr inbounds i8, i8* [[SRC:%.*]], i16 [[N:%.*]]
369 ; CHECK-NEXT:    [[CMP_SRC_START:%.*]] = icmp ult i8* [[SRC]], [[LOWER:%.*]]
370 ; CHECK-NEXT:    [[CMP_SRC_END:%.*]] = icmp uge i8* [[SRC_END]], [[UPPER:%.*]]
371 ; CHECK-NEXT:    [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]]
372 ; CHECK-NEXT:    br i1 [[OR_PRECOND_0]], label [[TRAP_BB:%.*]], label [[STEP_CHECK:%.*]]
373 ; CHECK:       trap.bb:
374 ; CHECK-NEXT:    ret i4 2
375 ; CHECK:       step.check:
376 ; CHECK-NEXT:    [[STEP_POS:%.*]] = icmp uge i16 [[STEP:%.*]], 0
377 ; CHECK-NEXT:    [[STEP_ULT_N:%.*]] = icmp ult i16 [[STEP]], [[N]]
378 ; CHECK-NEXT:    [[AND_STEP:%.*]] = and i1 [[STEP_POS]], [[STEP_ULT_N]]
379 ; CHECK-NEXT:    br i1 [[AND_STEP]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]]
380 ; CHECK:       ptr.check:
381 ; CHECK-NEXT:    [[SRC_STEP:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i16 [[STEP]]
382 ; CHECK-NEXT:    [[CMP_STEP_START:%.*]] = icmp ult i8* [[SRC_STEP]], [[LOWER]]
383 ; CHECK-NEXT:    [[CMP_STEP_END:%.*]] = icmp uge i8* [[SRC_STEP]], [[UPPER]]
384 ; CHECK-NEXT:    [[OR_CHECK:%.*]] = or i1 false, false
385 ; CHECK-NEXT:    br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]]
386 ; CHECK:       exit:
387 ; CHECK-NEXT:    ret i4 3
389 entry:
390   %src.end = getelementptr inbounds i8, i8* %src, i16 %N
391   %cmp.src.start = icmp ult i8* %src, %lower
392   %cmp.src.end = icmp uge i8* %src.end, %upper
393   %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end
394   br i1 %or.precond.0, label %trap.bb, label %step.check
396 trap.bb:
397   ret i4 2
399 step.check:
400   %step.pos = icmp uge i16 %step, 0
401   %step.ult.N = icmp ult i16 %step, %N
402   %and.step = and i1 %step.pos, %step.ult.N
403   br i1 %and.step, label %ptr.check, label %exit
405 ptr.check:
406   %src.step = getelementptr inbounds i8, i8* %src, i16 %step
407   %cmp.step.start = icmp ult i8* %src.step, %lower
408   %cmp.step.end = icmp uge i8* %src.step, %upper
409   %or.check = or i1 %cmp.step.start, %cmp.step.end
410   br i1 %or.check, label %trap.bb, label %exit
412 exit:
413   ret i4 3
416 define i4 @ptr_src_uge_end(i8* %src, i8* %lower, i8* %upper, i16 %N, i16 %step) {
417 ; CHECK-LABEL: @ptr_src_uge_end(
418 ; CHECK-NEXT:  entry:
419 ; CHECK-NEXT:    [[SRC_END:%.*]] = getelementptr inbounds i8, i8* [[SRC:%.*]], i16 [[N:%.*]]
420 ; CHECK-NEXT:    [[CMP_SRC_START:%.*]] = icmp ult i8* [[SRC]], [[LOWER:%.*]]
421 ; CHECK-NEXT:    [[CMP_SRC_END:%.*]] = icmp uge i8* [[SRC_END]], [[UPPER:%.*]]
422 ; CHECK-NEXT:    [[CMP_OVERFLOW:%.*]] = icmp ugt i8* [[SRC]], [[SRC_END]]
423 ; CHECK-NEXT:    [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]]
424 ; CHECK-NEXT:    [[OR_PRECOND_1:%.*]] = or i1 [[OR_PRECOND_0]], [[CMP_OVERFLOW]]
425 ; CHECK-NEXT:    br i1 [[OR_PRECOND_1]], label [[TRAP_BB:%.*]], label [[STEP_CHECK:%.*]]
426 ; CHECK:       trap.bb:
427 ; CHECK-NEXT:    ret i4 2
428 ; CHECK:       step.check:
429 ; CHECK-NEXT:    [[STEP_POS:%.*]] = icmp uge i16 [[STEP:%.*]], 0
430 ; CHECK-NEXT:    [[STEP_ULT_N:%.*]] = icmp ult i16 [[STEP]], [[N]]
431 ; CHECK-NEXT:    [[AND_STEP:%.*]] = and i1 [[STEP_POS]], [[STEP_ULT_N]]
432 ; CHECK-NEXT:    br i1 [[AND_STEP]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]]
433 ; CHECK:       ptr.check:
434 ; CHECK-NEXT:    [[SRC_STEP:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i16 [[STEP]]
435 ; CHECK-NEXT:    [[CMP_STEP_START:%.*]] = icmp ult i8* [[SRC_STEP]], [[LOWER]]
436 ; CHECK-NEXT:    [[CMP_STEP_END:%.*]] = icmp uge i8* [[SRC_STEP]], [[UPPER]]
437 ; CHECK-NEXT:    [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], [[CMP_STEP_END]]
438 ; CHECK-NEXT:    br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]]
439 ; CHECK:       exit:
440 ; CHECK-NEXT:    ret i4 3
442 entry:
443   %src.end = getelementptr inbounds i8, i8* %src, i16 %N
444   %cmp.src.start = icmp ult i8* %src, %lower
445   %cmp.src.end = icmp uge i8* %src.end, %upper
446   %cmp.overflow = icmp ugt i8* %src, %src.end
447   %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end
448   %or.precond.1 = or i1 %or.precond.0, %cmp.overflow
449   br i1 %or.precond.1, label %trap.bb, label %step.check
451 trap.bb:
452   ret i4 2
454 step.check:
455   %step.pos = icmp uge i16 %step, 0
456   %step.ult.N = icmp ult i16 %step, %N
457   %and.step = and i1 %step.pos, %step.ult.N
458   br i1 %and.step, label %ptr.check, label %exit
460 ptr.check:
461   %src.step = getelementptr inbounds i8, i8* %src, i16 %step
462   %cmp.step.start = icmp ult i8* %src.step, %lower
463   %cmp.step.end = icmp uge i8* %src.step, %upper
464   %or.check = or i1 %cmp.step.start, %cmp.step.end
465   br i1 %or.check, label %trap.bb, label %exit
467 exit:
468   ret i4 3
471 define i4 @inc_ptr_N_could_be_negative(i8* %src, i8* %lower, i8* %upper, i16 %N, i16 %step) {
472 ; CHECK-LABEL: @inc_ptr_N_could_be_negative(
473 ; CHECK-NEXT:  entry:
474 ; CHECK-NEXT:    [[SRC_END:%.*]] = getelementptr inbounds i8, i8* [[SRC:%.*]], i16 [[N:%.*]]
475 ; CHECK-NEXT:    [[CMP_SRC_START:%.*]] = icmp ult i8* [[SRC]], [[LOWER:%.*]]
476 ; CHECK-NEXT:    [[CMP_SRC_END:%.*]] = icmp uge i8* [[SRC_END]], [[UPPER:%.*]]
477 ; CHECK-NEXT:    [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]]
478 ; CHECK-NEXT:    br i1 [[OR_PRECOND_0]], label [[TRAP_BB:%.*]], label [[STEP_CHECK:%.*]]
479 ; CHECK:       trap.bb:
480 ; CHECK-NEXT:    ret i4 2
481 ; CHECK:       step.check:
482 ; CHECK-NEXT:    [[STEP_POS:%.*]] = icmp uge i16 [[STEP:%.*]], 0
483 ; CHECK-NEXT:    [[NEXT:%.*]] = add nuw nsw i16 [[STEP]], 2
484 ; CHECK-NEXT:    [[STEP_ULT_N:%.*]] = icmp ult i16 [[NEXT]], [[N]]
485 ; CHECK-NEXT:    [[AND_STEP:%.*]] = and i1 [[STEP_POS]], [[STEP_ULT_N]]
486 ; CHECK-NEXT:    br i1 [[AND_STEP]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]]
487 ; CHECK:       ptr.check:
488 ; CHECK-NEXT:    [[SRC_STEP:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i16 [[STEP]]
489 ; CHECK-NEXT:    [[CMP_STEP_START:%.*]] = icmp ult i8* [[SRC_STEP]], [[LOWER]]
490 ; CHECK-NEXT:    [[CMP_STEP_END:%.*]] = icmp uge i8* [[SRC_STEP]], [[UPPER]]
491 ; CHECK-NEXT:    [[OR_CHECK:%.*]] = or i1 false, false
492 ; CHECK-NEXT:    br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]]
493 ; CHECK:       exit:
494 ; CHECK-NEXT:    ret i4 3
496 entry:
497   %src.end = getelementptr inbounds i8, i8* %src, i16 %N
498   %cmp.src.start = icmp ult i8* %src, %lower
499   %cmp.src.end = icmp uge i8* %src.end, %upper
500   %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end
501   br i1 %or.precond.0, label %trap.bb, label %step.check
503 trap.bb:
504   ret i4 2
506 step.check:
507   %step.pos = icmp uge i16 %step, 0
508   %next = add nsw nuw i16 %step, 2
509   %step.ult.N = icmp ult i16 %next, %N
510   %and.step = and i1 %step.pos, %step.ult.N
511   br i1 %and.step, label %ptr.check, label %exit
513 ptr.check:
514   %src.step = getelementptr inbounds i8, i8* %src, i16 %step
515   %cmp.step.start = icmp ult i8* %src.step, %lower
516   %cmp.step.end = icmp uge i8* %src.step, %upper
517   %or.check = or i1 %cmp.step.start, %cmp.step.end
518   br i1 %or.check, label %trap.bb, label %exit
520 exit:
521   ret i4 3
524 define i4 @inc_ptr_src_uge_end(i8* %src, i8* %lower, i8* %upper, i16 %N, i16 %step) {
525 ; CHECK-LABEL: @inc_ptr_src_uge_end(
526 ; CHECK-NEXT:  entry:
527 ; CHECK-NEXT:    [[SRC_END:%.*]] = getelementptr inbounds i8, i8* [[SRC:%.*]], i16 [[N:%.*]]
528 ; CHECK-NEXT:    [[CMP_SRC_START:%.*]] = icmp ult i8* [[SRC]], [[LOWER:%.*]]
529 ; CHECK-NEXT:    [[CMP_SRC_END:%.*]] = icmp uge i8* [[SRC_END]], [[UPPER:%.*]]
530 ; CHECK-NEXT:    [[CMP_OVERFLOW:%.*]] = icmp ugt i8* [[SRC]], [[SRC_END]]
531 ; CHECK-NEXT:    [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]]
532 ; CHECK-NEXT:    [[OR_PRECOND_1:%.*]] = or i1 [[OR_PRECOND_0]], [[CMP_OVERFLOW]]
533 ; CHECK-NEXT:    br i1 [[OR_PRECOND_1]], label [[TRAP_BB:%.*]], label [[STEP_CHECK:%.*]]
534 ; CHECK:       trap.bb:
535 ; CHECK-NEXT:    ret i4 2
536 ; CHECK:       step.check:
537 ; CHECK-NEXT:    [[STEP_POS:%.*]] = icmp uge i16 [[STEP:%.*]], 0
538 ; CHECK-NEXT:    [[NEXT:%.*]] = add nuw nsw i16 [[STEP]], 2
539 ; CHECK-NEXT:    [[STEP_ULT_N:%.*]] = icmp ult i16 [[NEXT]], [[N]]
540 ; CHECK-NEXT:    [[AND_STEP:%.*]] = and i1 [[STEP_POS]], [[STEP_ULT_N]]
541 ; CHECK-NEXT:    br i1 [[AND_STEP]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]]
542 ; CHECK:       ptr.check:
543 ; CHECK-NEXT:    [[SRC_STEP:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i16 [[STEP]]
544 ; CHECK-NEXT:    [[CMP_STEP_START:%.*]] = icmp ult i8* [[SRC_STEP]], [[LOWER]]
545 ; CHECK-NEXT:    [[CMP_STEP_END:%.*]] = icmp uge i8* [[SRC_STEP]], [[UPPER]]
546 ; CHECK-NEXT:    [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], [[CMP_STEP_END]]
547 ; CHECK-NEXT:    br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]]
548 ; CHECK:       exit:
549 ; CHECK-NEXT:    ret i4 3
551 entry:
552   %src.end = getelementptr inbounds i8, i8* %src, i16 %N
553   %cmp.src.start = icmp ult i8* %src, %lower
554   %cmp.src.end = icmp uge i8* %src.end, %upper
555   %cmp.overflow = icmp ugt i8* %src, %src.end
556   %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end
557   %or.precond.1 = or i1 %or.precond.0, %cmp.overflow
558   br i1 %or.precond.1, label %trap.bb, label %step.check
560 trap.bb:
561   ret i4 2
563 step.check:
564   %step.pos = icmp uge i16 %step, 0
565   %next = add nsw nuw i16 %step, 2
566   %step.ult.N = icmp ult i16 %next, %N
567   %and.step = and i1 %step.pos, %step.ult.N
568   br i1 %and.step, label %ptr.check, label %exit
570 ptr.check:
571   %src.step = getelementptr inbounds i8, i8* %src, i16 %step
572   %cmp.step.start = icmp ult i8* %src.step, %lower
573   %cmp.step.end = icmp uge i8* %src.step, %upper
574   %or.check = or i1 %cmp.step.start, %cmp.step.end
575   br i1 %or.check, label %trap.bb, label %exit
577 exit:
578   ret i4 3
581 define i4 @inc_ptr_src_uge_end_no_nsw_add(i8* %src, i8* %lower, i8* %upper, i16 %idx, i16 %N, i16 %step) {
582 ; CHECK-LABEL: @inc_ptr_src_uge_end_no_nsw_add(
583 ; CHECK-NEXT:  entry.1:
584 ; CHECK-NEXT:    [[IDX_POS:%.*]] = icmp sge i16 [[IDX:%.*]], 0
585 ; CHECK-NEXT:    br i1 [[IDX_POS]], label [[ENTRY:%.*]], label [[TRAP_BB:%.*]]
586 ; CHECK:       entry:
587 ; CHECK-NEXT:    [[SRC_IDX:%.*]] = getelementptr inbounds i8, i8* [[SRC:%.*]], i16 [[IDX]]
588 ; CHECK-NEXT:    [[CMP_SRC_START:%.*]] = icmp ult i8* [[SRC_IDX]], [[LOWER:%.*]]
589 ; CHECK-NEXT:    br i1 [[CMP_SRC_START]], label [[TRAP_BB]], label [[STEP_CHECK:%.*]]
590 ; CHECK:       trap.bb:
591 ; CHECK-NEXT:    ret i4 2
592 ; CHECK:       step.check:
593 ; CHECK-NEXT:    [[NEXT:%.*]] = add i16 [[IDX]], 2
594 ; CHECK-NEXT:    [[SRC_STEP:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i16 [[NEXT]]
595 ; CHECK-NEXT:    [[CMP_STEP_START:%.*]] = icmp ult i8* [[SRC_STEP]], [[LOWER]]
596 ; CHECK-NEXT:    [[CMP_STEP_END:%.*]] = icmp uge i8* [[SRC_STEP]], [[UPPER:%.*]]
597 ; CHECK-NEXT:    [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], [[CMP_STEP_END]]
598 ; CHECK-NEXT:    br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT:%.*]]
599 ; CHECK:       exit:
600 ; CHECK-NEXT:    ret i4 3
602 entry.1:
603   %idx.pos = icmp sge i16 %idx, 0
604   br i1 %idx.pos, label %entry, label %trap.bb
606 entry:
607   %src.idx = getelementptr inbounds i8, i8* %src, i16 %idx
608   %cmp.src.start = icmp ult i8* %src.idx, %lower
609   br i1 %cmp.src.start, label %trap.bb, label %step.check
611 trap.bb:
612   ret i4 2
614 step.check:
615   %next = add i16 %idx, 2
616   %src.step = getelementptr inbounds i8, i8* %src, i16 %next
617   %cmp.step.start = icmp ult i8* %src.step, %lower
618   %cmp.step.end = icmp uge i8* %src.step, %upper
619   %or.check = or i1 %cmp.step.start, %cmp.step.end
620   br i1 %or.check, label %trap.bb, label %exit
622 exit:
623   ret i4 3
626 define i4 @inc_ptr_src_uge_end_no_nsw_add_sge_0(i8* %src, i8* %lower, i8* %upper, i16 %idx, i16 %N, i16 %step) {
627 ; CHECK-LABEL: @inc_ptr_src_uge_end_no_nsw_add_sge_0(
628 ; CHECK-NEXT:  entry.1:
629 ; CHECK-NEXT:    [[IDX_POS:%.*]] = icmp sge i16 [[IDX:%.*]], 0
630 ; CHECK-NEXT:    br i1 [[IDX_POS]], label [[ENTRY:%.*]], label [[TRAP_BB:%.*]]
631 ; CHECK:       entry:
632 ; CHECK-NEXT:    [[SRC_IDX:%.*]] = getelementptr inbounds i8, i8* [[SRC:%.*]], i16 [[IDX]]
633 ; CHECK-NEXT:    [[CMP_SRC_START:%.*]] = icmp ult i8* [[SRC_IDX]], [[LOWER:%.*]]
634 ; CHECK-NEXT:    br i1 [[CMP_SRC_START]], label [[TRAP_BB]], label [[STEP_CHECK:%.*]]
635 ; CHECK:       trap.bb:
636 ; CHECK-NEXT:    ret i4 2
637 ; CHECK:       step.check:
638 ; CHECK-NEXT:    [[NEXT:%.*]] = add i16 [[IDX]], 2
639 ; CHECK-NEXT:    [[SRC_STEP:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i16 [[NEXT]]
640 ; CHECK-NEXT:    [[CMP_STEP_START:%.*]] = icmp ult i8* [[SRC_STEP]], [[LOWER]]
641 ; CHECK-NEXT:    [[CMP_STEP_END:%.*]] = icmp uge i8* [[SRC_STEP]], [[UPPER:%.*]]
642 ; CHECK-NEXT:    [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], [[CMP_STEP_END]]
643 ; CHECK-NEXT:    br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT:%.*]]
644 ; CHECK:       exit:
645 ; CHECK-NEXT:    ret i4 3
647 entry.1:
648   %idx.pos = icmp sge i16 %idx, 0
649   br i1 %idx.pos, label %entry, label %trap.bb
651 entry:
652   %src.idx = getelementptr inbounds i8, i8* %src, i16 %idx
653   %cmp.src.start = icmp ult i8* %src.idx, %lower
654   br i1 %cmp.src.start, label %trap.bb, label %step.check
656 trap.bb:
657   ret i4 2
659 step.check:
660   %next = add i16 %idx, 2
661   %src.step = getelementptr inbounds i8, i8* %src, i16 %next
662   %cmp.step.start = icmp ult i8* %src.step, %lower
663   %cmp.step.end = icmp uge i8* %src.step, %upper
664   %or.check = or i1 %cmp.step.start, %cmp.step.end
665   br i1 %or.check, label %trap.bb, label %exit
667 exit:
668   ret i4 3
674 ; N might be negative, meaning %src.end could be < %src! Cannot remove checks!
675 define i4 @ptr_N_unsigned_positive(i8* %src, i8* %lower, i8* %upper, i16 %N, i16 %step) {
676 ; CHECK-LABEL: @ptr_N_unsigned_positive(
677 ; CHECK-NEXT:  entry:
678 ; CHECK-NEXT:    [[SRC_END:%.*]] = getelementptr inbounds i8, i8* [[SRC:%.*]], i16 [[N:%.*]]
679 ; CHECK-NEXT:    [[CMP_SRC_START:%.*]] = icmp ult i8* [[SRC]], [[LOWER:%.*]]
680 ; CHECK-NEXT:    [[CMP_SRC_END:%.*]] = icmp uge i8* [[SRC_END]], [[UPPER:%.*]]
681 ; CHECK-NEXT:    [[N_NEG:%.*]] = icmp ult i16 [[N]], 0
682 ; CHECK-NEXT:    [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]]
683 ; CHECK-NEXT:    [[OR_PRECOND_1:%.*]] = or i1 [[OR_PRECOND_0]], [[N_NEG]]
684 ; CHECK-NEXT:    br i1 [[OR_PRECOND_1]], label [[TRAP_BB:%.*]], label [[STEP_CHECK:%.*]]
685 ; CHECK:       trap.bb:
686 ; CHECK-NEXT:    ret i4 2
687 ; CHECK:       step.check:
688 ; CHECK-NEXT:    [[STEP_POS:%.*]] = icmp uge i16 [[STEP:%.*]], 0
689 ; CHECK-NEXT:    [[STEP_ULT_N:%.*]] = icmp ult i16 [[STEP]], [[N]]
690 ; CHECK-NEXT:    [[AND_STEP:%.*]] = and i1 [[STEP_POS]], [[STEP_ULT_N]]
691 ; CHECK-NEXT:    br i1 [[AND_STEP]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]]
692 ; CHECK:       ptr.check:
693 ; CHECK-NEXT:    [[SRC_STEP:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i16 [[STEP]]
694 ; CHECK-NEXT:    [[CMP_STEP_START:%.*]] = icmp ult i8* [[SRC_STEP]], [[LOWER]]
695 ; CHECK-NEXT:    [[CMP_STEP_END:%.*]] = icmp uge i8* [[SRC_STEP]], [[UPPER]]
696 ; CHECK-NEXT:    [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], [[CMP_STEP_END]]
697 ; CHECK-NEXT:    br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]]
698 ; CHECK:       exit:
699 ; CHECK-NEXT:    ret i4 3
701 entry:
702   %src.end = getelementptr inbounds i8, i8* %src, i16 %N
703   %cmp.src.start = icmp ult i8* %src, %lower
704   %cmp.src.end = icmp uge i8* %src.end, %upper
705   %N.neg = icmp ult i16 %N, 0
706   %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end
707   %or.precond.1 = or i1 %or.precond.0, %N.neg
708   br i1 %or.precond.1, label %trap.bb, label %step.check
710 trap.bb:
711   ret i4 2
713 step.check:
714   %step.pos = icmp uge i16 %step, 0
715   %step.ult.N = icmp ult i16 %step, %N
716   %and.step = and i1 %step.pos, %step.ult.N
717   br i1 %and.step, label %ptr.check, label %exit
719 ptr.check:
720   %src.step = getelementptr inbounds i8, i8* %src, i16 %step
721   %cmp.step.start = icmp ult i8* %src.step, %lower
722   %cmp.step.end = icmp uge i8* %src.step, %upper
723   %or.check = or i1 %cmp.step.start, %cmp.step.end
724   br i1 %or.check, label %trap.bb, label %exit
726 exit:
727   ret i4 3
730 define i4 @ptr_N_signed_positive_assume(i8* %src, i8* %lower, i8* %upper, i16 %N, i16 %step) {
731 ; CHECK-LABEL: @ptr_N_signed_positive_assume(
732 ; CHECK-NEXT:  entry:
733 ; CHECK-NEXT:    [[SRC_END:%.*]] = getelementptr inbounds i8, i8* [[SRC:%.*]], i16 [[N:%.*]]
734 ; CHECK-NEXT:    [[CMP_SRC_START:%.*]] = icmp ult i8* [[SRC]], [[LOWER:%.*]]
735 ; CHECK-NEXT:    [[CMP_SRC_END:%.*]] = icmp uge i8* [[SRC_END]], [[UPPER:%.*]]
736 ; CHECK-NEXT:    [[N_NEG:%.*]] = icmp slt i16 [[N]], 0
737 ; CHECK-NEXT:    call void @llvm.assume(i1 [[N_NEG]])
738 ; CHECK-NEXT:    [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]]
739 ; CHECK-NEXT:    br i1 [[OR_PRECOND_0]], label [[TRAP_BB:%.*]], label [[STEP_CHECK:%.*]]
740 ; CHECK:       trap.bb:
741 ; CHECK-NEXT:    ret i4 2
742 ; CHECK:       step.check:
743 ; CHECK-NEXT:    [[STEP_POS:%.*]] = icmp uge i16 [[STEP:%.*]], 0
744 ; CHECK-NEXT:    [[STEP_ULT_N:%.*]] = icmp ult i16 [[STEP]], [[N]]
745 ; CHECK-NEXT:    [[AND_STEP:%.*]] = and i1 [[STEP_POS]], [[STEP_ULT_N]]
746 ; CHECK-NEXT:    br i1 [[AND_STEP]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]]
747 ; CHECK:       ptr.check:
748 ; CHECK-NEXT:    [[SRC_STEP:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i16 [[STEP]]
749 ; CHECK-NEXT:    [[CMP_STEP_START:%.*]] = icmp ult i8* [[SRC_STEP]], [[LOWER]]
750 ; CHECK-NEXT:    [[CMP_STEP_END:%.*]] = icmp uge i8* [[SRC_STEP]], [[UPPER]]
751 ; CHECK-NEXT:    [[OR_CHECK:%.*]] = or i1 false, false
752 ; CHECK-NEXT:    br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]]
753 ; CHECK:       exit:
754 ; CHECK-NEXT:    ret i4 3
756 entry:
757   %src.end = getelementptr inbounds i8, i8* %src, i16 %N
758   %cmp.src.start = icmp ult i8* %src, %lower
759   %cmp.src.end = icmp uge i8* %src.end, %upper
760   %N.neg = icmp slt i16 %N, 0
761   call void @llvm.assume(i1 %N.neg)
762   %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end
763   br i1 %or.precond.0, label %trap.bb, label %step.check
765 trap.bb:
766   ret i4 2
768 step.check:
769   %step.pos = icmp uge i16 %step, 0
770   %step.ult.N = icmp ult i16 %step, %N
771   %and.step = and i1 %step.pos, %step.ult.N
772   br i1 %and.step, label %ptr.check, label %exit
774 ptr.check:
775   %src.step = getelementptr inbounds i8, i8* %src, i16 %step
776   %cmp.step.start = icmp ult i8* %src.step, %lower
777   %cmp.step.end = icmp uge i8* %src.step, %upper
778   %or.check = or i1 %cmp.step.start, %cmp.step.end
779   br i1 %or.check, label %trap.bb, label %exit
781 exit:
782   ret i4 3
785 define i4 @ptr_N_step_zext_n_zext(i8* %src, i8* %lower, i8* %upper, i16 %N, i16 %step) {
786 ; CHECK-LABEL: @ptr_N_step_zext_n_zext(
787 ; CHECK-NEXT:  entry:
788 ; CHECK-NEXT:    [[N_ADD_1:%.*]] = add nuw nsw i16 [[N:%.*]], 1
789 ; CHECK-NEXT:    [[N_ADD_1_EXT:%.*]] = zext i16 [[N_ADD_1]] to i32
790 ; CHECK-NEXT:    [[SRC_END:%.*]] = getelementptr inbounds i8, i8* [[SRC:%.*]], i32 [[N_ADD_1_EXT]]
791 ; CHECK-NEXT:    [[CMP_SRC_START:%.*]] = icmp ult i8* [[SRC]], [[LOWER:%.*]]
792 ; CHECK-NEXT:    [[CMP_SRC_END:%.*]] = icmp uge i8* [[SRC_END]], [[UPPER:%.*]]
793 ; CHECK-NEXT:    [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]]
794 ; CHECK-NEXT:    br i1 [[OR_PRECOND_0]], label [[TRAP_BB:%.*]], label [[STEP_CHECK:%.*]]
795 ; CHECK:       trap.bb:
796 ; CHECK-NEXT:    ret i4 2
797 ; CHECK:       step.check:
798 ; CHECK-NEXT:    [[STEP_ADD_1:%.*]] = add nuw nsw i16 [[STEP:%.*]], 1
799 ; CHECK-NEXT:    [[STEP_ADD_1_EXT:%.*]] = zext i16 [[STEP_ADD_1]] to i32
800 ; CHECK-NEXT:    [[STEP_ULT_N:%.*]] = icmp ult i32 [[STEP_ADD_1_EXT]], [[N_ADD_1_EXT]]
801 ; CHECK-NEXT:    br i1 [[STEP_ULT_N]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]]
802 ; CHECK:       ptr.check:
803 ; CHECK-NEXT:    [[SRC_STEP:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i32 [[STEP_ADD_1_EXT]]
804 ; CHECK-NEXT:    [[CMP_STEP_START:%.*]] = icmp ult i8* [[SRC_STEP]], [[LOWER]]
805 ; CHECK-NEXT:    [[CMP_STEP_END:%.*]] = icmp uge i8* [[SRC_STEP]], [[UPPER]]
806 ; CHECK-NEXT:    [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], false
807 ; CHECK-NEXT:    br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]]
808 ; CHECK:       exit:
809 ; CHECK-NEXT:    ret i4 3
812 entry:
813   %N.add.1 = add nuw nsw i16 %N, 1
814   %N.add.1.ext = zext i16 %N.add.1 to i32
815   %src.end = getelementptr inbounds i8, i8* %src, i32 %N.add.1.ext
816   %cmp.src.start = icmp ult i8* %src, %lower
817   %cmp.src.end = icmp uge i8* %src.end, %upper
818   %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end
819   br i1 %or.precond.0, label %trap.bb, label %step.check
821 trap.bb:
822   ret i4 2
824 step.check:
825   %step.add.1 = add nuw nsw i16 %step, 1
826   %step.add.1.ext = zext i16 %step.add.1 to i32
827   %step.ult.N = icmp ult i32 %step.add.1.ext, %N.add.1.ext
828   br i1 %step.ult.N, label %ptr.check, label %exit
830 ptr.check:
831   %src.step = getelementptr inbounds i8, i8* %src, i32 %step.add.1.ext
832   %cmp.step.start = icmp ult i8* %src.step, %lower
833   %cmp.step.end = icmp uge i8* %src.step, %upper
834   %or.check = or i1 %cmp.step.start, %cmp.step.end
835   br i1 %or.check, label %trap.bb, label %exit
837 exit:
838   ret i4 3
841 define i4 @ptr_N_step_zext_n_zext_out_of_bounds(i8* %src, i8* %lower, i8* %upper, i16 %N, i16 %step) {
842 ; CHECK-LABEL: @ptr_N_step_zext_n_zext_out_of_bounds(
843 ; CHECK-NEXT:  entry:
844 ; CHECK-NEXT:    [[N_ADD_2:%.*]] = add nuw nsw i16 [[N:%.*]], 2
845 ; CHECK-NEXT:    [[N_ADD_2_EXT:%.*]] = zext i16 [[N_ADD_2]] to i32
846 ; CHECK-NEXT:    [[SRC_END:%.*]] = getelementptr inbounds i8, i8* [[SRC:%.*]], i32 [[N_ADD_2_EXT]]
847 ; CHECK-NEXT:    [[CMP_SRC_START:%.*]] = icmp ult i8* [[SRC]], [[LOWER:%.*]]
848 ; CHECK-NEXT:    [[CMP_SRC_END:%.*]] = icmp uge i8* [[SRC_END]], [[UPPER:%.*]]
849 ; CHECK-NEXT:    [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]]
850 ; CHECK-NEXT:    br i1 [[OR_PRECOND_0]], label [[TRAP_BB:%.*]], label [[STEP_CHECK:%.*]]
851 ; CHECK:       trap.bb:
852 ; CHECK-NEXT:    ret i4 2
853 ; CHECK:       step.check:
854 ; CHECK-NEXT:    [[STEP_ADD_2:%.*]] = add nuw nsw i16 [[STEP:%.*]], 2
855 ; CHECK-NEXT:    [[STEP_ADD_2_EXT:%.*]] = zext i16 [[STEP_ADD_2]] to i32
856 ; CHECK-NEXT:    [[STEP_EXT:%.*]] = zext i16 [[STEP]] to i32
857 ; CHECK-NEXT:    [[STEP_ULT_N:%.*]] = icmp ult i32 [[STEP_EXT]], [[N_ADD_2_EXT]]
858 ; CHECK-NEXT:    br i1 [[STEP_ULT_N]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]]
859 ; CHECK:       ptr.check:
860 ; CHECK-NEXT:    [[SRC_STEP:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i32 [[STEP_ADD_2_EXT]]
861 ; CHECK-NEXT:    [[CMP_STEP_START:%.*]] = icmp ult i8* [[SRC_STEP]], [[LOWER]]
862 ; CHECK-NEXT:    [[CMP_STEP_END:%.*]] = icmp uge i8* [[SRC_STEP]], [[UPPER]]
863 ; CHECK-NEXT:    [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], [[CMP_STEP_END]]
864 ; CHECK-NEXT:    br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]]
865 ; CHECK:       exit:
866 ; CHECK-NEXT:    ret i4 3
869 entry:
870   %N.add.2 = add nuw nsw i16 %N, 2
871   %N.add.2.ext = zext i16 %N.add.2 to i32
872   %src.end = getelementptr inbounds i8, i8* %src, i32 %N.add.2.ext
873   %cmp.src.start = icmp ult i8* %src, %lower
874   %cmp.src.end = icmp uge i8* %src.end, %upper
875   %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end
876   br i1 %or.precond.0, label %trap.bb, label %step.check
878 trap.bb:
879   ret i4 2
881 step.check:
882   %step.add.2 = add nuw nsw i16 %step, 2
883   %step.add.2.ext = zext i16 %step.add.2 to i32
884   %step.ext = zext i16 %step to i32
885   %step.ult.N = icmp ult i32 %step.ext, %N.add.2.ext
886   br i1 %step.ult.N, label %ptr.check, label %exit
888 ptr.check:
889   %src.step = getelementptr inbounds i8, i8* %src, i32 %step.add.2.ext
890   %cmp.step.start = icmp ult i8* %src.step, %lower
891   %cmp.step.end = icmp uge i8* %src.step, %upper
892   %or.check = or i1 %cmp.step.start, %cmp.step.end
893   br i1 %or.check, label %trap.bb, label %exit
895 exit:
896   ret i4 3