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