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