xref: /llvm-project/llvm/test/Transforms/ConstraintElimination/gep-arithmetic.ll (revision a608607fd70503c20854bbc0f6f5182b51489b4f)
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 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
27;
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
33
34then:
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
53
54else:
55  ret i1 false
56}
57
58define 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]]
100;
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
106
107then:
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
126
127else:
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
146}
147
148define 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
170;
171entry:
172  %N.pos = icmp sge i16 %N, 0
173  br i1 %N.pos, label %entry.1, label %trap.bb
174
175entry.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
181
182trap.bb:
183  ret i4 2
184
185step.check:
186  %step.ult.N = icmp ult i16 1, %N
187  br i1 %step.ult.N, label %ptr.check, label %exit
188
189ptr.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
195
196exit:
197  ret i4 3
198}
199
200; Same as ptr_N_signed_positive_explicit_check_constant_step, but without inbounds.
201define 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
225;
226entry:
227  %N.pos = icmp sge i16 %N, 0
228  br i1 %N.pos, label %entry.1, label %trap.bb
229
230entry.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
236
237trap.bb:
238  ret i4 2
239
240step.check:
241  %step.ult.N = icmp ult i16 1, %N
242  br i1 %step.ult.N, label %ptr.check, label %exit
243
244ptr.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
250
251exit:
252  ret i4 3
253}
254
255define 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
280;
281entry:
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
286
287entry.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
293
294trap.bb:
295  ret i4 2
296
297step.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
302
303ptr.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
309
310exit:
311  ret i4 3
312}
313
314define 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
338;
339entry:
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
343
344entry.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
349
350trap.bb:
351  ret i4 2
352
353step.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
358
359ptr.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
365
366exit:
367  ret i4 3
368}
369
370define 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
392;
393entry:
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
401
402trap.bb:
403  ret i4 2
404
405step.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
410
411ptr.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
417
418exit:
419  ret i4 3
420}
421
422define 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
444;
445entry:
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
451
452trap.bb:
453  ret i4 2
454
455step.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
460
461ptr.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
467
468exit:
469  ret i4 3
470}
471
472define 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
496;
497entry:
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
505
506trap.bb:
507  ret i4 2
508
509step.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
514
515ptr.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
521
522exit:
523  ret i4 3
524}
525
526; N might be negative, meaning %src.end could be < %src! Cannot remove checks!
527define 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
550;
551entry:
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
559
560trap.bb:
561  ret i4 2
562
563step.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
568
569ptr.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
575
576exit:
577  ret i4 3
578}
579
580define 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
604;
605entry:
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
613
614trap.bb:
615  ret i4 2
616
617step.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
622
623ptr.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
629
630exit:
631  ret i4 3
632}
633
634define i1 @test_nusw(ptr %p, i32 %x, i32 %y) {
635; CHECK-LABEL: @test_nusw(
636; CHECK-NEXT:    [[X_EXT:%.*]] = zext i32 [[X:%.*]] to i64
637; CHECK-NEXT:    [[Y_EXT:%.*]] = zext i32 [[Y:%.*]] to i64
638; CHECK-NEXT:    [[CMP1:%.*]] = icmp ugt i64 [[X_EXT]], [[Y_EXT]]
639; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP1]])
640; CHECK-NEXT:    [[GEP_X:%.*]] = getelementptr nusw i8, ptr [[P:%.*]], i64 [[X_EXT]]
641; CHECK-NEXT:    [[GEP_Y:%.*]] = getelementptr nusw i8, ptr [[P]], i64 [[Y_EXT]]
642; CHECK-NEXT:    ret i1 true
643;
644  %x.ext = zext i32 %x to i64
645  %y.ext = zext i32 %y to i64
646  %cmp1 = icmp ugt i64 %x.ext, %y.ext
647  call void @llvm.assume(i1 %cmp1)
648  %gep.x = getelementptr nusw i8, ptr %p, i64 %x.ext
649  %gep.y = getelementptr nusw i8, ptr %p, i64 %y.ext
650  %cmp2 = icmp ugt ptr %gep.x, %gep.y
651  ret i1 %cmp2
652}
653
654define i1 @test_nusw_nested(ptr %p, i32 %x, i32 %y) {
655; CHECK-LABEL: @test_nusw_nested(
656; CHECK-NEXT:    [[X_EXT:%.*]] = zext i32 [[X:%.*]] to i64
657; CHECK-NEXT:    [[Y_EXT:%.*]] = zext i32 [[Y:%.*]] to i64
658; CHECK-NEXT:    [[CMP1:%.*]] = icmp ugt i64 [[X_EXT]], [[Y_EXT]]
659; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP1]])
660; CHECK-NEXT:    [[GEP_X:%.*]] = getelementptr nusw i8, ptr [[P:%.*]], i64 [[X_EXT]]
661; CHECK-NEXT:    [[GEP_X1:%.*]] = getelementptr nusw i8, ptr [[GEP_X]], i64 1
662; CHECK-NEXT:    [[GEP_Y:%.*]] = getelementptr nusw i8, ptr [[P]], i64 [[Y_EXT]]
663; CHECK-NEXT:    ret i1 true
664;
665  %x.ext = zext i32 %x to i64
666  %y.ext = zext i32 %y to i64
667  %cmp1 = icmp ugt i64 %x.ext, %y.ext
668  call void @llvm.assume(i1 %cmp1)
669  %gep.x = getelementptr nusw i8, ptr %p, i64 %x.ext
670  %gep.x1 = getelementptr nusw i8, ptr %gep.x, i64 1
671  %gep.y = getelementptr nusw i8, ptr %p, i64 %y.ext
672  %cmp2 = icmp ugt ptr %gep.x1, %gep.y
673  ret i1 %cmp2
674}
675
676define i1 @test_missing_nusw(ptr %p, i32 %x, i32 %y) {
677; CHECK-LABEL: @test_missing_nusw(
678; CHECK-NEXT:    [[X_EXT:%.*]] = zext i32 [[X:%.*]] to i64
679; CHECK-NEXT:    [[Y_EXT:%.*]] = zext i32 [[Y:%.*]] to i64
680; CHECK-NEXT:    [[CMP1:%.*]] = icmp ugt i64 [[X_EXT]], [[Y_EXT]]
681; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP1]])
682; CHECK-NEXT:    [[GEP_X:%.*]] = getelementptr nusw i8, ptr [[P:%.*]], i64 [[X_EXT]]
683; CHECK-NEXT:    [[GEP_X1:%.*]] = getelementptr i8, ptr [[GEP_X]], i64 1
684; CHECK-NEXT:    [[GEP_Y:%.*]] = getelementptr nusw i8, ptr [[P]], i64 [[Y_EXT]]
685; CHECK-NEXT:    [[CMP2:%.*]] = icmp ugt ptr [[GEP_X1]], [[GEP_Y]]
686; CHECK-NEXT:    ret i1 [[CMP2]]
687;
688  %x.ext = zext i32 %x to i64
689  %y.ext = zext i32 %y to i64
690  %cmp1 = icmp ugt i64 %x.ext, %y.ext
691  call void @llvm.assume(i1 %cmp1)
692  %gep.x = getelementptr nusw i8, ptr %p, i64 %x.ext
693  %gep.x1 = getelementptr i8, ptr %gep.x, i64 1
694  %gep.y = getelementptr nusw i8, ptr %p, i64 %y.ext
695  %cmp2 = icmp ugt ptr %gep.x1, %gep.y
696  ret i1 %cmp2
697}
698
699define i1 @test_nuw(ptr %p, i64 %x, i64 %y) {
700; CHECK-LABEL: @test_nuw(
701; CHECK-NEXT:    [[CMP1:%.*]] = icmp ugt i64 [[X:%.*]], [[Y:%.*]]
702; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP1]])
703; CHECK-NEXT:    [[GEP_X:%.*]] = getelementptr nuw i8, ptr [[P:%.*]], i64 [[X]]
704; CHECK-NEXT:    [[GEP_Y:%.*]] = getelementptr nuw i8, ptr [[P]], i64 [[Y]]
705; CHECK-NEXT:    ret i1 true
706;
707  %cmp1 = icmp ugt i64 %x, %y
708  call void @llvm.assume(i1 %cmp1)
709  %gep.x = getelementptr nuw i8, ptr %p, i64 %x
710  %gep.y = getelementptr nuw i8, ptr %p, i64 %y
711  %cmp2 = icmp ugt ptr %gep.x, %gep.y
712  ret i1 %cmp2
713}
714
715define i1 @test_nuw_nested(ptr %p, i64 %x, i64 %y) {
716; CHECK-LABEL: @test_nuw_nested(
717; CHECK-NEXT:    [[CMP1:%.*]] = icmp ugt i64 [[X:%.*]], [[Y:%.*]]
718; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP1]])
719; CHECK-NEXT:    [[GEP_X:%.*]] = getelementptr nuw i8, ptr [[P:%.*]], i64 [[X]]
720; CHECK-NEXT:    [[GEP_X1:%.*]] = getelementptr nuw i8, ptr [[GEP_X]], i64 1
721; CHECK-NEXT:    [[GEP_Y:%.*]] = getelementptr nuw i8, ptr [[P]], i64 [[Y]]
722; CHECK-NEXT:    ret i1 true
723;
724  %cmp1 = icmp ugt i64 %x, %y
725  call void @llvm.assume(i1 %cmp1)
726  %gep.x = getelementptr nuw i8, ptr %p, i64 %x
727  %gep.x1 = getelementptr nuw i8, ptr %gep.x, i64 1
728  %gep.y = getelementptr nuw i8, ptr %p, i64 %y
729  %cmp2 = icmp ugt ptr %gep.x1, %gep.y
730  ret i1 %cmp2
731}
732
733define i1 @test_nuw_nested_missing_nuw(ptr %p, i64 %x, i64 %y) {
734; CHECK-LABEL: @test_nuw_nested_missing_nuw(
735; CHECK-NEXT:    [[CMP1:%.*]] = icmp ugt i64 [[X:%.*]], [[Y:%.*]]
736; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP1]])
737; CHECK-NEXT:    [[GEP_X:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[X]]
738; CHECK-NEXT:    [[GEP_X1:%.*]] = getelementptr nuw i8, ptr [[GEP_X]], i64 1
739; CHECK-NEXT:    [[GEP_Y:%.*]] = getelementptr nuw i8, ptr [[P]], i64 [[Y]]
740; CHECK-NEXT:    [[CMP2:%.*]] = icmp ugt ptr [[GEP_X1]], [[GEP_Y]]
741; CHECK-NEXT:    ret i1 [[CMP2]]
742;
743  %cmp1 = icmp ugt i64 %x, %y
744  call void @llvm.assume(i1 %cmp1)
745  %gep.x = getelementptr i8, ptr %p, i64 %x
746  %gep.x1 = getelementptr nuw i8, ptr %gep.x, i64 1
747  %gep.y = getelementptr nuw i8, ptr %p, i64 %y
748  %cmp2 = icmp ugt ptr %gep.x1, %gep.y
749  ret i1 %cmp2
750}
751
752define i1 @test_nuw_incorrect_precondition(ptr %p, i64 %x, i64 %y) {
753; CHECK-LABEL: @test_nuw_incorrect_precondition(
754; CHECK-NEXT:    [[CMP1:%.*]] = icmp uge i64 [[X:%.*]], [[Y:%.*]]
755; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP1]])
756; CHECK-NEXT:    [[GEP_X:%.*]] = getelementptr nuw i8, ptr [[P:%.*]], i64 [[X]]
757; CHECK-NEXT:    [[GEP_Y:%.*]] = getelementptr nuw i8, ptr [[P]], i64 [[Y]]
758; CHECK-NEXT:    [[CMP2:%.*]] = icmp ugt ptr [[GEP_X]], [[GEP_Y]]
759; CHECK-NEXT:    ret i1 [[CMP2]]
760;
761  %cmp1 = icmp uge i64 %x, %y
762  call void @llvm.assume(i1 %cmp1)
763  %gep.x = getelementptr nuw i8, ptr %p, i64 %x
764  %gep.y = getelementptr nuw i8, ptr %p, i64 %y
765  %cmp2 = icmp ugt ptr %gep.x, %gep.y
766  ret i1 %cmp2
767}
768