[SLP] Add cost model for `llvm.powi.*` intrinsics
[llvm-project.git] / llvm / test / Transforms / ConstraintElimination / gep-arithmetic.ll
blobc490f72e914f450bc514ca53fbb3562052c79a29
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s
4 declare void @llvm.assume(i1)
6 define i1 @gep_constant_positive_index(i8* %dst, i8* %lower, i8* %upper) {
7 ; CHECK-LABEL: @gep_constant_positive_index(
8 ; CHECK-NEXT:    [[DST_ADD_4:%.*]] = getelementptr inbounds i8, i8* [[DST:%.*]], i64 4
9 ; CHECK-NEXT:    [[PRE_DST_LOWER:%.*]] = icmp uge i8* [[DST]], [[LOWER:%.*]]
10 ; CHECK-NEXT:    [[PRE_DST_UPPER:%.*]] = icmp ult i8* [[DST_ADD_4]], [[UPPER:%.*]]
11 ; CHECK-NEXT:    [[AND:%.*]] = and i1 [[PRE_DST_LOWER]], [[PRE_DST_UPPER]]
12 ; CHECK-NEXT:    br i1 [[AND]], label [[THEN:%.*]], label [[ELSE:%.*]]
13 ; CHECK:       then:
14 ; CHECK-NEXT:    [[CMP_DST_LOWER:%.*]] = icmp uge i8* [[DST]], [[LOWER]]
15 ; CHECK-NEXT:    [[CMP_DST_UPPER:%.*]] = icmp ult i8* [[DST]], [[UPPER]]
16 ; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 true, true
17 ; CHECK-NEXT:    [[DST_ADD_3:%.*]] = getelementptr inbounds i8, i8* [[DST]], i64 3
18 ; CHECK-NEXT:    [[CMP_DST_ADD_3_LOWER:%.*]] = icmp uge i8* [[DST_ADD_3]], [[LOWER]]
19 ; CHECK-NEXT:    [[CMP_DST_ADD_3_UPPER:%.*]] = icmp ult i8* [[DST_ADD_3]], [[UPPER]]
20 ; CHECK-NEXT:    [[RES_2:%.*]] = xor i1 [[RES_1]], true
21 ; CHECK-NEXT:    [[RES_3:%.*]] = xor i1 [[RES_2]], true
22 ; CHECK-NEXT:    [[CMP_DST_ADD_4_LOWER:%.*]] = icmp uge i8* [[DST_ADD_4]], [[LOWER]]
23 ; CHECK-NEXT:    [[CMP_DST_ADD_4_UPPER:%.*]] = icmp ult i8* [[DST_ADD_4]], [[UPPER]]
24 ; CHECK-NEXT:    [[RES_4:%.*]] = xor i1 [[RES_3]], true
25 ; CHECK-NEXT:    [[RES_5:%.*]] = xor i1 [[RES_4]], true
26 ; CHECK-NEXT:    [[DST_ADD_5:%.*]] = getelementptr inbounds i8, i8* [[DST]], i64 5
27 ; CHECK-NEXT:    [[CMP_DST_ADD_5_LOWER:%.*]] = icmp uge i8* [[DST_ADD_5]], [[LOWER]]
28 ; CHECK-NEXT:    [[CMP_DST_ADD_5_UPPER:%.*]] = icmp ult i8* [[DST_ADD_5]], [[UPPER]]
29 ; CHECK-NEXT:    [[RES_6:%.*]] = xor i1 [[RES_5]], true
30 ; CHECK-NEXT:    [[RES_7:%.*]] = xor i1 [[RES_6]], [[CMP_DST_ADD_5_UPPER]]
31 ; CHECK-NEXT:    ret i1 [[RES_7]]
32 ; CHECK:       else:
33 ; CHECK-NEXT:    ret i1 false
35   %dst.add.4 = getelementptr inbounds i8, i8* %dst, i64 4
36   %pre.dst.lower = icmp uge i8* %dst, %lower
37   %pre.dst.upper = icmp ult i8* %dst.add.4, %upper
38   %and = and i1 %pre.dst.lower, %pre.dst.upper
39   br i1 %and, label %then, label %else
41 then:
42   %cmp.dst.lower = icmp uge i8* %dst, %lower
43   %cmp.dst.upper = icmp ult i8* %dst, %upper
44   %res.1 = xor i1 %cmp.dst.lower, %cmp.dst.upper
46   %dst.add.3 = getelementptr inbounds i8, i8* %dst, i64 3
47   %cmp.dst.add.3.lower = icmp uge i8* %dst.add.3, %lower
48   %cmp.dst.add.3.upper = icmp ult i8* %dst.add.3, %upper
49   %res.2 = xor i1 %res.1, %cmp.dst.add.3.lower
50   %res.3 = xor i1 %res.2, %cmp.dst.add.3.upper
52   %cmp.dst.add.4.lower = icmp uge i8* %dst.add.4, %lower
53   %cmp.dst.add.4.upper = icmp ult i8* %dst.add.4, %upper
54   %res.4 = xor i1 %res.3, %cmp.dst.add.4.lower
55   %res.5 = xor i1 %res.4, %cmp.dst.add.4.upper
57   %dst.add.5 = getelementptr inbounds i8, i8* %dst, i64 5
58   %cmp.dst.add.5.lower = icmp uge i8* %dst.add.5, %lower
59   %cmp.dst.add.5.upper = icmp ult i8* %dst.add.5, %upper
60   %res.6 = xor i1 %res.5, %cmp.dst.add.5.lower
61   %res.7 = xor i1 %res.6, %cmp.dst.add.5.upper
63   ret i1 %res.7
65 else:
66   ret i1 false
69 define i1 @gep_constant_negative_index(i8* %dst, i8* %lower, i8* %upper) {
70 ; CHECK-LABEL: @gep_constant_negative_index(
71 ; CHECK-NEXT:    [[DST_SUB_4:%.*]] = getelementptr inbounds i8, i8* [[DST:%.*]], i64 -4
72 ; CHECK-NEXT:    [[PRE_DST_LOWER:%.*]] = icmp uge i8* [[DST]], [[LOWER:%.*]]
73 ; CHECK-NEXT:    [[PRE_DST_UPPER:%.*]] = icmp ult i8* [[DST_SUB_4]], [[UPPER:%.*]]
74 ; CHECK-NEXT:    [[AND:%.*]] = and i1 [[PRE_DST_LOWER]], [[PRE_DST_UPPER]]
75 ; CHECK-NEXT:    br i1 [[AND]], label [[THEN:%.*]], label [[ELSE:%.*]]
76 ; CHECK:       then:
77 ; CHECK-NEXT:    [[CMP_DST_LOWER:%.*]] = icmp uge i8* [[DST]], [[LOWER]]
78 ; CHECK-NEXT:    [[CMP_DST_UPPER:%.*]] = icmp ult i8* [[DST]], [[UPPER]]
79 ; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 true, [[CMP_DST_UPPER]]
80 ; CHECK-NEXT:    [[DST_SUB_3:%.*]] = getelementptr inbounds i8, i8* [[DST]], i64 -3
81 ; CHECK-NEXT:    [[CMP_DST_SUB_3_LOWER:%.*]] = icmp uge i8* [[DST_SUB_3]], [[LOWER]]
82 ; CHECK-NEXT:    [[CMP_DST_SUB_3_UPPER:%.*]] = icmp ult i8* [[DST_SUB_3]], [[UPPER]]
83 ; CHECK-NEXT:    [[RES_2:%.*]] = xor i1 [[RES_1]], [[CMP_DST_SUB_3_LOWER]]
84 ; CHECK-NEXT:    [[RES_3:%.*]] = xor i1 [[RES_2]], [[CMP_DST_SUB_3_UPPER]]
85 ; CHECK-NEXT:    [[CMP_DST_SUB_4_LOWER:%.*]] = icmp uge i8* [[DST_SUB_4]], [[LOWER]]
86 ; CHECK-NEXT:    [[CMP_DST_SUB_4_UPPER:%.*]] = icmp ult i8* [[DST_SUB_4]], [[UPPER]]
87 ; CHECK-NEXT:    [[RES_4:%.*]] = xor i1 [[RES_3]], [[CMP_DST_SUB_4_LOWER]]
88 ; CHECK-NEXT:    [[RES_5:%.*]] = xor i1 [[RES_4]], [[CMP_DST_SUB_4_UPPER]]
89 ; CHECK-NEXT:    [[DST_SUB_5:%.*]] = getelementptr inbounds i8, i8* [[DST]], i64 -5
90 ; CHECK-NEXT:    [[CMP_DST_SUB_5_LOWER:%.*]] = icmp uge i8* [[DST_SUB_5]], [[LOWER]]
91 ; CHECK-NEXT:    [[CMP_DST_SUB_5_UPPER:%.*]] = icmp ult i8* [[DST_SUB_5]], [[UPPER]]
92 ; CHECK-NEXT:    [[RES_6:%.*]] = xor i1 [[RES_5]], [[CMP_DST_SUB_5_LOWER]]
93 ; CHECK-NEXT:    [[RES_7:%.*]] = xor i1 [[RES_6]], [[CMP_DST_SUB_5_UPPER]]
94 ; CHECK-NEXT:    ret i1 [[RES_7]]
95 ; CHECK:       else:
96 ; CHECK-NEXT:    [[ELSE_CMP_DST_LOWER:%.*]] = icmp uge i8* [[DST]], [[LOWER]]
97 ; CHECK-NEXT:    [[ELSE_CMP_DST_UPPER:%.*]] = icmp ult i8* [[DST]], [[UPPER]]
98 ; CHECK-NEXT:    [[ELSE_RES_1:%.*]] = xor i1 [[ELSE_CMP_DST_LOWER]], [[ELSE_CMP_DST_UPPER]]
99 ; CHECK-NEXT:    [[ELSE_DST_SUB_3:%.*]] = getelementptr inbounds i8, i8* [[DST]], i64 -3
100 ; CHECK-NEXT:    [[ELSE_CMP_DST_SUB_3_LOWER:%.*]] = icmp uge i8* [[ELSE_DST_SUB_3]], [[LOWER]]
101 ; CHECK-NEXT:    [[ELSE_CMP_DST_SUB_3_UPPER:%.*]] = icmp ult i8* [[ELSE_DST_SUB_3]], [[UPPER]]
102 ; CHECK-NEXT:    [[ELSE_RES_2:%.*]] = xor i1 [[ELSE_RES_1]], [[ELSE_CMP_DST_SUB_3_LOWER]]
103 ; CHECK-NEXT:    [[ELSE_RES_3:%.*]] = xor i1 [[ELSE_RES_2]], [[ELSE_CMP_DST_SUB_3_UPPER]]
104 ; CHECK-NEXT:    [[ELSE_CMP_DST_SUB_4_LOWER:%.*]] = icmp uge i8* [[DST_SUB_4]], [[LOWER]]
105 ; CHECK-NEXT:    [[ELSE_CMP_DST_SUB_4_UPPER:%.*]] = icmp ult i8* [[DST_SUB_4]], [[UPPER]]
106 ; CHECK-NEXT:    [[ELSE_RES_4:%.*]] = xor i1 [[ELSE_RES_3]], [[ELSE_CMP_DST_SUB_4_LOWER]]
107 ; CHECK-NEXT:    [[ELSE_RES_5:%.*]] = xor i1 [[ELSE_RES_4]], [[ELSE_CMP_DST_SUB_4_UPPER]]
108 ; CHECK-NEXT:    [[ELSE_DST_SUB_5:%.*]] = getelementptr inbounds i8, i8* [[DST]], i64 -5
109 ; CHECK-NEXT:    [[ELSE_CMP_DST_SUB_5_LOWER:%.*]] = icmp uge i8* [[ELSE_DST_SUB_5]], [[LOWER]]
110 ; CHECK-NEXT:    [[ELSE_CMP_DST_SUB_5_UPPER:%.*]] = icmp ult i8* [[ELSE_DST_SUB_5]], [[UPPER]]
111 ; CHECK-NEXT:    [[ELSE_RES_6:%.*]] = xor i1 [[ELSE_RES_5]], [[ELSE_CMP_DST_SUB_5_LOWER]]
112 ; CHECK-NEXT:    [[ELSE_RES_7:%.*]] = xor i1 [[ELSE_RES_6]], [[ELSE_CMP_DST_SUB_5_UPPER]]
113 ; CHECK-NEXT:    ret i1 [[ELSE_RES_7]]
115   %dst.sub.4 = getelementptr inbounds i8, i8* %dst, i64 -4
116   %pre.dst.lower = icmp uge i8* %dst, %lower
117   %pre.dst.upper = icmp ult i8* %dst.sub.4, %upper
118   %and = and i1 %pre.dst.lower, %pre.dst.upper
119   br i1 %and, label %then, label %else
121 then:
122   %cmp.dst.lower = icmp uge i8* %dst, %lower
123   %cmp.dst.upper = icmp ult i8* %dst, %upper
124   %res.1 = xor i1 %cmp.dst.lower, %cmp.dst.upper
126   %dst.sub.3 = getelementptr inbounds i8, i8* %dst, i64 -3
127   %cmp.dst.sub.3.lower = icmp uge i8* %dst.sub.3, %lower
128   %cmp.dst.sub.3.upper = icmp ult i8* %dst.sub.3, %upper
129   %res.2 = xor i1 %res.1, %cmp.dst.sub.3.lower
130   %res.3 = xor i1 %res.2, %cmp.dst.sub.3.upper
132   %cmp.dst.sub.4.lower = icmp uge i8* %dst.sub.4, %lower
133   %cmp.dst.sub.4.upper = icmp ult i8* %dst.sub.4, %upper
134   %res.4 = xor i1 %res.3, %cmp.dst.sub.4.lower
135   %res.5 = xor i1 %res.4, %cmp.dst.sub.4.upper
137   %dst.sub.5 = getelementptr inbounds i8, i8* %dst, i64 -5
138   %cmp.dst.sub.5.lower = icmp uge i8* %dst.sub.5, %lower
139   %cmp.dst.sub.5.upper = icmp ult i8* %dst.sub.5, %upper
140   %res.6 = xor i1 %res.5, %cmp.dst.sub.5.lower
141   %res.7 = xor i1 %res.6, %cmp.dst.sub.5.upper
143   ret i1 %res.7
145 else:
146   %else.cmp.dst.lower = icmp uge i8* %dst, %lower
147   %else.cmp.dst.upper = icmp ult i8* %dst, %upper
148   %else.res.1 = xor i1 %else.cmp.dst.lower, %else.cmp.dst.upper
150   %else.dst.sub.3 = getelementptr inbounds i8, i8* %dst, i64 -3
151   %else.cmp.dst.sub.3.lower = icmp uge i8* %else.dst.sub.3, %lower
152   %else.cmp.dst.sub.3.upper = icmp ult i8* %else.dst.sub.3, %upper
153   %else.res.2 = xor i1 %else.res.1, %else.cmp.dst.sub.3.lower
154   %else.res.3 = xor i1 %else.res.2, %else.cmp.dst.sub.3.upper
156   %else.cmp.dst.sub.4.lower = icmp uge i8* %dst.sub.4, %lower
157   %else.cmp.dst.sub.4.upper = icmp ult i8* %dst.sub.4, %upper
158   %else.res.4 = xor i1 %else.res.3, %else.cmp.dst.sub.4.lower
159   %else.res.5 = xor i1 %else.res.4, %else.cmp.dst.sub.4.upper
161   %else.dst.sub.5 = getelementptr inbounds i8, i8* %dst, i64 -5
162   %else.cmp.dst.sub.5.lower = icmp uge i8* %else.dst.sub.5, %lower
163   %else.cmp.dst.sub.5.upper = icmp ult i8* %else.dst.sub.5, %upper
164   %else.res.6 = xor i1 %else.res.5, %else.cmp.dst.sub.5.lower
165   %else.res.7 = xor i1 %else.res.6, %else.cmp.dst.sub.5.upper
167   ret i1 %else.res.7
170 define i1 @n_unknown(i32* %dst, i32 %n, i32 %i) {
171 ; CHECK-LABEL: @n_unknown(
172 ; CHECK-NEXT:  entry:
173 ; CHECK-NEXT:    [[SUB:%.*]] = add i32 [[N:%.*]], -1
174 ; CHECK-NEXT:    [[IDXPROM:%.*]] = zext i32 [[SUB]] to i64
175 ; CHECK-NEXT:    [[PTR_N_SUB_1:%.*]] = getelementptr i32, i32* [[DST:%.*]], i64 [[IDXPROM]]
176 ; CHECK-NEXT:    [[CMP_PTR_DST:%.*]] = icmp uge i32* [[PTR_N_SUB_1]], [[DST]]
177 ; CHECK-NEXT:    br i1 [[CMP_PTR_DST]], label [[PRE_BB_2:%.*]], label [[EXIT:%.*]]
178 ; CHECK:       exit:
179 ; CHECK-NEXT:    ret i1 false
180 ; CHECK:       pre.bb.2:
181 ; CHECK-NEXT:    [[PRE_2:%.*]] = icmp uge i32 [[I:%.*]], 0
182 ; CHECK-NEXT:    br i1 [[PRE_2]], label [[TGT_BB:%.*]], label [[EXIT]]
183 ; CHECK:       tgt.bb:
184 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i32 [[I]], [[N]]
185 ; CHECK-NEXT:    ret i1 [[CMP1]]
187 entry:
188   %sub = add i32 %n, -1
189   %idxprom = zext i32 %sub to i64
190   %ptr.n.sub.1 = getelementptr i32, i32* %dst, i64 %idxprom
191   %cmp.ptr.dst = icmp uge i32* %ptr.n.sub.1, %dst
192   br i1 %cmp.ptr.dst, label %pre.bb.2, label %exit
194 exit:
195   ret i1 false
197 pre.bb.2:
198   %pre.2 = icmp uge i32 %i, 0
199   br i1 %pre.2, label %tgt.bb, label %exit
201 tgt.bb:
202   %cmp1 = icmp ult i32 %i, %n
203   ret i1 %cmp1
206 define i1 @n_known_zero_due_to_nuw(i32* %dst, i32 %n, i32 %i) {
207 ; CHECK-LABEL: @n_known_zero_due_to_nuw(
208 ; CHECK-NEXT:  entry:
209 ; CHECK-NEXT:    [[SUB:%.*]] = add i32 [[N:%.*]], -1
210 ; CHECK-NEXT:    [[IDXPROM:%.*]] = zext i32 [[SUB]] to i64
211 ; CHECK-NEXT:    [[PTR_N_SUB_1:%.*]] = getelementptr i32, i32* [[DST:%.*]], i64 [[IDXPROM]]
212 ; CHECK-NEXT:    [[CMP_PTR_DST:%.*]] = icmp uge i32* [[PTR_N_SUB_1]], [[DST]]
213 ; CHECK-NEXT:    br i1 [[CMP_PTR_DST]], label [[PRE_BB_2:%.*]], label [[EXIT:%.*]]
214 ; CHECK:       exit:
215 ; CHECK-NEXT:    ret i1 false
216 ; CHECK:       pre.bb.2:
217 ; CHECK-NEXT:    [[PRE_2:%.*]] = icmp uge i32 [[I:%.*]], 0
218 ; CHECK-NEXT:    br i1 [[PRE_2]], label [[TGT_BB:%.*]], label [[EXIT]]
219 ; CHECK:       tgt.bb:
220 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i32 [[I]], [[N]]
221 ; CHECK-NEXT:    ret i1 [[CMP1]]
223 entry:
224   %sub = add i32 %n, -1
225   %idxprom = zext i32 %sub to i64
226   %ptr.n.sub.1 = getelementptr i32, i32* %dst, i64 %idxprom
227   %cmp.ptr.dst = icmp uge i32* %ptr.n.sub.1, %dst
228   br i1 %cmp.ptr.dst, label %pre.bb.2, label %exit
230 exit:
231   ret i1 false
233 pre.bb.2:
234   %pre.2 = icmp uge i32 %i, 0
235   br i1 %pre.2, label %tgt.bb, label %exit
237 tgt.bb:
238   %cmp1 = icmp ult i32 %i, %n
239   ret i1 %cmp1
242 define i4 @ptr_N_signed_positive_explicit_check_constant_step(i8* %src, i8* %lower, i8* %upper, i16 %N) {
243 ; CHECK-LABEL: @ptr_N_signed_positive_explicit_check_constant_step(
244 ; CHECK-NEXT:  entry:
245 ; CHECK-NEXT:    [[N_POS:%.*]] = icmp sge i16 [[N:%.*]], 0
246 ; CHECK-NEXT:    br i1 [[N_POS]], label [[ENTRY_1:%.*]], label [[TRAP_BB:%.*]]
247 ; CHECK:       entry.1:
248 ; CHECK-NEXT:    [[SRC_END:%.*]] = getelementptr inbounds i8, i8* [[SRC:%.*]], i16 [[N]]
249 ; CHECK-NEXT:    [[CMP_SRC_START:%.*]] = icmp ult i8* [[SRC]], [[LOWER:%.*]]
250 ; CHECK-NEXT:    [[CMP_SRC_END:%.*]] = icmp uge i8* [[SRC_END]], [[UPPER:%.*]]
251 ; CHECK-NEXT:    [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]]
252 ; CHECK-NEXT:    br i1 [[OR_PRECOND_0]], label [[TRAP_BB]], label [[STEP_CHECK:%.*]]
253 ; CHECK:       trap.bb:
254 ; CHECK-NEXT:    ret i4 2
255 ; CHECK:       step.check:
256 ; CHECK-NEXT:    [[STEP_ULT_N:%.*]] = icmp ult i16 1, [[N]]
257 ; CHECK-NEXT:    br i1 [[STEP_ULT_N]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]]
258 ; CHECK:       ptr.check:
259 ; CHECK-NEXT:    [[SRC_STEP:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i16 1
260 ; CHECK-NEXT:    [[CMP_STEP_START:%.*]] = icmp ult i8* [[SRC_STEP]], [[LOWER]]
261 ; CHECK-NEXT:    [[CMP_STEP_END:%.*]] = icmp uge i8* [[SRC_STEP]], [[UPPER]]
262 ; CHECK-NEXT:    [[OR_CHECK:%.*]] = or i1 false, false
263 ; CHECK-NEXT:    br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]]
264 ; CHECK:       exit:
265 ; CHECK-NEXT:    ret i4 3
268 entry:
269   %N.pos = icmp sge i16 %N, 0
270   br i1 %N.pos, label %entry.1, label %trap.bb
272 entry.1:
273   %src.end = getelementptr inbounds i8, i8* %src, i16 %N
274   %cmp.src.start = icmp ult i8* %src, %lower
275   %cmp.src.end = icmp uge i8* %src.end, %upper
276   %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end
277   br i1 %or.precond.0, label %trap.bb, label %step.check
279 trap.bb:
280   ret i4 2
282 step.check:
283   %step.ult.N = icmp ult i16 1, %N
284   br i1 %step.ult.N, label %ptr.check, label %exit
286 ptr.check:
287   %src.step = getelementptr inbounds i8, i8* %src, i16 1
288   %cmp.step.start = icmp ult i8* %src.step, %lower
289   %cmp.step.end = icmp uge i8* %src.step, %upper
290   %or.check = or i1 %cmp.step.start, %cmp.step.end
291   br i1 %or.check, label %trap.bb, label %exit
293 exit:
294   ret i4 3
297 ; Same as ptr_N_signed_positive_explicit_check_constant_step, but without inbounds.
298 define i4 @ptr_N_signed_positive_explicit_check_constant_step_no_inbonds(i8* %src, i8* %lower, i8* %upper, i16 %N) {
299 ; CHECK-LABEL: @ptr_N_signed_positive_explicit_check_constant_step_no_inbonds(
300 ; CHECK-NEXT:  entry:
301 ; CHECK-NEXT:    [[N_POS:%.*]] = icmp sge i16 [[N:%.*]], 0
302 ; CHECK-NEXT:    br i1 [[N_POS]], label [[ENTRY_1:%.*]], label [[TRAP_BB:%.*]]
303 ; CHECK:       entry.1:
304 ; CHECK-NEXT:    [[SRC_END:%.*]] = getelementptr i8, i8* [[SRC:%.*]], i16 [[N]]
305 ; CHECK-NEXT:    [[CMP_SRC_START:%.*]] = icmp ult i8* [[SRC]], [[LOWER:%.*]]
306 ; CHECK-NEXT:    [[CMP_SRC_END:%.*]] = icmp uge i8* [[SRC_END]], [[UPPER:%.*]]
307 ; CHECK-NEXT:    [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]]
308 ; CHECK-NEXT:    br i1 [[OR_PRECOND_0]], label [[TRAP_BB]], label [[STEP_CHECK:%.*]]
309 ; CHECK:       trap.bb:
310 ; CHECK-NEXT:    ret i4 2
311 ; CHECK:       step.check:
312 ; CHECK-NEXT:    [[STEP_ULT_N:%.*]] = icmp ult i16 1, [[N]]
313 ; CHECK-NEXT:    br i1 [[STEP_ULT_N]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]]
314 ; CHECK:       ptr.check:
315 ; CHECK-NEXT:    [[SRC_STEP:%.*]] = getelementptr i8, i8* [[SRC]], i16 1
316 ; CHECK-NEXT:    [[CMP_STEP_START:%.*]] = icmp ult i8* [[SRC_STEP]], [[LOWER]]
317 ; CHECK-NEXT:    [[CMP_STEP_END:%.*]] = icmp uge i8* [[SRC_STEP]], [[UPPER]]
318 ; CHECK-NEXT:    [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], [[CMP_STEP_END]]
319 ; CHECK-NEXT:    br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]]
320 ; CHECK:       exit:
321 ; CHECK-NEXT:    ret i4 3
324 entry:
325   %N.pos = icmp sge i16 %N, 0
326   br i1 %N.pos, label %entry.1, label %trap.bb
328 entry.1:
329   %src.end = getelementptr i8, i8* %src, i16 %N
330   %cmp.src.start = icmp ult i8* %src, %lower
331   %cmp.src.end = icmp uge i8* %src.end, %upper
332   %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end
333   br i1 %or.precond.0, label %trap.bb, label %step.check
335 trap.bb:
336   ret i4 2
338 step.check:
339   %step.ult.N = icmp ult i16 1, %N
340   br i1 %step.ult.N, label %ptr.check, label %exit
342 ptr.check:
343   %src.step = getelementptr i8, i8* %src, i16 1
344   %cmp.step.start = icmp ult i8* %src.step, %lower
345   %cmp.step.end = icmp uge i8* %src.step, %upper
346   %or.check = or i1 %cmp.step.start, %cmp.step.end
347   br i1 %or.check, label %trap.bb, label %exit
349 exit:
350   ret i4 3
353 define i4 @ptr_N_and_step_signed_positive_explicit_check_constant_step(i8* %src, i8* %lower, i8* %upper, i16 %N, i16 %step) {
354 ; CHECK-LABEL: @ptr_N_and_step_signed_positive_explicit_check_constant_step(
355 ; CHECK-NEXT:  entry:
356 ; CHECK-NEXT:    [[N_POS:%.*]] = icmp sge i16 [[N:%.*]], 0
357 ; CHECK-NEXT:    [[STEP_POS:%.*]] = icmp sge i16 [[STEP:%.*]], 0
358 ; CHECK-NEXT:    [[AND_1:%.*]] = and i1 [[N_POS]], [[STEP_POS]]
359 ; CHECK-NEXT:    br i1 [[AND_1]], label [[ENTRY_1:%.*]], label [[TRAP_BB:%.*]]
360 ; CHECK:       entry.1:
361 ; CHECK-NEXT:    [[SRC_END:%.*]] = getelementptr inbounds i8, i8* [[SRC:%.*]], i16 [[N]]
362 ; CHECK-NEXT:    [[CMP_SRC_START:%.*]] = icmp ult i8* [[SRC]], [[LOWER:%.*]]
363 ; CHECK-NEXT:    [[CMP_SRC_END:%.*]] = icmp uge i8* [[SRC_END]], [[UPPER:%.*]]
364 ; CHECK-NEXT:    [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]]
365 ; CHECK-NEXT:    br i1 [[OR_PRECOND_0]], label [[TRAP_BB]], label [[STEP_CHECK:%.*]]
366 ; CHECK:       trap.bb:
367 ; CHECK-NEXT:    ret i4 2
368 ; CHECK:       step.check:
369 ; CHECK-NEXT:    [[STEP_UGE_0:%.*]] = icmp uge i16 [[STEP]], 0
370 ; CHECK-NEXT:    [[STEP_ULT_N:%.*]] = icmp ult i16 [[STEP]], [[N]]
371 ; CHECK-NEXT:    [[AND_2:%.*]] = and i1 [[STEP_UGE_0]], [[STEP_ULT_N]]
372 ; CHECK-NEXT:    br i1 [[AND_2]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]]
373 ; CHECK:       ptr.check:
374 ; CHECK-NEXT:    [[SRC_STEP:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i16 1
375 ; CHECK-NEXT:    [[CMP_STEP_START:%.*]] = icmp ult i8* [[SRC_STEP]], [[LOWER]]
376 ; CHECK-NEXT:    [[CMP_STEP_END:%.*]] = icmp uge i8* [[SRC_STEP]], [[UPPER]]
377 ; CHECK-NEXT:    [[OR_CHECK:%.*]] = or i1 false, false
378 ; CHECK-NEXT:    br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]]
379 ; CHECK:       exit:
380 ; CHECK-NEXT:    ret i4 3
383 entry:
384   %N.pos = icmp sge i16 %N, 0
385   %step.pos = icmp sge i16 %step, 0
386   %and.1 = and i1 %N.pos, %step.pos
387   br i1 %and.1, label %entry.1, label %trap.bb
389 entry.1:
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.uge.0 = icmp uge i16 %step, 0
401   %step.ult.N = icmp ult i16 %step, %N
402   %and.2 = and i1 %step.uge.0, %step.ult.N
403   br i1 %and.2, label %ptr.check, label %exit
405 ptr.check:
406   %src.step = getelementptr inbounds i8, i8* %src, i16 1
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_N_and_step_signed_positive_unsigned_checks_only(i8* %src, i8* %lower, i8* %upper, i16 %N, i16 %step) {
417 ; CHECK-LABEL: @ptr_N_and_step_signed_positive_unsigned_checks_only(
418 ; CHECK-NEXT:  entry:
419 ; CHECK-NEXT:    [[SRC_END:%.*]] = getelementptr inbounds i8, i8* [[SRC:%.*]], i16 [[N:%.*]]
420 ; CHECK-NEXT:    [[NO_OVERFLOW:%.*]] = icmp ule i8* [[SRC]], [[SRC_END]]
421 ; CHECK-NEXT:    br i1 [[NO_OVERFLOW]], label [[ENTRY_1:%.*]], label [[TRAP_BB:%.*]]
422 ; CHECK:       entry.1:
423 ; CHECK-NEXT:    [[CMP_SRC_START:%.*]] = icmp ult i8* [[SRC]], [[LOWER:%.*]]
424 ; CHECK-NEXT:    [[CMP_SRC_END:%.*]] = icmp uge i8* [[SRC_END]], [[UPPER:%.*]]
425 ; CHECK-NEXT:    [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]]
426 ; CHECK-NEXT:    br i1 [[OR_PRECOND_0]], label [[TRAP_BB]], label [[STEP_CHECK:%.*]]
427 ; CHECK:       trap.bb:
428 ; CHECK-NEXT:    ret i4 2
429 ; CHECK:       step.check:
430 ; CHECK-NEXT:    [[STEP_UGE_0:%.*]] = icmp uge i16 [[STEP:%.*]], 0
431 ; CHECK-NEXT:    [[STEP_ULT_N:%.*]] = icmp ult i16 [[STEP]], [[N]]
432 ; CHECK-NEXT:    [[AND_2:%.*]] = and i1 [[STEP_UGE_0]], [[STEP_ULT_N]]
433 ; CHECK-NEXT:    br i1 [[AND_2]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]]
434 ; CHECK:       ptr.check:
435 ; CHECK-NEXT:    [[SRC_STEP:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i16 1
436 ; CHECK-NEXT:    [[CMP_STEP_START:%.*]] = icmp ult i8* [[SRC_STEP]], [[LOWER]]
437 ; CHECK-NEXT:    [[CMP_STEP_END:%.*]] = icmp uge i8* [[SRC_STEP]], [[UPPER]]
438 ; CHECK-NEXT:    [[OR_CHECK:%.*]] = or i1 false, [[CMP_STEP_END]]
439 ; CHECK-NEXT:    br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]]
440 ; CHECK:       exit:
441 ; CHECK-NEXT:    ret i4 3
443 entry:
444   %src.end = getelementptr inbounds i8, i8* %src, i16 %N
445   %no.overflow = icmp ule i8* %src, %src.end
446   br i1 %no.overflow, label %entry.1, label %trap.bb
448 entry.1:
449   %cmp.src.start = icmp ult i8* %src, %lower
450   %cmp.src.end = icmp uge i8* %src.end, %upper
451   %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end
452   br i1 %or.precond.0, label %trap.bb, label %step.check
454 trap.bb:
455   ret i4 2
457 step.check:
458   %step.uge.0 = icmp uge i16 %step, 0
459   %step.ult.N = icmp ult i16 %step, %N
460   %and.2 = and i1 %step.uge.0, %step.ult.N
461   br i1 %and.2, label %ptr.check, label %exit
463 ptr.check:
464   %src.step = getelementptr inbounds i8, i8* %src, i16 1
465   %cmp.step.start = icmp ult i8* %src.step, %lower
466   %cmp.step.end = icmp uge i8* %src.step, %upper
467   %or.check = or i1 %cmp.step.start, %cmp.step.end
468   br i1 %or.check, label %trap.bb, label %exit
470 exit:
471   ret i4 3
474 define i4 @ptr_N_signed_positive(i8* %src, i8* %lower, i8* %upper, i16 %N, i16 %step) {
475 ; CHECK-LABEL: @ptr_N_signed_positive(
476 ; CHECK-NEXT:  entry:
477 ; CHECK-NEXT:    [[SRC_END:%.*]] = getelementptr inbounds i8, i8* [[SRC:%.*]], i16 [[N:%.*]]
478 ; CHECK-NEXT:    [[CMP_SRC_START:%.*]] = icmp ult i8* [[SRC]], [[LOWER:%.*]]
479 ; CHECK-NEXT:    [[CMP_SRC_END:%.*]] = icmp uge i8* [[SRC_END]], [[UPPER:%.*]]
480 ; CHECK-NEXT:    [[N_NEG:%.*]] = icmp slt i16 [[N]], 0
481 ; CHECK-NEXT:    [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]]
482 ; CHECK-NEXT:    [[OR_PRECOND_1:%.*]] = or i1 [[OR_PRECOND_0]], [[N_NEG]]
483 ; CHECK-NEXT:    br i1 [[OR_PRECOND_1]], label [[TRAP_BB:%.*]], label [[STEP_CHECK:%.*]]
484 ; CHECK:       trap.bb:
485 ; CHECK-NEXT:    ret i4 2
486 ; CHECK:       step.check:
487 ; CHECK-NEXT:    [[STEP_POS:%.*]] = icmp uge i16 [[STEP:%.*]], 0
488 ; CHECK-NEXT:    [[STEP_ULT_N:%.*]] = icmp ult i16 [[STEP]], [[N]]
489 ; CHECK-NEXT:    [[AND_STEP:%.*]] = and i1 [[STEP_POS]], [[STEP_ULT_N]]
490 ; CHECK-NEXT:    br i1 [[AND_STEP]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]]
491 ; CHECK:       ptr.check:
492 ; CHECK-NEXT:    [[SRC_STEP:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i16 [[STEP]]
493 ; CHECK-NEXT:    [[CMP_STEP_START:%.*]] = icmp ult i8* [[SRC_STEP]], [[LOWER]]
494 ; CHECK-NEXT:    [[CMP_STEP_END:%.*]] = icmp uge i8* [[SRC_STEP]], [[UPPER]]
495 ; CHECK-NEXT:    [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], [[CMP_STEP_END]]
496 ; CHECK-NEXT:    br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]]
497 ; CHECK:       exit:
498 ; CHECK-NEXT:    ret i4 3
500 entry:
501   %src.end = getelementptr inbounds i8, i8* %src, i16 %N
502   %cmp.src.start = icmp ult i8* %src, %lower
503   %cmp.src.end = icmp uge i8* %src.end, %upper
504   %N.neg = icmp slt i16 %N, 0
505   %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end
506   %or.precond.1 = or i1 %or.precond.0, %N.neg
507   br i1 %or.precond.1, label %trap.bb, label %step.check
509 trap.bb:
510   ret i4 2
512 step.check:
513   %step.pos = icmp uge i16 %step, 0
514   %step.ult.N = icmp ult i16 %step, %N
515   %and.step = and i1 %step.pos, %step.ult.N
516   br i1 %and.step, label %ptr.check, label %exit
518 ptr.check:
519   %src.step = getelementptr inbounds i8, i8* %src, i16 %step
520   %cmp.step.start = icmp ult i8* %src.step, %lower
521   %cmp.step.end = icmp uge i8* %src.step, %upper
522   %or.check = or i1 %cmp.step.start, %cmp.step.end
523   br i1 %or.check, label %trap.bb, label %exit
525 exit:
526   ret i4 3
529 define i4 @ptr_N_could_be_negative(i8* %src, i8* %lower, i8* %upper, i8 %N, i8 %step) {
530 ; CHECK-LABEL: @ptr_N_could_be_negative(
531 ; CHECK-NEXT:  entry:
532 ; CHECK-NEXT:    [[SRC_END:%.*]] = getelementptr inbounds i8, i8* [[SRC:%.*]], i8 [[N:%.*]]
533 ; CHECK-NEXT:    [[CMP_SRC_START:%.*]] = icmp ult i8* [[SRC]], [[LOWER:%.*]]
534 ; CHECK-NEXT:    [[CMP_SRC_END:%.*]] = icmp uge i8* [[SRC_END]], [[UPPER:%.*]]
535 ; CHECK-NEXT:    [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]]
536 ; CHECK-NEXT:    br i1 [[OR_PRECOND_0]], label [[TRAP_BB:%.*]], label [[STEP_CHECK:%.*]]
537 ; CHECK:       trap.bb:
538 ; CHECK-NEXT:    ret i4 2
539 ; CHECK:       step.check:
540 ; CHECK-NEXT:    [[STEP_POS:%.*]] = icmp uge i8 [[STEP:%.*]], 0
541 ; CHECK-NEXT:    [[STEP_ULT_N:%.*]] = icmp ult i8 [[STEP]], [[N]]
542 ; CHECK-NEXT:    [[AND_STEP:%.*]] = and i1 [[STEP_POS]], [[STEP_ULT_N]]
543 ; CHECK-NEXT:    br i1 [[AND_STEP]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]]
544 ; CHECK:       ptr.check:
545 ; CHECK-NEXT:    [[SRC_STEP:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i8 [[STEP]]
546 ; CHECK-NEXT:    [[CMP_STEP_START:%.*]] = icmp ult i8* [[SRC_STEP]], [[LOWER]]
547 ; CHECK-NEXT:    [[CMP_STEP_END:%.*]] = icmp uge i8* [[SRC_STEP]], [[UPPER]]
548 ; CHECK-NEXT:    [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], [[CMP_STEP_END]]
549 ; CHECK-NEXT:    br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]]
550 ; CHECK:       exit:
551 ; CHECK-NEXT:    ret i4 3
553 entry:
554   %src.end = getelementptr inbounds i8, i8* %src, i8 %N
555   %cmp.src.start = icmp ult i8* %src, %lower
556   %cmp.src.end = icmp uge i8* %src.end, %upper
557   %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end
558   br i1 %or.precond.0, label %trap.bb, label %step.check
560 trap.bb:
561   ret i4 2
563 step.check:
564   %step.pos = icmp uge i8 %step, 0
565   %step.ult.N = icmp ult i8 %step, %N
566   %and.step = and i1 %step.pos, %step.ult.N
567   br i1 %and.step, label %ptr.check, label %exit
569 ptr.check:
570   %src.step = getelementptr inbounds i8, i8* %src, i8 %step
571   %cmp.step.start = icmp ult i8* %src.step, %lower
572   %cmp.step.end = icmp uge i8* %src.step, %upper
573   %or.check = or i1 %cmp.step.start, %cmp.step.end
574   br i1 %or.check, label %trap.bb, label %exit
576 exit:
577   ret i4 3
580 define i4 @ptr_src_uge_end(i8* %src, i8* %lower, i8* %upper, i8 %N, i8 %step) {
581 ; CHECK-LABEL: @ptr_src_uge_end(
582 ; CHECK-NEXT:  entry:
583 ; CHECK-NEXT:    [[SRC_END:%.*]] = getelementptr inbounds i8, i8* [[SRC:%.*]], i8 [[N:%.*]]
584 ; CHECK-NEXT:    [[CMP_SRC_START:%.*]] = icmp ult i8* [[SRC]], [[LOWER:%.*]]
585 ; CHECK-NEXT:    [[CMP_SRC_END:%.*]] = icmp uge i8* [[SRC_END]], [[UPPER:%.*]]
586 ; CHECK-NEXT:    [[CMP_OVERFLOW:%.*]] = icmp ugt i8* [[SRC]], [[SRC_END]]
587 ; CHECK-NEXT:    [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]]
588 ; CHECK-NEXT:    [[OR_PRECOND_1:%.*]] = or i1 [[OR_PRECOND_0]], [[CMP_OVERFLOW]]
589 ; CHECK-NEXT:    br i1 [[OR_PRECOND_1]], label [[TRAP_BB:%.*]], label [[STEP_CHECK:%.*]]
590 ; CHECK:       trap.bb:
591 ; CHECK-NEXT:    ret i4 2
592 ; CHECK:       step.check:
593 ; CHECK-NEXT:    [[STEP_POS:%.*]] = icmp uge i8 [[STEP:%.*]], 0
594 ; CHECK-NEXT:    [[STEP_ULT_N:%.*]] = icmp ult i8 [[STEP]], [[N]]
595 ; CHECK-NEXT:    [[AND_STEP:%.*]] = and i1 [[STEP_POS]], [[STEP_ULT_N]]
596 ; CHECK-NEXT:    br i1 [[AND_STEP]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]]
597 ; CHECK:       ptr.check:
598 ; CHECK-NEXT:    [[SRC_STEP:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i8 [[STEP]]
599 ; CHECK-NEXT:    [[CMP_STEP_START:%.*]] = icmp ult i8* [[SRC_STEP]], [[LOWER]]
600 ; CHECK-NEXT:    [[CMP_STEP_END:%.*]] = icmp uge i8* [[SRC_STEP]], [[UPPER]]
601 ; CHECK-NEXT:    [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], [[CMP_STEP_END]]
602 ; CHECK-NEXT:    br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]]
603 ; CHECK:       exit:
604 ; CHECK-NEXT:    ret i4 3
606 entry:
607   %src.end = getelementptr inbounds i8, i8* %src, i8 %N
608   %cmp.src.start = icmp ult i8* %src, %lower
609   %cmp.src.end = icmp uge i8* %src.end, %upper
610   %cmp.overflow = icmp ugt i8* %src, %src.end
611   %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end
612   %or.precond.1 = or i1 %or.precond.0, %cmp.overflow
613   br i1 %or.precond.1, label %trap.bb, label %step.check
615 trap.bb:
616   ret i4 2
618 step.check:
619   %step.pos = icmp uge i8 %step, 0
620   %step.ult.N = icmp ult i8 %step, %N
621   %and.step = and i1 %step.pos, %step.ult.N
622   br i1 %and.step, label %ptr.check, label %exit
624 ptr.check:
625   %src.step = getelementptr inbounds i8, i8* %src, i8 %step
626   %cmp.step.start = icmp ult i8* %src.step, %lower
627   %cmp.step.end = icmp uge i8* %src.step, %upper
628   %or.check = or i1 %cmp.step.start, %cmp.step.end
629   br i1 %or.check, label %trap.bb, label %exit
631 exit:
632   ret i4 3
635 define i4 @inc_ptr_N_could_be_negative(i8* %src, i8* %lower, i8* %upper, i8 %N, i8 %step) {
636 ; CHECK-LABEL: @inc_ptr_N_could_be_negative(
637 ; CHECK-NEXT:  entry:
638 ; CHECK-NEXT:    [[SRC_END:%.*]] = getelementptr inbounds i8, i8* [[SRC:%.*]], i8 [[N:%.*]]
639 ; CHECK-NEXT:    [[CMP_SRC_START:%.*]] = icmp ult i8* [[SRC]], [[LOWER:%.*]]
640 ; CHECK-NEXT:    [[CMP_SRC_END:%.*]] = icmp uge i8* [[SRC_END]], [[UPPER:%.*]]
641 ; CHECK-NEXT:    [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]]
642 ; CHECK-NEXT:    br i1 [[OR_PRECOND_0]], label [[TRAP_BB:%.*]], label [[STEP_CHECK:%.*]]
643 ; CHECK:       trap.bb:
644 ; CHECK-NEXT:    ret i4 2
645 ; CHECK:       step.check:
646 ; CHECK-NEXT:    [[STEP_POS:%.*]] = icmp uge i8 [[STEP:%.*]], 0
647 ; CHECK-NEXT:    [[NEXT:%.*]] = add nuw nsw i8 [[STEP]], 2
648 ; CHECK-NEXT:    [[STEP_ULT_N:%.*]] = icmp ult i8 [[NEXT]], [[N]]
649 ; CHECK-NEXT:    [[AND_STEP:%.*]] = and i1 [[STEP_POS]], [[STEP_ULT_N]]
650 ; CHECK-NEXT:    br i1 [[AND_STEP]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]]
651 ; CHECK:       ptr.check:
652 ; CHECK-NEXT:    [[SRC_STEP:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i8 [[STEP]]
653 ; CHECK-NEXT:    [[CMP_STEP_START:%.*]] = icmp ult i8* [[SRC_STEP]], [[LOWER]]
654 ; CHECK-NEXT:    [[CMP_STEP_END:%.*]] = icmp uge i8* [[SRC_STEP]], [[UPPER]]
655 ; CHECK-NEXT:    [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], [[CMP_STEP_END]]
656 ; CHECK-NEXT:    br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]]
657 ; CHECK:       exit:
658 ; CHECK-NEXT:    ret i4 3
660 entry:
661   %src.end = getelementptr inbounds i8, i8* %src, i8 %N
662   %cmp.src.start = icmp ult i8* %src, %lower
663   %cmp.src.end = icmp uge i8* %src.end, %upper
664   %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end
665   br i1 %or.precond.0, label %trap.bb, label %step.check
667 trap.bb:
668   ret i4 2
670 step.check:
671   %step.pos = icmp uge i8 %step, 0
672   %next = add nsw nuw i8 %step, 2
673   %step.ult.N = icmp ult i8 %next, %N
674   %and.step = and i1 %step.pos, %step.ult.N
675   br i1 %and.step, label %ptr.check, label %exit
677 ptr.check:
678   %src.step = getelementptr inbounds i8, i8* %src, i8 %step
679   %cmp.step.start = icmp ult i8* %src.step, %lower
680   %cmp.step.end = icmp uge i8* %src.step, %upper
681   %or.check = or i1 %cmp.step.start, %cmp.step.end
682   br i1 %or.check, label %trap.bb, label %exit
684 exit:
685   ret i4 3
688 define i4 @inc_ptr_src_uge_end(i8* %src, i8* %lower, i8* %upper, i16 %N, i16 %step) {
689 ; CHECK-LABEL: @inc_ptr_src_uge_end(
690 ; CHECK-NEXT:  entry:
691 ; CHECK-NEXT:    [[SRC_END:%.*]] = getelementptr inbounds i8, i8* [[SRC:%.*]], i16 [[N:%.*]]
692 ; CHECK-NEXT:    [[CMP_SRC_START:%.*]] = icmp ult i8* [[SRC]], [[LOWER:%.*]]
693 ; CHECK-NEXT:    [[CMP_SRC_END:%.*]] = icmp uge i8* [[SRC_END]], [[UPPER:%.*]]
694 ; CHECK-NEXT:    [[CMP_OVERFLOW:%.*]] = icmp ugt i8* [[SRC]], [[SRC_END]]
695 ; CHECK-NEXT:    [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]]
696 ; CHECK-NEXT:    [[OR_PRECOND_1:%.*]] = or i1 [[OR_PRECOND_0]], [[CMP_OVERFLOW]]
697 ; CHECK-NEXT:    br i1 [[OR_PRECOND_1]], label [[TRAP_BB:%.*]], label [[STEP_CHECK:%.*]]
698 ; CHECK:       trap.bb:
699 ; CHECK-NEXT:    ret i4 2
700 ; CHECK:       step.check:
701 ; CHECK-NEXT:    [[STEP_POS:%.*]] = icmp uge i16 [[STEP:%.*]], 0
702 ; CHECK-NEXT:    [[NEXT:%.*]] = add nuw nsw i16 [[STEP]], 2
703 ; CHECK-NEXT:    [[STEP_ULT_N:%.*]] = icmp ult i16 [[NEXT]], [[N]]
704 ; CHECK-NEXT:    [[AND_STEP:%.*]] = and i1 [[STEP_POS]], [[STEP_ULT_N]]
705 ; CHECK-NEXT:    br i1 [[AND_STEP]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]]
706 ; CHECK:       ptr.check:
707 ; CHECK-NEXT:    [[SRC_STEP:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i16 [[STEP]]
708 ; CHECK-NEXT:    [[CMP_STEP_START:%.*]] = icmp ult i8* [[SRC_STEP]], [[LOWER]]
709 ; CHECK-NEXT:    [[CMP_STEP_END:%.*]] = icmp uge i8* [[SRC_STEP]], [[UPPER]]
710 ; CHECK-NEXT:    [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], [[CMP_STEP_END]]
711 ; CHECK-NEXT:    br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]]
712 ; CHECK:       exit:
713 ; CHECK-NEXT:    ret i4 3
715 entry:
716   %src.end = getelementptr inbounds i8, i8* %src, i16 %N
717   %cmp.src.start = icmp ult i8* %src, %lower
718   %cmp.src.end = icmp uge i8* %src.end, %upper
719   %cmp.overflow = icmp ugt i8* %src, %src.end
720   %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end
721   %or.precond.1 = or i1 %or.precond.0, %cmp.overflow
722   br i1 %or.precond.1, label %trap.bb, label %step.check
724 trap.bb:
725   ret i4 2
727 step.check:
728   %step.pos = icmp uge i16 %step, 0
729   %next = add nsw nuw i16 %step, 2
730   %step.ult.N = icmp ult i16 %next, %N
731   %and.step = and i1 %step.pos, %step.ult.N
732   br i1 %and.step, label %ptr.check, label %exit
734 ptr.check:
735   %src.step = getelementptr inbounds i8, i8* %src, i16 %step
736   %cmp.step.start = icmp ult i8* %src.step, %lower
737   %cmp.step.end = icmp uge i8* %src.step, %upper
738   %or.check = or i1 %cmp.step.start, %cmp.step.end
739   br i1 %or.check, label %trap.bb, label %exit
741 exit:
742   ret i4 3
745 define i4 @inc_ptr_src_uge_end_no_nsw_add(i8* %src, i8* %lower, i8* %upper, i16 %idx, i16 %N, i16 %step) {
746 ; CHECK-LABEL: @inc_ptr_src_uge_end_no_nsw_add(
747 ; CHECK-NEXT:  entry.1:
748 ; CHECK-NEXT:    [[IDX_POS:%.*]] = icmp sge i16 [[IDX:%.*]], 0
749 ; CHECK-NEXT:    br i1 [[IDX_POS]], label [[ENTRY:%.*]], label [[TRAP_BB:%.*]]
750 ; CHECK:       entry:
751 ; CHECK-NEXT:    [[SRC_IDX:%.*]] = getelementptr inbounds i8, i8* [[SRC:%.*]], i16 [[IDX]]
752 ; CHECK-NEXT:    [[CMP_SRC_START:%.*]] = icmp ult i8* [[SRC_IDX]], [[LOWER:%.*]]
753 ; CHECK-NEXT:    br i1 [[CMP_SRC_START]], label [[TRAP_BB]], label [[STEP_CHECK:%.*]]
754 ; CHECK:       trap.bb:
755 ; CHECK-NEXT:    ret i4 2
756 ; CHECK:       step.check:
757 ; CHECK-NEXT:    [[NEXT:%.*]] = add i16 [[IDX]], 2
758 ; CHECK-NEXT:    [[SRC_STEP:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i16 [[NEXT]]
759 ; CHECK-NEXT:    [[CMP_STEP_START:%.*]] = icmp ult i8* [[SRC_STEP]], [[LOWER]]
760 ; CHECK-NEXT:    [[CMP_STEP_END:%.*]] = icmp uge i8* [[SRC_STEP]], [[UPPER:%.*]]
761 ; CHECK-NEXT:    [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], [[CMP_STEP_END]]
762 ; CHECK-NEXT:    br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT:%.*]]
763 ; CHECK:       exit:
764 ; CHECK-NEXT:    ret i4 3
766 entry.1:
767   %idx.pos = icmp sge i16 %idx, 0
768   br i1 %idx.pos, label %entry, label %trap.bb
770 entry:
771   %src.idx = getelementptr inbounds i8, i8* %src, i16 %idx
772   %cmp.src.start = icmp ult i8* %src.idx, %lower
773   br i1 %cmp.src.start, label %trap.bb, label %step.check
775 trap.bb:
776   ret i4 2
778 step.check:
779   %next = add i16 %idx, 2
780   %src.step = getelementptr inbounds i8, i8* %src, i16 %next
781   %cmp.step.start = icmp ult i8* %src.step, %lower
782   %cmp.step.end = icmp uge i8* %src.step, %upper
783   %or.check = or i1 %cmp.step.start, %cmp.step.end
784   br i1 %or.check, label %trap.bb, label %exit
786 exit:
787   ret i4 3
790 define i4 @inc_ptr_src_uge_end_no_nsw_add_sge_0(i8* %src, i8* %lower, i8* %upper, i16 %idx, i16 %N, i16 %step) {
791 ; CHECK-LABEL: @inc_ptr_src_uge_end_no_nsw_add_sge_0(
792 ; CHECK-NEXT:  entry.1:
793 ; CHECK-NEXT:    [[IDX_POS:%.*]] = icmp sge i16 [[IDX:%.*]], 0
794 ; CHECK-NEXT:    br i1 [[IDX_POS]], label [[ENTRY:%.*]], label [[TRAP_BB:%.*]]
795 ; CHECK:       entry:
796 ; CHECK-NEXT:    [[SRC_IDX:%.*]] = getelementptr inbounds i8, i8* [[SRC:%.*]], i16 [[IDX]]
797 ; CHECK-NEXT:    [[CMP_SRC_START:%.*]] = icmp ult i8* [[SRC_IDX]], [[LOWER:%.*]]
798 ; CHECK-NEXT:    br i1 [[CMP_SRC_START]], label [[TRAP_BB]], label [[STEP_CHECK:%.*]]
799 ; CHECK:       trap.bb:
800 ; CHECK-NEXT:    ret i4 2
801 ; CHECK:       step.check:
802 ; CHECK-NEXT:    [[NEXT:%.*]] = add i16 [[IDX]], 2
803 ; CHECK-NEXT:    [[SRC_STEP:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i16 [[NEXT]]
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]], [[CMP_STEP_END]]
807 ; CHECK-NEXT:    br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT:%.*]]
808 ; CHECK:       exit:
809 ; CHECK-NEXT:    ret i4 3
811 entry.1:
812   %idx.pos = icmp sge i16 %idx, 0
813   br i1 %idx.pos, label %entry, label %trap.bb
815 entry:
816   %src.idx = getelementptr inbounds i8, i8* %src, i16 %idx
817   %cmp.src.start = icmp ult i8* %src.idx, %lower
818   br i1 %cmp.src.start, label %trap.bb, label %step.check
820 trap.bb:
821   ret i4 2
823 step.check:
824   %next = add i16 %idx, 2
825   %src.step = getelementptr inbounds i8, i8* %src, i16 %next
826   %cmp.step.start = icmp ult i8* %src.step, %lower
827   %cmp.step.end = icmp uge i8* %src.step, %upper
828   %or.check = or i1 %cmp.step.start, %cmp.step.end
829   br i1 %or.check, label %trap.bb, label %exit
831 exit:
832   ret i4 3
838 ; N might be negative, meaning %src.end could be < %src! Cannot remove checks!
839 define i4 @ptr_N_unsigned_positive(i8* %src, i8* %lower, i8* %upper, i16 %N, i16 %step) {
840 ; CHECK-LABEL: @ptr_N_unsigned_positive(
841 ; CHECK-NEXT:  entry:
842 ; CHECK-NEXT:    [[SRC_END:%.*]] = getelementptr inbounds i8, i8* [[SRC:%.*]], i16 [[N:%.*]]
843 ; CHECK-NEXT:    [[CMP_SRC_START:%.*]] = icmp ult i8* [[SRC]], [[LOWER:%.*]]
844 ; CHECK-NEXT:    [[CMP_SRC_END:%.*]] = icmp uge i8* [[SRC_END]], [[UPPER:%.*]]
845 ; CHECK-NEXT:    [[N_NEG:%.*]] = icmp ult i16 [[N]], 0
846 ; CHECK-NEXT:    [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]]
847 ; CHECK-NEXT:    [[OR_PRECOND_1:%.*]] = or i1 [[OR_PRECOND_0]], [[N_NEG]]
848 ; CHECK-NEXT:    br i1 [[OR_PRECOND_1]], label [[TRAP_BB:%.*]], label [[STEP_CHECK:%.*]]
849 ; CHECK:       trap.bb:
850 ; CHECK-NEXT:    ret i4 2
851 ; CHECK:       step.check:
852 ; CHECK-NEXT:    [[STEP_POS:%.*]] = icmp uge i16 [[STEP:%.*]], 0
853 ; CHECK-NEXT:    [[STEP_ULT_N:%.*]] = icmp ult i16 [[STEP]], [[N]]
854 ; CHECK-NEXT:    [[AND_STEP:%.*]] = and i1 [[STEP_POS]], [[STEP_ULT_N]]
855 ; CHECK-NEXT:    br i1 [[AND_STEP]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]]
856 ; CHECK:       ptr.check:
857 ; CHECK-NEXT:    [[SRC_STEP:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i16 [[STEP]]
858 ; CHECK-NEXT:    [[CMP_STEP_START:%.*]] = icmp ult i8* [[SRC_STEP]], [[LOWER]]
859 ; CHECK-NEXT:    [[CMP_STEP_END:%.*]] = icmp uge i8* [[SRC_STEP]], [[UPPER]]
860 ; CHECK-NEXT:    [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], [[CMP_STEP_END]]
861 ; CHECK-NEXT:    br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]]
862 ; CHECK:       exit:
863 ; CHECK-NEXT:    ret i4 3
865 entry:
866   %src.end = getelementptr inbounds i8, i8* %src, i16 %N
867   %cmp.src.start = icmp ult i8* %src, %lower
868   %cmp.src.end = icmp uge i8* %src.end, %upper
869   %N.neg = icmp ult i16 %N, 0
870   %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end
871   %or.precond.1 = or i1 %or.precond.0, %N.neg
872   br i1 %or.precond.1, label %trap.bb, label %step.check
874 trap.bb:
875   ret i4 2
877 step.check:
878   %step.pos = icmp uge i16 %step, 0
879   %step.ult.N = icmp ult i16 %step, %N
880   %and.step = and i1 %step.pos, %step.ult.N
881   br i1 %and.step, label %ptr.check, label %exit
883 ptr.check:
884   %src.step = getelementptr inbounds i8, i8* %src, i16 %step
885   %cmp.step.start = icmp ult i8* %src.step, %lower
886   %cmp.step.end = icmp uge i8* %src.step, %upper
887   %or.check = or i1 %cmp.step.start, %cmp.step.end
888   br i1 %or.check, label %trap.bb, label %exit
890 exit:
891   ret i4 3
894 define i4 @ptr_N_signed_positive_assume(i8* %src, i8* %lower, i8* %upper, i16 %N, i16 %step) {
895 ; CHECK-LABEL: @ptr_N_signed_positive_assume(
896 ; CHECK-NEXT:  entry:
897 ; CHECK-NEXT:    [[SRC_END:%.*]] = getelementptr inbounds i8, i8* [[SRC:%.*]], i16 [[N:%.*]]
898 ; CHECK-NEXT:    [[CMP_SRC_START:%.*]] = icmp ult i8* [[SRC]], [[LOWER:%.*]]
899 ; CHECK-NEXT:    [[CMP_SRC_END:%.*]] = icmp uge i8* [[SRC_END]], [[UPPER:%.*]]
900 ; CHECK-NEXT:    [[N_NEG:%.*]] = icmp slt i16 [[N]], 0
901 ; CHECK-NEXT:    call void @llvm.assume(i1 [[N_NEG]])
902 ; CHECK-NEXT:    [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]]
903 ; CHECK-NEXT:    br i1 [[OR_PRECOND_0]], label [[TRAP_BB:%.*]], label [[STEP_CHECK:%.*]]
904 ; CHECK:       trap.bb:
905 ; CHECK-NEXT:    ret i4 2
906 ; CHECK:       step.check:
907 ; CHECK-NEXT:    [[STEP_POS:%.*]] = icmp uge i16 [[STEP:%.*]], 0
908 ; CHECK-NEXT:    [[STEP_ULT_N:%.*]] = icmp ult i16 [[STEP]], [[N]]
909 ; CHECK-NEXT:    [[AND_STEP:%.*]] = and i1 [[STEP_POS]], [[STEP_ULT_N]]
910 ; CHECK-NEXT:    br i1 [[AND_STEP]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]]
911 ; CHECK:       ptr.check:
912 ; CHECK-NEXT:    [[SRC_STEP:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i16 [[STEP]]
913 ; CHECK-NEXT:    [[CMP_STEP_START:%.*]] = icmp ult i8* [[SRC_STEP]], [[LOWER]]
914 ; CHECK-NEXT:    [[CMP_STEP_END:%.*]] = icmp uge i8* [[SRC_STEP]], [[UPPER]]
915 ; CHECK-NEXT:    [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], [[CMP_STEP_END]]
916 ; CHECK-NEXT:    br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]]
917 ; CHECK:       exit:
918 ; CHECK-NEXT:    ret i4 3
920 entry:
921   %src.end = getelementptr inbounds i8, i8* %src, i16 %N
922   %cmp.src.start = icmp ult i8* %src, %lower
923   %cmp.src.end = icmp uge i8* %src.end, %upper
924   %N.neg = icmp slt i16 %N, 0
925   call void @llvm.assume(i1 %N.neg)
926   %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end
927   br i1 %or.precond.0, label %trap.bb, label %step.check
929 trap.bb:
930   ret i4 2
932 step.check:
933   %step.pos = icmp uge i16 %step, 0
934   %step.ult.N = icmp ult i16 %step, %N
935   %and.step = and i1 %step.pos, %step.ult.N
936   br i1 %and.step, label %ptr.check, label %exit
938 ptr.check:
939   %src.step = getelementptr inbounds i8, i8* %src, i16 %step
940   %cmp.step.start = icmp ult i8* %src.step, %lower
941   %cmp.step.end = icmp uge i8* %src.step, %upper
942   %or.check = or i1 %cmp.step.start, %cmp.step.end
943   br i1 %or.check, label %trap.bb, label %exit
945 exit:
946   ret i4 3
949 define i4 @ptr_N_step_zext_n_zext(i8* %src, i8* %lower, i8* %upper, i16 %N, i16 %step) {
950 ; CHECK-LABEL: @ptr_N_step_zext_n_zext(
951 ; CHECK-NEXT:  entry:
952 ; CHECK-NEXT:    [[N_ADD_1:%.*]] = add nuw nsw i16 [[N:%.*]], 1
953 ; CHECK-NEXT:    [[N_ADD_1_EXT:%.*]] = zext i16 [[N_ADD_1]] to i32
954 ; CHECK-NEXT:    [[SRC_END:%.*]] = getelementptr inbounds i8, i8* [[SRC:%.*]], i32 [[N_ADD_1_EXT]]
955 ; CHECK-NEXT:    [[CMP_SRC_START:%.*]] = icmp ult i8* [[SRC]], [[LOWER:%.*]]
956 ; CHECK-NEXT:    [[CMP_SRC_END:%.*]] = icmp uge i8* [[SRC_END]], [[UPPER:%.*]]
957 ; CHECK-NEXT:    [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]]
958 ; CHECK-NEXT:    br i1 [[OR_PRECOND_0]], label [[TRAP_BB:%.*]], label [[STEP_CHECK:%.*]]
959 ; CHECK:       trap.bb:
960 ; CHECK-NEXT:    ret i4 2
961 ; CHECK:       step.check:
962 ; CHECK-NEXT:    [[STEP_ADD_1:%.*]] = add nuw nsw i16 [[STEP:%.*]], 1
963 ; CHECK-NEXT:    [[STEP_ADD_1_EXT:%.*]] = zext i16 [[STEP_ADD_1]] to i32
964 ; CHECK-NEXT:    [[STEP_ULT_N:%.*]] = icmp ult i32 [[STEP_ADD_1_EXT]], [[N_ADD_1_EXT]]
965 ; CHECK-NEXT:    br i1 [[STEP_ULT_N]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]]
966 ; CHECK:       ptr.check:
967 ; CHECK-NEXT:    [[SRC_STEP:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i32 [[STEP_ADD_1_EXT]]
968 ; CHECK-NEXT:    [[CMP_STEP_START:%.*]] = icmp ult i8* [[SRC_STEP]], [[LOWER]]
969 ; CHECK-NEXT:    [[CMP_STEP_END:%.*]] = icmp uge i8* [[SRC_STEP]], [[UPPER]]
970 ; CHECK-NEXT:    [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], false
971 ; CHECK-NEXT:    br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]]
972 ; CHECK:       exit:
973 ; CHECK-NEXT:    ret i4 3
976 entry:
977   %N.add.1 = add nuw nsw i16 %N, 1
978   %N.add.1.ext = zext i16 %N.add.1 to i32
979   %src.end = getelementptr inbounds i8, i8* %src, i32 %N.add.1.ext
980   %cmp.src.start = icmp ult i8* %src, %lower
981   %cmp.src.end = icmp uge i8* %src.end, %upper
982   %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end
983   br i1 %or.precond.0, label %trap.bb, label %step.check
985 trap.bb:
986   ret i4 2
988 step.check:
989   %step.add.1 = add nuw nsw i16 %step, 1
990   %step.add.1.ext = zext i16 %step.add.1 to i32
991   %step.ult.N = icmp ult i32 %step.add.1.ext, %N.add.1.ext
992   br i1 %step.ult.N, label %ptr.check, label %exit
994 ptr.check:
995   %src.step = getelementptr inbounds i8, i8* %src, i32 %step.add.1.ext
996   %cmp.step.start = icmp ult i8* %src.step, %lower
997   %cmp.step.end = icmp uge i8* %src.step, %upper
998   %or.check = or i1 %cmp.step.start, %cmp.step.end
999   br i1 %or.check, label %trap.bb, label %exit
1001 exit:
1002   ret i4 3
1005 define i4 @ptr_N_step_zext_n_zext_out_of_bounds(i8* %src, i8* %lower, i8* %upper, i16 %N, i16 %step) {
1006 ; CHECK-LABEL: @ptr_N_step_zext_n_zext_out_of_bounds(
1007 ; CHECK-NEXT:  entry:
1008 ; CHECK-NEXT:    [[N_ADD_2:%.*]] = add nuw nsw i16 [[N:%.*]], 2
1009 ; CHECK-NEXT:    [[N_ADD_2_EXT:%.*]] = zext i16 [[N_ADD_2]] to i32
1010 ; CHECK-NEXT:    [[SRC_END:%.*]] = getelementptr inbounds i8, i8* [[SRC:%.*]], i32 [[N_ADD_2_EXT]]
1011 ; CHECK-NEXT:    [[CMP_SRC_START:%.*]] = icmp ult i8* [[SRC]], [[LOWER:%.*]]
1012 ; CHECK-NEXT:    [[CMP_SRC_END:%.*]] = icmp uge i8* [[SRC_END]], [[UPPER:%.*]]
1013 ; CHECK-NEXT:    [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]]
1014 ; CHECK-NEXT:    br i1 [[OR_PRECOND_0]], label [[TRAP_BB:%.*]], label [[STEP_CHECK:%.*]]
1015 ; CHECK:       trap.bb:
1016 ; CHECK-NEXT:    ret i4 2
1017 ; CHECK:       step.check:
1018 ; CHECK-NEXT:    [[STEP_ADD_2:%.*]] = add nuw nsw i16 [[STEP:%.*]], 2
1019 ; CHECK-NEXT:    [[STEP_ADD_2_EXT:%.*]] = zext i16 [[STEP_ADD_2]] to i32
1020 ; CHECK-NEXT:    [[STEP_EXT:%.*]] = zext i16 [[STEP]] to i32
1021 ; CHECK-NEXT:    [[STEP_ULT_N:%.*]] = icmp ult i32 [[STEP_EXT]], [[N_ADD_2_EXT]]
1022 ; CHECK-NEXT:    br i1 [[STEP_ULT_N]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]]
1023 ; CHECK:       ptr.check:
1024 ; CHECK-NEXT:    [[SRC_STEP:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i32 [[STEP_ADD_2_EXT]]
1025 ; CHECK-NEXT:    [[CMP_STEP_START:%.*]] = icmp ult i8* [[SRC_STEP]], [[LOWER]]
1026 ; CHECK-NEXT:    [[CMP_STEP_END:%.*]] = icmp uge i8* [[SRC_STEP]], [[UPPER]]
1027 ; CHECK-NEXT:    [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], [[CMP_STEP_END]]
1028 ; CHECK-NEXT:    br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]]
1029 ; CHECK:       exit:
1030 ; CHECK-NEXT:    ret i4 3
1033 entry:
1034   %N.add.2 = add nuw nsw i16 %N, 2
1035   %N.add.2.ext = zext i16 %N.add.2 to i32
1036   %src.end = getelementptr inbounds i8, i8* %src, i32 %N.add.2.ext
1037   %cmp.src.start = icmp ult i8* %src, %lower
1038   %cmp.src.end = icmp uge i8* %src.end, %upper
1039   %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end
1040   br i1 %or.precond.0, label %trap.bb, label %step.check
1042 trap.bb:
1043   ret i4 2
1045 step.check:
1046   %step.add.2 = add nuw nsw i16 %step, 2
1047   %step.add.2.ext = zext i16 %step.add.2 to i32
1048   %step.ext = zext i16 %step to i32
1049   %step.ult.N = icmp ult i32 %step.ext, %N.add.2.ext
1050   br i1 %step.ult.N, label %ptr.check, label %exit
1052 ptr.check:
1053   %src.step = getelementptr inbounds i8, i8* %src, i32 %step.add.2.ext
1054   %cmp.step.start = icmp ult i8* %src.step, %lower
1055   %cmp.step.end = icmp uge i8* %src.step, %upper
1056   %or.check = or i1 %cmp.step.start, %cmp.step.end
1057   br i1 %or.check, label %trap.bb, label %exit
1059 exit:
1060   ret i4 3