Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / Transforms / ConstraintElimination / gep-arithmetic.ll
bloba4d825b327969c82cd5a94428ef603ab728491ae
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 noundef) #0
6 define i1 @gep_constant_positive_index(ptr %dst, ptr %lower, ptr %upper) {
7 ; CHECK-LABEL: @gep_constant_positive_index(
8 ; CHECK-NEXT:    [[DST_ADD_4:%.*]] = getelementptr inbounds i8, ptr [[DST:%.*]], i64 4
9 ; CHECK-NEXT:    [[PRE_DST_LOWER:%.*]] = icmp uge ptr [[DST]], [[LOWER:%.*]]
10 ; CHECK-NEXT:    [[PRE_DST_UPPER:%.*]] = icmp ult ptr [[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:    [[RES_1:%.*]] = xor i1 true, true
15 ; CHECK-NEXT:    [[DST_ADD_3:%.*]] = getelementptr inbounds i8, ptr [[DST]], i64 3
16 ; CHECK-NEXT:    [[RES_2:%.*]] = xor i1 [[RES_1]], true
17 ; CHECK-NEXT:    [[RES_3:%.*]] = xor i1 [[RES_2]], true
18 ; CHECK-NEXT:    [[RES_4:%.*]] = xor i1 [[RES_3]], true
19 ; CHECK-NEXT:    [[RES_5:%.*]] = xor i1 [[RES_4]], true
20 ; CHECK-NEXT:    [[DST_ADD_5:%.*]] = getelementptr inbounds i8, ptr [[DST]], i64 5
21 ; CHECK-NEXT:    [[CMP_DST_ADD_5_UPPER:%.*]] = icmp ult ptr [[DST_ADD_5]], [[UPPER]]
22 ; CHECK-NEXT:    [[RES_6:%.*]] = xor i1 [[RES_5]], true
23 ; CHECK-NEXT:    [[RES_7:%.*]] = xor i1 [[RES_6]], [[CMP_DST_ADD_5_UPPER]]
24 ; CHECK-NEXT:    ret i1 [[RES_7]]
25 ; CHECK:       else:
26 ; CHECK-NEXT:    ret i1 false
28   %dst.add.4 = getelementptr inbounds i8, ptr %dst, i64 4
29   %pre.dst.lower = icmp uge ptr %dst, %lower
30   %pre.dst.upper = icmp ult ptr %dst.add.4, %upper
31   %and = and i1 %pre.dst.lower, %pre.dst.upper
32   br i1 %and, label %then, label %else
34 then:
35   %cmp.dst.lower = icmp uge ptr %dst, %lower
36   %cmp.dst.upper = icmp ult ptr %dst, %upper
37   %res.1 = xor i1 %cmp.dst.lower, %cmp.dst.upper
38   %dst.add.3 = getelementptr inbounds i8, ptr %dst, i64 3
39   %cmp.dst.add.3.lower = icmp uge ptr %dst.add.3, %lower
40   %cmp.dst.add.3.upper = icmp ult ptr %dst.add.3, %upper
41   %res.2 = xor i1 %res.1, %cmp.dst.add.3.lower
42   %res.3 = xor i1 %res.2, %cmp.dst.add.3.upper
43   %cmp.dst.add.4.lower = icmp uge ptr %dst.add.4, %lower
44   %cmp.dst.add.4.upper = icmp ult ptr %dst.add.4, %upper
45   %res.4 = xor i1 %res.3, %cmp.dst.add.4.lower
46   %res.5 = xor i1 %res.4, %cmp.dst.add.4.upper
47   %dst.add.5 = getelementptr inbounds i8, ptr %dst, i64 5
48   %cmp.dst.add.5.lower = icmp uge ptr %dst.add.5, %lower
49   %cmp.dst.add.5.upper = icmp ult ptr %dst.add.5, %upper
50   %res.6 = xor i1 %res.5, %cmp.dst.add.5.lower
51   %res.7 = xor i1 %res.6, %cmp.dst.add.5.upper
52   ret i1 %res.7
54 else:
55   ret i1 false
58 define i1 @gep_constant_negative_index(ptr %dst, ptr %lower, ptr %upper) {
59 ; CHECK-LABEL: @gep_constant_negative_index(
60 ; CHECK-NEXT:    [[DST_SUB_4:%.*]] = getelementptr inbounds i8, ptr [[DST:%.*]], i64 -4
61 ; CHECK-NEXT:    [[PRE_DST_LOWER:%.*]] = icmp uge ptr [[DST]], [[LOWER:%.*]]
62 ; CHECK-NEXT:    [[PRE_DST_UPPER:%.*]] = icmp ult ptr [[DST_SUB_4]], [[UPPER:%.*]]
63 ; CHECK-NEXT:    [[AND:%.*]] = and i1 [[PRE_DST_LOWER]], [[PRE_DST_UPPER]]
64 ; CHECK-NEXT:    br i1 [[AND]], label [[THEN:%.*]], label [[ELSE:%.*]]
65 ; CHECK:       then:
66 ; CHECK-NEXT:    [[CMP_DST_UPPER:%.*]] = icmp ult ptr [[DST]], [[UPPER]]
67 ; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 true, [[CMP_DST_UPPER]]
68 ; CHECK-NEXT:    [[DST_SUB_3:%.*]] = getelementptr inbounds i8, ptr [[DST]], i64 -3
69 ; CHECK-NEXT:    [[CMP_DST_SUB_3_LOWER:%.*]] = icmp uge ptr [[DST_SUB_3]], [[LOWER]]
70 ; CHECK-NEXT:    [[CMP_DST_SUB_3_UPPER:%.*]] = icmp ult ptr [[DST_SUB_3]], [[UPPER]]
71 ; CHECK-NEXT:    [[RES_2:%.*]] = xor i1 [[RES_1]], [[CMP_DST_SUB_3_LOWER]]
72 ; CHECK-NEXT:    [[RES_3:%.*]] = xor i1 [[RES_2]], [[CMP_DST_SUB_3_UPPER]]
73 ; CHECK-NEXT:    [[CMP_DST_SUB_4_LOWER:%.*]] = icmp uge ptr [[DST_SUB_4]], [[LOWER]]
74 ; CHECK-NEXT:    [[RES_4:%.*]] = xor i1 [[RES_3]], [[CMP_DST_SUB_4_LOWER]]
75 ; CHECK-NEXT:    [[RES_5:%.*]] = xor i1 [[RES_4]], true
76 ; CHECK-NEXT:    [[DST_SUB_5:%.*]] = getelementptr inbounds i8, ptr [[DST]], i64 -5
77 ; CHECK-NEXT:    [[CMP_DST_SUB_5_LOWER:%.*]] = icmp uge ptr [[DST_SUB_5]], [[LOWER]]
78 ; CHECK-NEXT:    [[RES_6:%.*]] = xor i1 [[RES_5]], [[CMP_DST_SUB_5_LOWER]]
79 ; CHECK-NEXT:    [[RES_7:%.*]] = xor i1 [[RES_6]], true
80 ; CHECK-NEXT:    ret i1 [[RES_7]]
81 ; CHECK:       else:
82 ; CHECK-NEXT:    [[ELSE_CMP_DST_LOWER:%.*]] = icmp uge ptr [[DST]], [[LOWER]]
83 ; CHECK-NEXT:    [[ELSE_CMP_DST_UPPER:%.*]] = icmp ult ptr [[DST]], [[UPPER]]
84 ; CHECK-NEXT:    [[ELSE_RES_1:%.*]] = xor i1 [[ELSE_CMP_DST_LOWER]], [[ELSE_CMP_DST_UPPER]]
85 ; CHECK-NEXT:    [[ELSE_DST_SUB_3:%.*]] = getelementptr inbounds i8, ptr [[DST]], i64 -3
86 ; CHECK-NEXT:    [[ELSE_CMP_DST_SUB_3_LOWER:%.*]] = icmp uge ptr [[ELSE_DST_SUB_3]], [[LOWER]]
87 ; CHECK-NEXT:    [[ELSE_CMP_DST_SUB_3_UPPER:%.*]] = icmp ult ptr [[ELSE_DST_SUB_3]], [[UPPER]]
88 ; CHECK-NEXT:    [[ELSE_RES_2:%.*]] = xor i1 [[ELSE_RES_1]], [[ELSE_CMP_DST_SUB_3_LOWER]]
89 ; CHECK-NEXT:    [[ELSE_RES_3:%.*]] = xor i1 [[ELSE_RES_2]], [[ELSE_CMP_DST_SUB_3_UPPER]]
90 ; CHECK-NEXT:    [[ELSE_CMP_DST_SUB_4_LOWER:%.*]] = icmp uge ptr [[DST_SUB_4]], [[LOWER]]
91 ; CHECK-NEXT:    [[ELSE_CMP_DST_SUB_4_UPPER:%.*]] = icmp ult ptr [[DST_SUB_4]], [[UPPER]]
92 ; CHECK-NEXT:    [[ELSE_RES_4:%.*]] = xor i1 [[ELSE_RES_3]], [[ELSE_CMP_DST_SUB_4_LOWER]]
93 ; CHECK-NEXT:    [[ELSE_RES_5:%.*]] = xor i1 [[ELSE_RES_4]], [[ELSE_CMP_DST_SUB_4_UPPER]]
94 ; CHECK-NEXT:    [[ELSE_DST_SUB_5:%.*]] = getelementptr inbounds i8, ptr [[DST]], i64 -5
95 ; CHECK-NEXT:    [[ELSE_CMP_DST_SUB_5_LOWER:%.*]] = icmp uge ptr [[ELSE_DST_SUB_5]], [[LOWER]]
96 ; CHECK-NEXT:    [[ELSE_CMP_DST_SUB_5_UPPER:%.*]] = icmp ult ptr [[ELSE_DST_SUB_5]], [[UPPER]]
97 ; CHECK-NEXT:    [[ELSE_RES_6:%.*]] = xor i1 [[ELSE_RES_5]], [[ELSE_CMP_DST_SUB_5_LOWER]]
98 ; CHECK-NEXT:    [[ELSE_RES_7:%.*]] = xor i1 [[ELSE_RES_6]], [[ELSE_CMP_DST_SUB_5_UPPER]]
99 ; CHECK-NEXT:    ret i1 [[ELSE_RES_7]]
101   %dst.sub.4 = getelementptr inbounds i8, ptr %dst, i64 -4
102   %pre.dst.lower = icmp uge ptr %dst, %lower
103   %pre.dst.upper = icmp ult ptr %dst.sub.4, %upper
104   %and = and i1 %pre.dst.lower, %pre.dst.upper
105   br i1 %and, label %then, label %else
107 then:
108   %cmp.dst.lower = icmp uge ptr %dst, %lower
109   %cmp.dst.upper = icmp ult ptr %dst, %upper
110   %res.1 = xor i1 %cmp.dst.lower, %cmp.dst.upper
111   %dst.sub.3 = getelementptr inbounds i8, ptr %dst, i64 -3
112   %cmp.dst.sub.3.lower = icmp uge ptr %dst.sub.3, %lower
113   %cmp.dst.sub.3.upper = icmp ult ptr %dst.sub.3, %upper
114   %res.2 = xor i1 %res.1, %cmp.dst.sub.3.lower
115   %res.3 = xor i1 %res.2, %cmp.dst.sub.3.upper
116   %cmp.dst.sub.4.lower = icmp uge ptr %dst.sub.4, %lower
117   %cmp.dst.sub.4.upper = icmp ult ptr %dst.sub.4, %upper
118   %res.4 = xor i1 %res.3, %cmp.dst.sub.4.lower
119   %res.5 = xor i1 %res.4, %cmp.dst.sub.4.upper
120   %dst.sub.5 = getelementptr inbounds i8, ptr %dst, i64 -5
121   %cmp.dst.sub.5.lower = icmp uge ptr %dst.sub.5, %lower
122   %cmp.dst.sub.5.upper = icmp ult ptr %dst.sub.5, %upper
123   %res.6 = xor i1 %res.5, %cmp.dst.sub.5.lower
124   %res.7 = xor i1 %res.6, %cmp.dst.sub.5.upper
125   ret i1 %res.7
127 else:
128   %else.cmp.dst.lower = icmp uge ptr %dst, %lower
129   %else.cmp.dst.upper = icmp ult ptr %dst, %upper
130   %else.res.1 = xor i1 %else.cmp.dst.lower, %else.cmp.dst.upper
131   %else.dst.sub.3 = getelementptr inbounds i8, ptr %dst, i64 -3
132   %else.cmp.dst.sub.3.lower = icmp uge ptr %else.dst.sub.3, %lower
133   %else.cmp.dst.sub.3.upper = icmp ult ptr %else.dst.sub.3, %upper
134   %else.res.2 = xor i1 %else.res.1, %else.cmp.dst.sub.3.lower
135   %else.res.3 = xor i1 %else.res.2, %else.cmp.dst.sub.3.upper
136   %else.cmp.dst.sub.4.lower = icmp uge ptr %dst.sub.4, %lower
137   %else.cmp.dst.sub.4.upper = icmp ult ptr %dst.sub.4, %upper
138   %else.res.4 = xor i1 %else.res.3, %else.cmp.dst.sub.4.lower
139   %else.res.5 = xor i1 %else.res.4, %else.cmp.dst.sub.4.upper
140   %else.dst.sub.5 = getelementptr inbounds i8, ptr %dst, i64 -5
141   %else.cmp.dst.sub.5.lower = icmp uge ptr %else.dst.sub.5, %lower
142   %else.cmp.dst.sub.5.upper = icmp ult ptr %else.dst.sub.5, %upper
143   %else.res.6 = xor i1 %else.res.5, %else.cmp.dst.sub.5.lower
144   %else.res.7 = xor i1 %else.res.6, %else.cmp.dst.sub.5.upper
145   ret i1 %else.res.7
148 define i4 @ptr_N_signed_positive_explicit_check_constant_step(ptr %src, ptr %lower, ptr %upper, i16 %N) {
149 ; CHECK-LABEL: @ptr_N_signed_positive_explicit_check_constant_step(
150 ; CHECK-NEXT:  entry:
151 ; CHECK-NEXT:    [[N_POS:%.*]] = icmp sge i16 [[N:%.*]], 0
152 ; CHECK-NEXT:    br i1 [[N_POS]], label [[ENTRY_1:%.*]], label [[TRAP_BB:%.*]]
153 ; CHECK:       entry.1:
154 ; CHECK-NEXT:    [[SRC_END:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i16 [[N]]
155 ; CHECK-NEXT:    [[CMP_SRC_START:%.*]] = icmp ult ptr [[SRC]], [[LOWER:%.*]]
156 ; CHECK-NEXT:    [[CMP_SRC_END:%.*]] = icmp uge ptr [[SRC_END]], [[UPPER:%.*]]
157 ; CHECK-NEXT:    [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]]
158 ; CHECK-NEXT:    br i1 [[OR_PRECOND_0]], label [[TRAP_BB]], label [[STEP_CHECK:%.*]]
159 ; CHECK:       trap.bb:
160 ; CHECK-NEXT:    ret i4 2
161 ; CHECK:       step.check:
162 ; CHECK-NEXT:    [[STEP_ULT_N:%.*]] = icmp ult i16 1, [[N]]
163 ; CHECK-NEXT:    br i1 [[STEP_ULT_N]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]]
164 ; CHECK:       ptr.check:
165 ; CHECK-NEXT:    [[SRC_STEP:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i16 1
166 ; CHECK-NEXT:    [[OR_CHECK:%.*]] = or i1 false, false
167 ; CHECK-NEXT:    br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]]
168 ; CHECK:       exit:
169 ; CHECK-NEXT:    ret i4 3
171 entry:
172   %N.pos = icmp sge i16 %N, 0
173   br i1 %N.pos, label %entry.1, label %trap.bb
175 entry.1:
176   %src.end = getelementptr inbounds i8, ptr %src, i16 %N
177   %cmp.src.start = icmp ult ptr %src, %lower
178   %cmp.src.end = icmp uge ptr %src.end, %upper
179   %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end
180   br i1 %or.precond.0, label %trap.bb, label %step.check
182 trap.bb:
183   ret i4 2
185 step.check:
186   %step.ult.N = icmp ult i16 1, %N
187   br i1 %step.ult.N, label %ptr.check, label %exit
189 ptr.check:
190   %src.step = getelementptr inbounds i8, ptr %src, i16 1
191   %cmp.step.start = icmp ult ptr %src.step, %lower
192   %cmp.step.end = icmp uge ptr %src.step, %upper
193   %or.check = or i1 %cmp.step.start, %cmp.step.end
194   br i1 %or.check, label %trap.bb, label %exit
196 exit:
197   ret i4 3
200 ; Same as ptr_N_signed_positive_explicit_check_constant_step, but without inbounds.
201 define i4 @ptr_N_signed_positive_explicit_check_constant_step_no_inbonds(ptr %src, ptr %lower, ptr %upper, i16 %N) {
202 ; CHECK-LABEL: @ptr_N_signed_positive_explicit_check_constant_step_no_inbonds(
203 ; CHECK-NEXT:  entry:
204 ; CHECK-NEXT:    [[N_POS:%.*]] = icmp sge i16 [[N:%.*]], 0
205 ; CHECK-NEXT:    br i1 [[N_POS]], label [[ENTRY_1:%.*]], label [[TRAP_BB:%.*]]
206 ; CHECK:       entry.1:
207 ; CHECK-NEXT:    [[SRC_END:%.*]] = getelementptr i8, ptr [[SRC:%.*]], i16 [[N]]
208 ; CHECK-NEXT:    [[CMP_SRC_START:%.*]] = icmp ult ptr [[SRC]], [[LOWER:%.*]]
209 ; CHECK-NEXT:    [[CMP_SRC_END:%.*]] = icmp uge ptr [[SRC_END]], [[UPPER:%.*]]
210 ; CHECK-NEXT:    [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]]
211 ; CHECK-NEXT:    br i1 [[OR_PRECOND_0]], label [[TRAP_BB]], label [[STEP_CHECK:%.*]]
212 ; CHECK:       trap.bb:
213 ; CHECK-NEXT:    ret i4 2
214 ; CHECK:       step.check:
215 ; CHECK-NEXT:    [[STEP_ULT_N:%.*]] = icmp ult i16 1, [[N]]
216 ; CHECK-NEXT:    br i1 [[STEP_ULT_N]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]]
217 ; CHECK:       ptr.check:
218 ; CHECK-NEXT:    [[SRC_STEP:%.*]] = getelementptr i8, ptr [[SRC]], i16 1
219 ; CHECK-NEXT:    [[CMP_STEP_START:%.*]] = icmp ult ptr [[SRC_STEP]], [[LOWER]]
220 ; CHECK-NEXT:    [[CMP_STEP_END:%.*]] = icmp uge ptr [[SRC_STEP]], [[UPPER]]
221 ; CHECK-NEXT:    [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], [[CMP_STEP_END]]
222 ; CHECK-NEXT:    br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]]
223 ; CHECK:       exit:
224 ; CHECK-NEXT:    ret i4 3
226 entry:
227   %N.pos = icmp sge i16 %N, 0
228   br i1 %N.pos, label %entry.1, label %trap.bb
230 entry.1:
231   %src.end = getelementptr i8, ptr %src, i16 %N
232   %cmp.src.start = icmp ult ptr %src, %lower
233   %cmp.src.end = icmp uge ptr %src.end, %upper
234   %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end
235   br i1 %or.precond.0, label %trap.bb, label %step.check
237 trap.bb:
238   ret i4 2
240 step.check:
241   %step.ult.N = icmp ult i16 1, %N
242   br i1 %step.ult.N, label %ptr.check, label %exit
244 ptr.check:
245   %src.step = getelementptr i8, ptr %src, i16 1
246   %cmp.step.start = icmp ult ptr %src.step, %lower
247   %cmp.step.end = icmp uge ptr %src.step, %upper
248   %or.check = or i1 %cmp.step.start, %cmp.step.end
249   br i1 %or.check, label %trap.bb, label %exit
251 exit:
252   ret i4 3
255 define i4 @ptr_N_and_step_signed_positive_explicit_check_constant_step(ptr %src, ptr %lower, ptr %upper, i16 %N, i16 %step) {
256 ; CHECK-LABEL: @ptr_N_and_step_signed_positive_explicit_check_constant_step(
257 ; CHECK-NEXT:  entry:
258 ; CHECK-NEXT:    [[N_POS:%.*]] = icmp sge i16 [[N:%.*]], 0
259 ; CHECK-NEXT:    [[STEP_POS:%.*]] = icmp sge i16 [[STEP:%.*]], 0
260 ; CHECK-NEXT:    [[AND_1:%.*]] = and i1 [[N_POS]], [[STEP_POS]]
261 ; CHECK-NEXT:    br i1 [[AND_1]], label [[ENTRY_1:%.*]], label [[TRAP_BB:%.*]]
262 ; CHECK:       entry.1:
263 ; CHECK-NEXT:    [[SRC_END:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i16 [[N]]
264 ; CHECK-NEXT:    [[CMP_SRC_START:%.*]] = icmp ult ptr [[SRC]], [[LOWER:%.*]]
265 ; CHECK-NEXT:    [[CMP_SRC_END:%.*]] = icmp uge ptr [[SRC_END]], [[UPPER:%.*]]
266 ; CHECK-NEXT:    [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]]
267 ; CHECK-NEXT:    br i1 [[OR_PRECOND_0]], label [[TRAP_BB]], label [[STEP_CHECK:%.*]]
268 ; CHECK:       trap.bb:
269 ; CHECK-NEXT:    ret i4 2
270 ; CHECK:       step.check:
271 ; CHECK-NEXT:    [[STEP_ULT_N:%.*]] = icmp ult i16 [[STEP]], [[N]]
272 ; CHECK-NEXT:    [[AND_2:%.*]] = and i1 true, [[STEP_ULT_N]]
273 ; CHECK-NEXT:    br i1 [[AND_2]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]]
274 ; CHECK:       ptr.check:
275 ; CHECK-NEXT:    [[SRC_STEP:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i16 1
276 ; CHECK-NEXT:    [[OR_CHECK:%.*]] = or i1 false, false
277 ; CHECK-NEXT:    br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]]
278 ; CHECK:       exit:
279 ; CHECK-NEXT:    ret i4 3
281 entry:
282   %N.pos = icmp sge i16 %N, 0
283   %step.pos = icmp sge i16 %step, 0
284   %and.1 = and i1 %N.pos, %step.pos
285   br i1 %and.1, label %entry.1, label %trap.bb
287 entry.1:
288   %src.end = getelementptr inbounds i8, ptr %src, i16 %N
289   %cmp.src.start = icmp ult ptr %src, %lower
290   %cmp.src.end = icmp uge ptr %src.end, %upper
291   %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end
292   br i1 %or.precond.0, label %trap.bb, label %step.check
294 trap.bb:
295   ret i4 2
297 step.check:
298   %step.uge.0 = icmp uge i16 %step, 0
299   %step.ult.N = icmp ult i16 %step, %N
300   %and.2 = and i1 %step.uge.0, %step.ult.N
301   br i1 %and.2, label %ptr.check, label %exit
303 ptr.check:
304   %src.step = getelementptr inbounds i8, ptr %src, i16 1
305   %cmp.step.start = icmp ult ptr %src.step, %lower
306   %cmp.step.end = icmp uge ptr %src.step, %upper
307   %or.check = or i1 %cmp.step.start, %cmp.step.end
308   br i1 %or.check, label %trap.bb, label %exit
310 exit:
311   ret i4 3
314 define i4 @ptr_N_and_step_signed_positive_unsigned_checks_only(ptr %src, ptr %lower, ptr %upper, i16 %N, i16 %step) {
315 ; CHECK-LABEL: @ptr_N_and_step_signed_positive_unsigned_checks_only(
316 ; CHECK-NEXT:  entry:
317 ; CHECK-NEXT:    [[SRC_END:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i16 [[N:%.*]]
318 ; CHECK-NEXT:    [[NO_OVERFLOW:%.*]] = icmp ule ptr [[SRC]], [[SRC_END]]
319 ; CHECK-NEXT:    br i1 [[NO_OVERFLOW]], label [[ENTRY_1:%.*]], label [[TRAP_BB:%.*]]
320 ; CHECK:       entry.1:
321 ; CHECK-NEXT:    [[CMP_SRC_START:%.*]] = icmp ult ptr [[SRC]], [[LOWER:%.*]]
322 ; CHECK-NEXT:    [[CMP_SRC_END:%.*]] = icmp uge ptr [[SRC_END]], [[UPPER:%.*]]
323 ; CHECK-NEXT:    [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]]
324 ; CHECK-NEXT:    br i1 [[OR_PRECOND_0]], label [[TRAP_BB]], label [[STEP_CHECK:%.*]]
325 ; CHECK:       trap.bb:
326 ; CHECK-NEXT:    ret i4 2
327 ; CHECK:       step.check:
328 ; CHECK-NEXT:    [[STEP_ULT_N:%.*]] = icmp ult i16 [[STEP:%.*]], [[N]]
329 ; CHECK-NEXT:    [[AND_2:%.*]] = and i1 true, [[STEP_ULT_N]]
330 ; CHECK-NEXT:    br i1 [[AND_2]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]]
331 ; CHECK:       ptr.check:
332 ; CHECK-NEXT:    [[SRC_STEP:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i16 1
333 ; CHECK-NEXT:    [[CMP_STEP_END:%.*]] = icmp uge ptr [[SRC_STEP]], [[UPPER]]
334 ; CHECK-NEXT:    [[OR_CHECK:%.*]] = or i1 false, [[CMP_STEP_END]]
335 ; CHECK-NEXT:    br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]]
336 ; CHECK:       exit:
337 ; CHECK-NEXT:    ret i4 3
339 entry:
340   %src.end = getelementptr inbounds i8, ptr %src, i16 %N
341   %no.overflow = icmp ule ptr %src, %src.end
342   br i1 %no.overflow, label %entry.1, label %trap.bb
344 entry.1:
345   %cmp.src.start = icmp ult ptr %src, %lower
346   %cmp.src.end = icmp uge ptr %src.end, %upper
347   %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end
348   br i1 %or.precond.0, label %trap.bb, label %step.check
350 trap.bb:
351   ret i4 2
353 step.check:
354   %step.uge.0 = icmp uge i16 %step, 0
355   %step.ult.N = icmp ult i16 %step, %N
356   %and.2 = and i1 %step.uge.0, %step.ult.N
357   br i1 %and.2, label %ptr.check, label %exit
359 ptr.check:
360   %src.step = getelementptr inbounds i8, ptr %src, i16 1
361   %cmp.step.start = icmp ult ptr %src.step, %lower
362   %cmp.step.end = icmp uge ptr %src.step, %upper
363   %or.check = or i1 %cmp.step.start, %cmp.step.end
364   br i1 %or.check, label %trap.bb, label %exit
366 exit:
367   ret i4 3
370 define i4 @ptr_N_signed_positive(ptr %src, ptr %lower, ptr %upper, i16 %N, i16 %step) {
371 ; CHECK-LABEL: @ptr_N_signed_positive(
372 ; CHECK-NEXT:  entry:
373 ; CHECK-NEXT:    [[SRC_END:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i16 [[N:%.*]]
374 ; CHECK-NEXT:    [[CMP_SRC_START:%.*]] = icmp ult ptr [[SRC]], [[LOWER:%.*]]
375 ; CHECK-NEXT:    [[CMP_SRC_END:%.*]] = icmp uge ptr [[SRC_END]], [[UPPER:%.*]]
376 ; CHECK-NEXT:    [[N_NEG:%.*]] = icmp slt i16 [[N]], 0
377 ; CHECK-NEXT:    [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]]
378 ; CHECK-NEXT:    [[OR_PRECOND_1:%.*]] = or i1 [[OR_PRECOND_0]], [[N_NEG]]
379 ; CHECK-NEXT:    br i1 [[OR_PRECOND_1]], label [[TRAP_BB:%.*]], label [[STEP_CHECK:%.*]]
380 ; CHECK:       trap.bb:
381 ; CHECK-NEXT:    ret i4 2
382 ; CHECK:       step.check:
383 ; CHECK-NEXT:    [[STEP_ULT_N:%.*]] = icmp ult i16 [[STEP:%.*]], [[N]]
384 ; CHECK-NEXT:    [[AND_STEP:%.*]] = and i1 true, [[STEP_ULT_N]]
385 ; CHECK-NEXT:    br i1 [[AND_STEP]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]]
386 ; CHECK:       ptr.check:
387 ; CHECK-NEXT:    [[SRC_STEP:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i16 [[STEP]]
388 ; CHECK-NEXT:    [[OR_CHECK:%.*]] = or i1 false, false
389 ; CHECK-NEXT:    br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]]
390 ; CHECK:       exit:
391 ; CHECK-NEXT:    ret i4 3
393 entry:
394   %src.end = getelementptr inbounds i8, ptr %src, i16 %N
395   %cmp.src.start = icmp ult ptr %src, %lower
396   %cmp.src.end = icmp uge ptr %src.end, %upper
397   %N.neg = icmp slt i16 %N, 0
398   %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end
399   %or.precond.1 = or i1 %or.precond.0, %N.neg
400   br i1 %or.precond.1, label %trap.bb, label %step.check
402 trap.bb:
403   ret i4 2
405 step.check:
406   %step.pos = icmp uge i16 %step, 0
407   %step.ult.N = icmp ult i16 %step, %N
408   %and.step = and i1 %step.pos, %step.ult.N
409   br i1 %and.step, label %ptr.check, label %exit
411 ptr.check:
412   %src.step = getelementptr inbounds i8, ptr %src, i16 %step
413   %cmp.step.start = icmp ult ptr %src.step, %lower
414   %cmp.step.end = icmp uge ptr %src.step, %upper
415   %or.check = or i1 %cmp.step.start, %cmp.step.end
416   br i1 %or.check, label %trap.bb, label %exit
418 exit:
419   ret i4 3
422 define i4 @ptr_N_could_be_negative(ptr %src, ptr %lower, ptr %upper, i8 %N, i8 %step) {
423 ; CHECK-LABEL: @ptr_N_could_be_negative(
424 ; CHECK-NEXT:  entry:
425 ; CHECK-NEXT:    [[SRC_END:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i8 [[N:%.*]]
426 ; CHECK-NEXT:    [[CMP_SRC_START:%.*]] = icmp ult ptr [[SRC]], [[LOWER:%.*]]
427 ; CHECK-NEXT:    [[CMP_SRC_END:%.*]] = icmp uge ptr [[SRC_END]], [[UPPER:%.*]]
428 ; CHECK-NEXT:    [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]]
429 ; CHECK-NEXT:    br i1 [[OR_PRECOND_0]], label [[TRAP_BB:%.*]], label [[STEP_CHECK:%.*]]
430 ; CHECK:       trap.bb:
431 ; CHECK-NEXT:    ret i4 2
432 ; CHECK:       step.check:
433 ; CHECK-NEXT:    [[STEP_ULT_N:%.*]] = icmp ult i8 [[STEP:%.*]], [[N]]
434 ; CHECK-NEXT:    [[AND_STEP:%.*]] = and i1 true, [[STEP_ULT_N]]
435 ; CHECK-NEXT:    br i1 [[AND_STEP]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]]
436 ; CHECK:       ptr.check:
437 ; CHECK-NEXT:    [[SRC_STEP:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i8 [[STEP]]
438 ; CHECK-NEXT:    [[CMP_STEP_START:%.*]] = icmp ult ptr [[SRC_STEP]], [[LOWER]]
439 ; CHECK-NEXT:    [[CMP_STEP_END:%.*]] = icmp uge ptr [[SRC_STEP]], [[UPPER]]
440 ; CHECK-NEXT:    [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], [[CMP_STEP_END]]
441 ; CHECK-NEXT:    br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]]
442 ; CHECK:       exit:
443 ; CHECK-NEXT:    ret i4 3
445 entry:
446   %src.end = getelementptr inbounds i8, ptr %src, i8 %N
447   %cmp.src.start = icmp ult ptr %src, %lower
448   %cmp.src.end = icmp uge ptr %src.end, %upper
449   %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end
450   br i1 %or.precond.0, label %trap.bb, label %step.check
452 trap.bb:
453   ret i4 2
455 step.check:
456   %step.pos = icmp uge i8 %step, 0
457   %step.ult.N = icmp ult i8 %step, %N
458   %and.step = and i1 %step.pos, %step.ult.N
459   br i1 %and.step, label %ptr.check, label %exit
461 ptr.check:
462   %src.step = getelementptr inbounds i8, ptr %src, i8 %step
463   %cmp.step.start = icmp ult ptr %src.step, %lower
464   %cmp.step.end = icmp uge ptr %src.step, %upper
465   %or.check = or i1 %cmp.step.start, %cmp.step.end
466   br i1 %or.check, label %trap.bb, label %exit
468 exit:
469   ret i4 3
472 define i4 @ptr_src_uge_end(ptr %src, ptr %lower, ptr %upper, i8 %N, i8 %step) {
473 ; CHECK-LABEL: @ptr_src_uge_end(
474 ; CHECK-NEXT:  entry:
475 ; CHECK-NEXT:    [[SRC_END:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i8 [[N:%.*]]
476 ; CHECK-NEXT:    [[CMP_SRC_START:%.*]] = icmp ult ptr [[SRC]], [[LOWER:%.*]]
477 ; CHECK-NEXT:    [[CMP_SRC_END:%.*]] = icmp uge ptr [[SRC_END]], [[UPPER:%.*]]
478 ; CHECK-NEXT:    [[CMP_OVERFLOW:%.*]] = icmp ugt ptr [[SRC]], [[SRC_END]]
479 ; CHECK-NEXT:    [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]]
480 ; CHECK-NEXT:    [[OR_PRECOND_1:%.*]] = or i1 [[OR_PRECOND_0]], [[CMP_OVERFLOW]]
481 ; CHECK-NEXT:    br i1 [[OR_PRECOND_1]], label [[TRAP_BB:%.*]], label [[STEP_CHECK:%.*]]
482 ; CHECK:       trap.bb:
483 ; CHECK-NEXT:    ret i4 2
484 ; CHECK:       step.check:
485 ; CHECK-NEXT:    [[STEP_ULT_N:%.*]] = icmp ult i8 [[STEP:%.*]], [[N]]
486 ; CHECK-NEXT:    [[AND_STEP:%.*]] = and i1 true, [[STEP_ULT_N]]
487 ; CHECK-NEXT:    br i1 [[AND_STEP]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]]
488 ; CHECK:       ptr.check:
489 ; CHECK-NEXT:    [[SRC_STEP:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i8 [[STEP]]
490 ; CHECK-NEXT:    [[CMP_STEP_START:%.*]] = icmp ult ptr [[SRC_STEP]], [[LOWER]]
491 ; CHECK-NEXT:    [[CMP_STEP_END:%.*]] = icmp uge ptr [[SRC_STEP]], [[UPPER]]
492 ; CHECK-NEXT:    [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], [[CMP_STEP_END]]
493 ; CHECK-NEXT:    br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]]
494 ; CHECK:       exit:
495 ; CHECK-NEXT:    ret i4 3
497 entry:
498   %src.end = getelementptr inbounds i8, ptr %src, i8 %N
499   %cmp.src.start = icmp ult ptr %src, %lower
500   %cmp.src.end = icmp uge ptr %src.end, %upper
501   %cmp.overflow = icmp ugt ptr %src, %src.end
502   %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end
503   %or.precond.1 = or i1 %or.precond.0, %cmp.overflow
504   br i1 %or.precond.1, label %trap.bb, label %step.check
506 trap.bb:
507   ret i4 2
509 step.check:
510   %step.pos = icmp uge i8 %step, 0
511   %step.ult.N = icmp ult i8 %step, %N
512   %and.step = and i1 %step.pos, %step.ult.N
513   br i1 %and.step, label %ptr.check, label %exit
515 ptr.check:
516   %src.step = getelementptr inbounds i8, ptr %src, i8 %step
517   %cmp.step.start = icmp ult ptr %src.step, %lower
518   %cmp.step.end = icmp uge ptr %src.step, %upper
519   %or.check = or i1 %cmp.step.start, %cmp.step.end
520   br i1 %or.check, label %trap.bb, label %exit
522 exit:
523   ret i4 3
526 ; N might be negative, meaning %src.end could be < %src! Cannot remove checks!
527 define i4 @ptr_N_unsigned_positive(ptr %src, ptr %lower, ptr %upper, i16 %N, i16 %step) {
528 ; CHECK-LABEL: @ptr_N_unsigned_positive(
529 ; CHECK-NEXT:  entry:
530 ; CHECK-NEXT:    [[SRC_END:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i16 [[N:%.*]]
531 ; CHECK-NEXT:    [[CMP_SRC_START:%.*]] = icmp ult ptr [[SRC]], [[LOWER:%.*]]
532 ; CHECK-NEXT:    [[CMP_SRC_END:%.*]] = icmp uge ptr [[SRC_END]], [[UPPER:%.*]]
533 ; CHECK-NEXT:    [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]]
534 ; CHECK-NEXT:    [[OR_PRECOND_1:%.*]] = or i1 [[OR_PRECOND_0]], false
535 ; CHECK-NEXT:    br i1 [[OR_PRECOND_1]], label [[TRAP_BB:%.*]], label [[STEP_CHECK:%.*]]
536 ; CHECK:       trap.bb:
537 ; CHECK-NEXT:    ret i4 2
538 ; CHECK:       step.check:
539 ; CHECK-NEXT:    [[STEP_ULT_N:%.*]] = icmp ult i16 [[STEP:%.*]], [[N]]
540 ; CHECK-NEXT:    [[AND_STEP:%.*]] = and i1 true, [[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, ptr [[SRC]], i16 [[STEP]]
544 ; CHECK-NEXT:    [[CMP_STEP_START:%.*]] = icmp ult ptr [[SRC_STEP]], [[LOWER]]
545 ; CHECK-NEXT:    [[CMP_STEP_END:%.*]] = icmp uge ptr [[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, ptr %src, i16 %N
553   %cmp.src.start = icmp ult ptr %src, %lower
554   %cmp.src.end = icmp uge ptr %src.end, %upper
555   %N.neg = icmp ult i16 %N, 0
556   %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end
557   %or.precond.1 = or i1 %or.precond.0, %N.neg
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   %step.ult.N = icmp ult i16 %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, ptr %src, i16 %step
571   %cmp.step.start = icmp ult ptr %src.step, %lower
572   %cmp.step.end = icmp uge ptr %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_N_signed_positive_assume(ptr %src, ptr %lower, ptr %upper, i16 %N, i16 %step) {
581 ; CHECK-LABEL: @ptr_N_signed_positive_assume(
582 ; CHECK-NEXT:  entry:
583 ; CHECK-NEXT:    [[SRC_END:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i16 [[N:%.*]]
584 ; CHECK-NEXT:    [[CMP_SRC_START:%.*]] = icmp ult ptr [[SRC]], [[LOWER:%.*]]
585 ; CHECK-NEXT:    [[CMP_SRC_END:%.*]] = icmp uge ptr [[SRC_END]], [[UPPER:%.*]]
586 ; CHECK-NEXT:    [[N_NEG:%.*]] = icmp slt i16 [[N]], 0
587 ; CHECK-NEXT:    call void @llvm.assume(i1 [[N_NEG]])
588 ; CHECK-NEXT:    [[OR_PRECOND_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]]
589 ; CHECK-NEXT:    br i1 [[OR_PRECOND_0]], label [[TRAP_BB:%.*]], label [[STEP_CHECK:%.*]]
590 ; CHECK:       trap.bb:
591 ; CHECK-NEXT:    ret i4 2
592 ; CHECK:       step.check:
593 ; CHECK-NEXT:    [[STEP_ULT_N:%.*]] = icmp ult i16 [[STEP:%.*]], [[N]]
594 ; CHECK-NEXT:    [[AND_STEP:%.*]] = and i1 true, [[STEP_ULT_N]]
595 ; CHECK-NEXT:    br i1 [[AND_STEP]], label [[PTR_CHECK:%.*]], label [[EXIT:%.*]]
596 ; CHECK:       ptr.check:
597 ; CHECK-NEXT:    [[SRC_STEP:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i16 [[STEP]]
598 ; CHECK-NEXT:    [[CMP_STEP_START:%.*]] = icmp ult ptr [[SRC_STEP]], [[LOWER]]
599 ; CHECK-NEXT:    [[CMP_STEP_END:%.*]] = icmp uge ptr [[SRC_STEP]], [[UPPER]]
600 ; CHECK-NEXT:    [[OR_CHECK:%.*]] = or i1 [[CMP_STEP_START]], [[CMP_STEP_END]]
601 ; CHECK-NEXT:    br i1 [[OR_CHECK]], label [[TRAP_BB]], label [[EXIT]]
602 ; CHECK:       exit:
603 ; CHECK-NEXT:    ret i4 3
605 entry:
606   %src.end = getelementptr inbounds i8, ptr %src, i16 %N
607   %cmp.src.start = icmp ult ptr %src, %lower
608   %cmp.src.end = icmp uge ptr %src.end, %upper
609   %N.neg = icmp slt i16 %N, 0
610   call void @llvm.assume(i1 %N.neg)
611   %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end
612   br i1 %or.precond.0, label %trap.bb, label %step.check
614 trap.bb:
615   ret i4 2
617 step.check:
618   %step.pos = icmp uge i16 %step, 0
619   %step.ult.N = icmp ult i16 %step, %N
620   %and.step = and i1 %step.pos, %step.ult.N
621   br i1 %and.step, label %ptr.check, label %exit
623 ptr.check:
624   %src.step = getelementptr inbounds i8, ptr %src, i16 %step
625   %cmp.step.start = icmp ult ptr %src.step, %lower
626   %cmp.step.end = icmp uge ptr %src.step, %upper
627   %or.check = or i1 %cmp.step.start, %cmp.step.end
628   br i1 %or.check, label %trap.bb, label %exit
630 exit:
631   ret i4 3