xref: /llvm-project/llvm/test/Transforms/ConstraintElimination/gep-sub.ll (revision d045e23c2d00a445e40a8c97471df023d8364f59)
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)
5
6define i1 @gep_sub_1_uge_inbounds(ptr %dst, ptr %lower) {
7; CHECK-LABEL: @gep_sub_1_uge_inbounds(
8; CHECK-NEXT:    [[PRE:%.*]] = icmp uge ptr [[DST:%.*]], [[LOWER:%.*]]
9; CHECK-NEXT:    call void @llvm.assume(i1 [[PRE]])
10; CHECK-NEXT:    [[DST_ADD_3:%.*]] = getelementptr inbounds i8, ptr [[DST]], i64 3
11; CHECK-NEXT:    [[DST_SUB_1:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_3]], i64 -1
12; CHECK-NEXT:    [[DST_SUB_3:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_3]], i64 -3
13; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 true, true
14; CHECK-NEXT:    [[DST_SUB_4:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_3]], i64 -4
15; CHECK-NEXT:    [[CMP_SUB_4:%.*]] = icmp uge ptr [[DST_SUB_4]], [[LOWER]]
16; CHECK-NEXT:    [[RES_2:%.*]] = xor i1 [[RES_1]], [[CMP_SUB_4]]
17; CHECK-NEXT:    ret i1 [[RES_2]]
18;
19  %pre = icmp uge ptr %dst, %lower
20  call void @llvm.assume(i1 %pre)
21  %dst.add.3 = getelementptr inbounds i8, ptr %dst, i64 3
22  %dst.sub.1 = getelementptr inbounds i8, ptr %dst.add.3, i64 -1
23  %cmp.sub.1 = icmp uge ptr %dst.sub.1, %lower
24  %dst.sub.3 = getelementptr inbounds i8, ptr %dst.add.3, i64 -3
25  %cmp.sub.3 = icmp uge ptr %dst.sub.3, %lower
26  %res.1 = xor i1 %cmp.sub.1, %cmp.sub.3
27  %dst.sub.4 = getelementptr inbounds i8, ptr %dst.add.3, i64 -4
28  %cmp.sub.4 = icmp uge ptr %dst.sub.4, %lower
29  %res.2 = xor i1 %res.1, %cmp.sub.4
30  ret i1 %res.2
31}
32
33define i1 @gep_sub_1_uge_only_inner_inbounds(ptr %dst, ptr %lower) {
34; CHECK-LABEL: @gep_sub_1_uge_only_inner_inbounds(
35; CHECK-NEXT:    [[PRE:%.*]] = icmp uge ptr [[DST:%.*]], [[LOWER:%.*]]
36; CHECK-NEXT:    call void @llvm.assume(i1 [[PRE]])
37; CHECK-NEXT:    [[DST_ADD_3:%.*]] = getelementptr inbounds i8, ptr [[DST]], i64 3
38; CHECK-NEXT:    [[DST_SUB_1:%.*]] = getelementptr i8, ptr [[DST_ADD_3]], i64 -1
39; CHECK-NEXT:    [[CMP_SUB_1:%.*]] = icmp uge ptr [[DST_SUB_1]], [[LOWER]]
40; CHECK-NEXT:    [[DST_SUB_3:%.*]] = getelementptr i8, ptr [[DST_ADD_3]], i64 -3
41; CHECK-NEXT:    [[CMP_SUB_3:%.*]] = icmp uge ptr [[DST_SUB_3]], [[LOWER]]
42; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 [[CMP_SUB_1]], [[CMP_SUB_3]]
43; CHECK-NEXT:    [[DST_SUB_4:%.*]] = getelementptr i8, ptr [[DST_ADD_3]], i64 -4
44; CHECK-NEXT:    [[CMP_SUB_4:%.*]] = icmp uge ptr [[DST_SUB_4]], [[LOWER]]
45; CHECK-NEXT:    [[RES_2:%.*]] = xor i1 [[RES_1]], [[CMP_SUB_4]]
46; CHECK-NEXT:    ret i1 [[RES_2]]
47;
48  %pre = icmp uge ptr %dst, %lower
49  call void @llvm.assume(i1 %pre)
50  %dst.add.3 = getelementptr inbounds i8, ptr %dst, i64 3
51  %dst.sub.1 = getelementptr i8, ptr %dst.add.3, i64 -1
52  %cmp.sub.1 = icmp uge ptr %dst.sub.1, %lower
53  %dst.sub.3 = getelementptr i8, ptr %dst.add.3, i64 -3
54  %cmp.sub.3 = icmp uge ptr %dst.sub.3, %lower
55  %res.1 = xor i1 %cmp.sub.1, %cmp.sub.3
56  %dst.sub.4 = getelementptr i8, ptr %dst.add.3, i64 -4
57  %cmp.sub.4 = icmp uge ptr %dst.sub.4, %lower
58  %res.2 = xor i1 %res.1, %cmp.sub.4
59  ret i1 %res.2
60}
61
62define i1 @gep_sub_1_uge_only_outer_inbounds(ptr %dst, ptr %lower) {
63; CHECK-LABEL: @gep_sub_1_uge_only_outer_inbounds(
64; CHECK-NEXT:    [[PRE:%.*]] = icmp uge ptr [[DST:%.*]], [[LOWER:%.*]]
65; CHECK-NEXT:    call void @llvm.assume(i1 [[PRE]])
66; CHECK-NEXT:    [[DST_ADD_3:%.*]] = getelementptr i8, ptr [[DST]], i64 3
67; CHECK-NEXT:    [[DST_SUB_1:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_3]], i64 -1
68; CHECK-NEXT:    [[CMP_SUB_1:%.*]] = icmp uge ptr [[DST_SUB_1]], [[LOWER]]
69; CHECK-NEXT:    [[DST_SUB_3:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_3]], i64 -3
70; CHECK-NEXT:    [[CMP_SUB_3:%.*]] = icmp uge ptr [[DST_SUB_3]], [[LOWER]]
71; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 [[CMP_SUB_1]], [[CMP_SUB_3]]
72; CHECK-NEXT:    [[DST_SUB_4:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_3]], i64 -4
73; CHECK-NEXT:    [[CMP_SUB_4:%.*]] = icmp uge ptr [[DST_SUB_4]], [[LOWER]]
74; CHECK-NEXT:    [[RES_2:%.*]] = xor i1 [[RES_1]], [[CMP_SUB_4]]
75; CHECK-NEXT:    ret i1 [[RES_2]]
76;
77  %pre = icmp uge ptr %dst, %lower
78  call void @llvm.assume(i1 %pre)
79  %dst.add.3 = getelementptr i8, ptr %dst, i64 3
80  %dst.sub.1 = getelementptr inbounds i8, ptr %dst.add.3, i64 -1
81  %cmp.sub.1 = icmp uge ptr %dst.sub.1, %lower
82  %dst.sub.3 = getelementptr inbounds i8, ptr %dst.add.3, i64 -3
83  %cmp.sub.3 = icmp uge ptr %dst.sub.3, %lower
84  %res.1 = xor i1 %cmp.sub.1, %cmp.sub.3
85  %dst.sub.4 = getelementptr inbounds i8, ptr %dst.add.3, i64 -4
86  %cmp.sub.4 = icmp uge ptr %dst.sub.4, %lower
87  %res.2 = xor i1 %res.1, %cmp.sub.4
88  ret i1 %res.2
89}
90
91define i1 @gep_sub_1_uge_no_inbounds(ptr %dst, ptr %lower) {
92; CHECK-LABEL: @gep_sub_1_uge_no_inbounds(
93; CHECK-NEXT:    [[PRE:%.*]] = icmp uge ptr [[DST:%.*]], [[LOWER:%.*]]
94; CHECK-NEXT:    call void @llvm.assume(i1 [[PRE]])
95; CHECK-NEXT:    [[DST_ADD_3:%.*]] = getelementptr i8, ptr [[DST]], i64 3
96; CHECK-NEXT:    [[DST_SUB_1:%.*]] = getelementptr i8, ptr [[DST_ADD_3]], i64 -1
97; CHECK-NEXT:    [[CMP_SUB_1:%.*]] = icmp uge ptr [[DST_SUB_1]], [[LOWER]]
98; CHECK-NEXT:    [[DST_SUB_3:%.*]] = getelementptr i8, ptr [[DST_ADD_3]], i64 -3
99; CHECK-NEXT:    [[CMP_SUB_3:%.*]] = icmp uge ptr [[DST_SUB_3]], [[LOWER]]
100; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 [[CMP_SUB_1]], [[CMP_SUB_3]]
101; CHECK-NEXT:    [[DST_SUB_4:%.*]] = getelementptr i8, ptr [[DST_ADD_3]], i64 -4
102; CHECK-NEXT:    [[CMP_SUB_4:%.*]] = icmp uge ptr [[DST_SUB_4]], [[LOWER]]
103; CHECK-NEXT:    [[RES_2:%.*]] = xor i1 [[RES_1]], [[CMP_SUB_4]]
104; CHECK-NEXT:    ret i1 [[RES_2]]
105;
106  %pre = icmp uge ptr %dst, %lower
107  call void @llvm.assume(i1 %pre)
108  %dst.add.3 = getelementptr i8, ptr %dst, i64 3
109  %dst.sub.1 = getelementptr i8, ptr %dst.add.3, i64 -1
110  %cmp.sub.1 = icmp uge ptr %dst.sub.1, %lower
111  %dst.sub.3 = getelementptr i8, ptr %dst.add.3, i64 -3
112  %cmp.sub.3 = icmp uge ptr %dst.sub.3, %lower
113  %res.1 = xor i1 %cmp.sub.1, %cmp.sub.3
114  %dst.sub.4 = getelementptr i8, ptr %dst.add.3, i64 -4
115  %cmp.sub.4 = icmp uge ptr %dst.sub.4, %lower
116  %res.2 = xor i1 %res.1, %cmp.sub.4
117  ret i1 %res.2
118}
119
120define i1 @gep_sub_1_ult(ptr %dst, ptr %upper) {
121; CHECK-LABEL: @gep_sub_1_ult(
122; CHECK-NEXT:    [[DST_ADD_4:%.*]] = getelementptr inbounds i8, ptr [[DST:%.*]], i64 4
123; CHECK-NEXT:    [[PRE:%.*]] = icmp ult ptr [[DST_ADD_4]], [[UPPER:%.*]]
124; CHECK-NEXT:    call void @llvm.assume(i1 [[PRE]])
125; CHECK-NEXT:    [[DST_ADD_3:%.*]] = getelementptr inbounds i8, ptr [[DST]], i64 3
126; CHECK-NEXT:    [[DST_SUB_1:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_3]], i64 -1
127; CHECK-NEXT:    [[DST_SUB_3:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_3]], i64 -3
128; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 true, true
129; CHECK-NEXT:    ret i1 [[RES_1]]
130;
131  %dst.add.4 = getelementptr inbounds i8, ptr %dst, i64 4
132  %pre = icmp ult ptr %dst.add.4, %upper
133  call void @llvm.assume(i1 %pre)
134  %dst.add.3 = getelementptr inbounds i8, ptr %dst, i64 3
135  %dst.sub.1 = getelementptr inbounds i8, ptr %dst.add.3, i64 -1
136  %cmp.sub.1 = icmp ult ptr %dst.sub.1, %upper
137  %dst.sub.3 = getelementptr inbounds i8, ptr %dst.add.3, i64 -3
138  %cmp.sub.3 = icmp ult ptr %dst.sub.3, %upper
139  %res.1 = xor i1 %cmp.sub.1, %cmp.sub.3
140  ret i1 %res.1
141}
142
143define i1 @gep_sub_ult_var_idx(ptr %dst, ptr %upper, i8 %idx) {
144; CHECK-LABEL: @gep_sub_ult_var_idx(
145; CHECK-NEXT:    [[NOT_ZERO:%.*]] = icmp ne i8 [[IDX:%.*]], 0
146; CHECK-NEXT:    call void @llvm.assume(i1 [[NOT_ZERO]])
147; CHECK-NEXT:    [[IDX_EXT:%.*]] = zext i8 [[IDX]] to i16
148; CHECK-NEXT:    [[DST_ADD_IDX:%.*]] = getelementptr inbounds i8, ptr [[DST:%.*]], i16 [[IDX_EXT]]
149; CHECK-NEXT:    [[PRE:%.*]] = icmp ult ptr [[DST_ADD_IDX]], [[UPPER:%.*]]
150; CHECK-NEXT:    call void @llvm.assume(i1 [[PRE]])
151; CHECK-NEXT:    [[DST_SUB_1:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_IDX]], i64 -1
152; CHECK-NEXT:    [[DST_SUB_2:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_IDX]], i64 -2
153; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 true, true
154; CHECK-NEXT:    [[DST_SUB_1_SUB_1:%.*]] = getelementptr inbounds i8, ptr [[DST_SUB_1]], i64 -1
155; CHECK-NEXT:    [[CMP_SUB_1_SUB_1:%.*]] = icmp ult ptr [[DST_SUB_1_SUB_1]], [[UPPER]]
156; CHECK-NEXT:    [[CMP_SUB_1_SUB_1_EQ:%.*]] = icmp eq ptr [[DST_SUB_1_SUB_1]], [[DST_SUB_2]]
157; CHECK-NEXT:    [[RES_2:%.*]] = xor i1 [[RES_1]], [[CMP_SUB_1_SUB_1]]
158; CHECK-NEXT:    [[RES_3:%.*]] = xor i1 [[RES_2]], [[CMP_SUB_1_SUB_1_EQ]]
159; CHECK-NEXT:    ret i1 [[RES_3]]
160;
161  %not.zero = icmp ne i8 %idx, 0
162  call void @llvm.assume(i1 %not.zero)
163  %idx.ext = zext i8 %idx to i16
164  %dst.add.idx = getelementptr inbounds i8, ptr %dst, i16 %idx.ext
165  %pre = icmp ult ptr %dst.add.idx, %upper
166  call void @llvm.assume(i1 %pre)
167  %dst.sub.1 = getelementptr inbounds i8, ptr %dst.add.idx, i64 -1
168  %cmp.sub.1 = icmp ult ptr %dst.sub.1, %upper
169  %dst.sub.2 = getelementptr inbounds i8, ptr %dst.add.idx, i64 -2
170  %cmp.sub.2 = icmp ult ptr %dst.sub.2, %upper
171  %res.1 = xor i1 %cmp.sub.1, %cmp.sub.2
172  %dst.sub.1.sub.1 = getelementptr inbounds i8, ptr %dst.sub.1, i64 -1
173  %cmp.sub.1.sub.1 = icmp ult ptr %dst.sub.1.sub.1, %upper
174  %cmp.sub.1.sub.1.eq = icmp eq ptr %dst.sub.1.sub.1, %dst.sub.2
175  %res.2 = xor i1 %res.1, %cmp.sub.1.sub.1
176  %res.3 = xor i1 %res.2, %cmp.sub.1.sub.1.eq
177  ret i1 %res.3
178}
179
180define i1 @gep_sub_ult_var_idx_sgt_1(ptr %dst, ptr %upper, i8 %idx) {
181; CHECK-LABEL: @gep_sub_ult_var_idx_sgt_1(
182; CHECK-NEXT:    [[SGT_1:%.*]] = icmp sgt i8 [[IDX:%.*]], 1
183; CHECK-NEXT:    call void @llvm.assume(i1 [[SGT_1]])
184; CHECK-NEXT:    [[IDX_EXT:%.*]] = zext i8 [[IDX]] to i16
185; CHECK-NEXT:    [[DST_ADD_IDX:%.*]] = getelementptr inbounds i8, ptr [[DST:%.*]], i16 [[IDX_EXT]]
186; CHECK-NEXT:    [[PRE:%.*]] = icmp ult ptr [[DST_ADD_IDX]], [[UPPER:%.*]]
187; CHECK-NEXT:    call void @llvm.assume(i1 [[PRE]])
188; CHECK-NEXT:    [[DST_SUB_1:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_IDX]], i64 -1
189; CHECK-NEXT:    [[DST_SUB_2:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_IDX]], i64 -2
190; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 true, true
191; CHECK-NEXT:    [[DST_SUB_3:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_IDX]], i64 -3
192; CHECK-NEXT:    [[RES_2:%.*]] = xor i1 [[RES_1]], true
193; CHECK-NEXT:    ret i1 [[RES_2]]
194;
195  %sgt.1 = icmp sgt i8 %idx, 1
196  call void @llvm.assume(i1 %sgt.1)
197  %idx.ext = zext i8 %idx to i16
198  %dst.add.idx = getelementptr inbounds i8, ptr %dst, i16 %idx.ext
199  %pre = icmp ult ptr %dst.add.idx, %upper
200  call void @llvm.assume(i1 %pre)
201  %dst.sub.1 = getelementptr inbounds i8, ptr %dst.add.idx, i64 -1
202  %cmp.sub.1 = icmp ult ptr %dst.sub.1, %upper
203  %dst.sub.2 = getelementptr inbounds i8, ptr %dst.add.idx, i64 -2
204  %cmp.sub.2 = icmp ult ptr %dst.sub.2, %upper
205  %res.1 = xor i1 %cmp.sub.1, %cmp.sub.2
206  %dst.sub.3 = getelementptr inbounds i8, ptr %dst.add.idx, i64 -3
207  %cmp.sub.3 = icmp ult ptr %dst.sub.3, %upper
208  %res.2 = xor i1 %res.1, %cmp.sub.3
209  ret i1 %res.2
210}
211
212define i1 @gep_sub_1_ult_var_idx_inbounds(ptr %dst, ptr %upper, i8 %len, i8 %idx) {
213; CHECK-LABEL: @gep_sub_1_ult_var_idx_inbounds(
214; CHECK-NEXT:    [[NOT_ZERO:%.*]] = icmp ne i8 [[LEN:%.*]], 0
215; CHECK-NEXT:    call void @llvm.assume(i1 [[NOT_ZERO]])
216; CHECK-NEXT:    [[LEN_EXT:%.*]] = zext i8 [[LEN]] to i16
217; CHECK-NEXT:    [[DST_ADD_LEN:%.*]] = getelementptr inbounds i8, ptr [[DST:%.*]], i16 [[LEN_EXT]]
218; CHECK-NEXT:    [[DST_SUB_1:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_LEN]], i64 -1
219; CHECK-NEXT:    [[CMP_SUB_1:%.*]] = icmp ult ptr [[DST_SUB_1]], [[UPPER:%.*]]
220; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_SUB_1]])
221; CHECK-NEXT:    [[CMP_IDX_ULT_LEN:%.*]] = icmp ult i8 [[IDX:%.*]], [[LEN]]
222; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_IDX_ULT_LEN]])
223; CHECK-NEXT:    [[IDX_EXT:%.*]] = zext i8 [[IDX]] to i16
224; CHECK-NEXT:    [[DST_ADD_IDX:%.*]] = getelementptr inbounds i8, ptr [[DST]], i16 [[IDX_EXT]]
225; CHECK-NEXT:    ret i1 true
226;
227  %not.zero = icmp ne i8 %len, 0
228  call void @llvm.assume(i1 %not.zero)
229  %len.ext = zext i8 %len to i16
230  %dst.add.len = getelementptr inbounds i8, ptr %dst, i16 %len.ext
231  %dst.sub.1 = getelementptr inbounds i8, ptr %dst.add.len, i64 -1
232  %cmp.sub.1 = icmp ult ptr %dst.sub.1, %upper
233  call void @llvm.assume(i1 %cmp.sub.1)
234  %cmp.idx.ult.len = icmp ult i8 %idx, %len
235  call void @llvm.assume(i1 %cmp.idx.ult.len)
236  %idx.ext = zext i8 %idx to i16
237  %dst.add.idx = getelementptr inbounds i8, ptr %dst, i16 %idx.ext
238  %cmp.idx = icmp ult ptr %dst.add.idx, %upper
239  ret i1 %cmp.idx
240}
241
242define i1 @gep_sub_1_ult_var_idx_only_inner_inbounds(ptr %dst, ptr %upper, i8 %len, i8 %idx) {
243; CHECK-LABEL: @gep_sub_1_ult_var_idx_only_inner_inbounds(
244; CHECK-NEXT:    [[NOT_ZERO:%.*]] = icmp ne i8 [[LEN:%.*]], 0
245; CHECK-NEXT:    call void @llvm.assume(i1 [[NOT_ZERO]])
246; CHECK-NEXT:    [[LEN_EXT:%.*]] = zext i8 [[LEN]] to i16
247; CHECK-NEXT:    [[DST_ADD_LEN:%.*]] = getelementptr inbounds i8, ptr [[DST:%.*]], i16 [[LEN_EXT]]
248; CHECK-NEXT:    [[DST_SUB_1:%.*]] = getelementptr i8, ptr [[DST_ADD_LEN]], i64 -1
249; CHECK-NEXT:    [[CMP_SUB_1:%.*]] = icmp ult ptr [[DST_SUB_1]], [[UPPER:%.*]]
250; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_SUB_1]])
251; CHECK-NEXT:    [[CMP_IDX_ULT_LEN:%.*]] = icmp ult i8 [[IDX:%.*]], [[LEN]]
252; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_IDX_ULT_LEN]])
253; CHECK-NEXT:    [[IDX_EXT:%.*]] = zext i8 [[IDX]] to i16
254; CHECK-NEXT:    [[DST_ADD_IDX:%.*]] = getelementptr inbounds i8, ptr [[DST]], i16 [[IDX_EXT]]
255; CHECK-NEXT:    [[CMP_IDX:%.*]] = icmp ult ptr [[DST_ADD_IDX]], [[UPPER]]
256; CHECK-NEXT:    ret i1 [[CMP_IDX]]
257;
258  %not.zero = icmp ne i8 %len, 0
259  call void @llvm.assume(i1 %not.zero)
260  %len.ext = zext i8 %len to i16
261  %dst.add.len = getelementptr inbounds i8, ptr %dst, i16 %len.ext
262  %dst.sub.1 = getelementptr i8, ptr %dst.add.len, i64 -1
263  %cmp.sub.1 = icmp ult ptr %dst.sub.1, %upper
264  call void @llvm.assume(i1 %cmp.sub.1)
265  %cmp.idx.ult.len = icmp ult i8 %idx, %len
266  call void @llvm.assume(i1 %cmp.idx.ult.len)
267  %idx.ext = zext i8 %idx to i16
268  %dst.add.idx = getelementptr inbounds i8, ptr %dst, i16 %idx.ext
269  %cmp.idx = icmp ult ptr %dst.add.idx, %upper
270  ret i1 %cmp.idx
271}
272
273define i1 @gep_sub_1_ult_var_idx_no_inbounds(ptr %dst, ptr %upper, i8 %len, i8 %idx) {
274; CHECK-LABEL: @gep_sub_1_ult_var_idx_no_inbounds(
275; CHECK-NEXT:    [[NOT_ZERO:%.*]] = icmp ne i8 [[LEN:%.*]], 0
276; CHECK-NEXT:    call void @llvm.assume(i1 [[NOT_ZERO]])
277; CHECK-NEXT:    [[LEN_EXT:%.*]] = zext i8 [[LEN]] to i16
278; CHECK-NEXT:    [[DST_ADD_LEN:%.*]] = getelementptr i8, ptr [[DST:%.*]], i16 [[LEN_EXT]]
279; CHECK-NEXT:    [[DST_SUB_1:%.*]] = getelementptr i8, ptr [[DST_ADD_LEN]], i64 -1
280; CHECK-NEXT:    [[CMP_SUB_1:%.*]] = icmp ult ptr [[DST_SUB_1]], [[UPPER:%.*]]
281; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_SUB_1]])
282; CHECK-NEXT:    [[CMP_IDX_ULT_LEN:%.*]] = icmp ult i8 [[IDX:%.*]], [[LEN]]
283; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_IDX_ULT_LEN]])
284; CHECK-NEXT:    [[IDX_EXT:%.*]] = zext i8 [[IDX]] to i16
285; CHECK-NEXT:    [[DST_ADD_IDX:%.*]] = getelementptr i8, ptr [[DST]], i16 [[IDX_EXT]]
286; CHECK-NEXT:    [[CMP_IDX:%.*]] = icmp ult ptr [[DST_ADD_IDX]], [[UPPER]]
287; CHECK-NEXT:    ret i1 [[CMP_IDX]]
288;
289  %not.zero = icmp ne i8 %len, 0
290  call void @llvm.assume(i1 %not.zero)
291  %len.ext = zext i8 %len to i16
292  %dst.add.len = getelementptr i8, ptr %dst, i16 %len.ext
293  %dst.sub.1 = getelementptr i8, ptr %dst.add.len, i64 -1
294  %cmp.sub.1 = icmp ult ptr %dst.sub.1, %upper
295  call void @llvm.assume(i1 %cmp.sub.1)
296  %cmp.idx.ult.len = icmp ult i8 %idx, %len
297  call void @llvm.assume(i1 %cmp.idx.ult.len)
298  %idx.ext = zext i8 %idx to i16
299  %dst.add.idx = getelementptr i8, ptr %dst, i16 %idx.ext
300  %cmp.idx = icmp ult ptr %dst.add.idx, %upper
301  ret i1 %cmp.idx
302}
303
304define i1 @gep_sub_2_ult_var_idx(ptr %dst, ptr %upper, i8 %len, i8 %idx) {
305; CHECK-LABEL: @gep_sub_2_ult_var_idx(
306; CHECK-NEXT:    [[NOT_ZERO:%.*]] = icmp ne i8 [[LEN:%.*]], 0
307; CHECK-NEXT:    call void @llvm.assume(i1 [[NOT_ZERO]])
308; CHECK-NEXT:    [[LEN_EXT:%.*]] = zext i8 [[LEN]] to i16
309; CHECK-NEXT:    [[DST_ADD_LEN:%.*]] = getelementptr inbounds i8, ptr [[DST:%.*]], i16 [[LEN_EXT]]
310; CHECK-NEXT:    [[DST_SUB_1:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_LEN]], i64 -2
311; CHECK-NEXT:    [[CMP_SUB_1:%.*]] = icmp ult ptr [[DST_SUB_1]], [[UPPER:%.*]]
312; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_SUB_1]])
313; CHECK-NEXT:    [[CMP_IDX_ULT_LEN:%.*]] = icmp ult i8 [[IDX:%.*]], [[LEN]]
314; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_IDX_ULT_LEN]])
315; CHECK-NEXT:    [[IDX_EXT:%.*]] = zext i8 [[IDX]] to i16
316; CHECK-NEXT:    [[DST_ADD_IDX:%.*]] = getelementptr inbounds i8, ptr [[DST]], i16 [[IDX_EXT]]
317; CHECK-NEXT:    [[CMP_IDX:%.*]] = icmp ult ptr [[DST_ADD_IDX]], [[UPPER]]
318; CHECK-NEXT:    ret i1 [[CMP_IDX]]
319;
320  %not.zero = icmp ne i8 %len, 0
321  call void @llvm.assume(i1 %not.zero)
322  %len.ext = zext i8 %len to i16
323  %dst.add.len = getelementptr inbounds i8, ptr %dst, i16 %len.ext
324  %dst.sub.1 = getelementptr inbounds i8, ptr %dst.add.len, i64 -2
325  %cmp.sub.1 = icmp ult ptr %dst.sub.1, %upper
326  call void @llvm.assume(i1 %cmp.sub.1)
327  %cmp.idx.ult.len = icmp ult i8 %idx, %len
328  call void @llvm.assume(i1 %cmp.idx.ult.len)
329  %idx.ext = zext i8 %idx to i16
330  %dst.add.idx = getelementptr inbounds i8, ptr %dst, i16 %idx.ext
331  %cmp.idx = icmp ult ptr %dst.add.idx, %upper
332  ret i1 %cmp.idx
333}
334
335define i1 @gep_sub_2_ult_var_idx_inbounds_len_sge_2(ptr %dst, ptr %upper, i8 %len, i8 %idx) {
336; CHECK-LABEL: @gep_sub_2_ult_var_idx_inbounds_len_sge_2(
337; CHECK-NEXT:    [[SGE_2:%.*]] = icmp sge i8 [[LEN:%.*]], 2
338; CHECK-NEXT:    call void @llvm.assume(i1 [[SGE_2]])
339; CHECK-NEXT:    [[LEN_EXT:%.*]] = zext i8 [[LEN]] to i16
340; CHECK-NEXT:    [[DST_ADD_LEN:%.*]] = getelementptr inbounds i8, ptr [[DST:%.*]], i16 [[LEN_EXT]]
341; CHECK-NEXT:    [[DST_SUB_1:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_LEN]], i64 -1
342; CHECK-NEXT:    [[CMP_SUB_1:%.*]] = icmp ult ptr [[DST_SUB_1]], [[UPPER:%.*]]
343; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_SUB_1]])
344; CHECK-NEXT:    [[CMP_IDX_ULT_LEN:%.*]] = icmp ult i8 [[IDX:%.*]], [[LEN]]
345; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_IDX_ULT_LEN]])
346; CHECK-NEXT:    [[IDX_EXT:%.*]] = zext i8 [[IDX]] to i16
347; CHECK-NEXT:    [[DST_ADD_IDX:%.*]] = getelementptr inbounds i8, ptr [[DST]], i16 [[IDX_EXT]]
348; CHECK-NEXT:    ret i1 true
349;
350  %sge.2 = icmp sge i8 %len, 2
351  call void @llvm.assume(i1 %sge.2)
352  %len.ext = zext i8 %len to i16
353  %dst.add.len = getelementptr inbounds i8, ptr %dst, i16 %len.ext
354  %dst.sub.1 = getelementptr inbounds i8, ptr %dst.add.len, i64 -1
355  %cmp.sub.1 = icmp ult ptr %dst.sub.1, %upper
356  call void @llvm.assume(i1 %cmp.sub.1)
357  %cmp.idx.ult.len = icmp ult i8 %idx, %len
358  call void @llvm.assume(i1 %cmp.idx.ult.len)
359  %idx.ext = zext i8 %idx to i16
360  %dst.add.idx = getelementptr inbounds i8, ptr %dst, i16 %idx.ext
361  %cmp.idx = icmp ult ptr %dst.add.idx, %upper
362  ret i1 %cmp.idx
363}
364
365define i1 @gep_sub_2_ult_var_idx_inbounds_len_uge_2(ptr %dst, ptr %upper, i8 %len, i8 %idx) {
366; CHECK-LABEL: @gep_sub_2_ult_var_idx_inbounds_len_uge_2(
367; CHECK-NEXT:    [[UGE_2:%.*]] = icmp uge i8 [[LEN:%.*]], 2
368; CHECK-NEXT:    call void @llvm.assume(i1 [[UGE_2]])
369; CHECK-NEXT:    [[LEN_EXT:%.*]] = zext i8 [[LEN]] to i16
370; CHECK-NEXT:    [[DST_ADD_LEN:%.*]] = getelementptr inbounds i8, ptr [[DST:%.*]], i16 [[LEN_EXT]]
371; CHECK-NEXT:    [[DST_SUB_1:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_LEN]], i64 -1
372; CHECK-NEXT:    [[CMP_SUB_1:%.*]] = icmp ult ptr [[DST_SUB_1]], [[UPPER:%.*]]
373; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_SUB_1]])
374; CHECK-NEXT:    [[CMP_IDX_ULT_LEN:%.*]] = icmp ult i8 [[IDX:%.*]], [[LEN]]
375; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_IDX_ULT_LEN]])
376; CHECK-NEXT:    [[IDX_EXT:%.*]] = zext i8 [[IDX]] to i16
377; CHECK-NEXT:    [[DST_ADD_IDX:%.*]] = getelementptr inbounds i8, ptr [[DST]], i16 [[IDX_EXT]]
378; CHECK-NEXT:    ret i1 true
379;
380  %uge.2 = icmp uge i8 %len, 2
381  call void @llvm.assume(i1 %uge.2)
382  %len.ext = zext i8 %len to i16
383  %dst.add.len = getelementptr inbounds i8, ptr %dst, i16 %len.ext
384  %dst.sub.1 = getelementptr inbounds i8, ptr %dst.add.len, i64 -1
385  %cmp.sub.1 = icmp ult ptr %dst.sub.1, %upper
386  call void @llvm.assume(i1 %cmp.sub.1)
387  %cmp.idx.ult.len = icmp ult i8 %idx, %len
388  call void @llvm.assume(i1 %cmp.idx.ult.len)
389  %idx.ext = zext i8 %idx to i16
390  %dst.add.idx = getelementptr inbounds i8, ptr %dst, i16 %idx.ext
391  %cmp.idx = icmp ult ptr %dst.add.idx, %upper
392  ret i1 %cmp.idx
393}
394
395define i1 @gep_sub_ult_var_idx_len_sgt_1(ptr %dst, ptr %upper, i8 %len, i8 %idx) {
396; CHECK-LABEL: @gep_sub_ult_var_idx_len_sgt_1(
397; CHECK-NEXT:    [[SGT_1:%.*]] = icmp sgt i8 [[LEN:%.*]], 1
398; CHECK-NEXT:    call void @llvm.assume(i1 [[SGT_1]])
399; CHECK-NEXT:    [[LEN_EXT:%.*]] = zext i8 [[LEN]] to i16
400; CHECK-NEXT:    [[DST_ADD_LEN:%.*]] = getelementptr inbounds i8, ptr [[DST:%.*]], i16 [[LEN_EXT]]
401; CHECK-NEXT:    [[DST_SUB_1:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_LEN]], i64 -2
402; CHECK-NEXT:    [[CMP_SUB_1:%.*]] = icmp ult ptr [[DST_SUB_1]], [[UPPER:%.*]]
403; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_SUB_1]])
404; CHECK-NEXT:    [[CMP_IDX_ULT_LEN:%.*]] = icmp ult i8 [[IDX:%.*]], [[LEN]]
405; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_IDX_ULT_LEN]])
406; CHECK-NEXT:    [[IDX_EXT:%.*]] = zext i8 [[IDX]] to i16
407; CHECK-NEXT:    [[DST_ADD_IDX:%.*]] = getelementptr inbounds i8, ptr [[DST]], i16 [[IDX_EXT]]
408; CHECK-NEXT:    [[CMP_IDX:%.*]] = icmp ult ptr [[DST_ADD_IDX]], [[UPPER]]
409; CHECK-NEXT:    ret i1 [[CMP_IDX]]
410;
411  %sgt.1 = icmp sgt i8 %len, 1
412  call void @llvm.assume(i1 %sgt.1)
413  %len.ext = zext i8 %len to i16
414  %dst.add.len = getelementptr inbounds i8, ptr %dst, i16 %len.ext
415  %dst.sub.1 = getelementptr inbounds i8, ptr %dst.add.len, i64 -2
416  %cmp.sub.1 = icmp ult ptr %dst.sub.1, %upper
417  call void @llvm.assume(i1 %cmp.sub.1)
418  %cmp.idx.ult.len = icmp ult i8 %idx, %len
419  call void @llvm.assume(i1 %cmp.idx.ult.len)
420  %idx.ext = zext i8 %idx to i16
421  %dst.add.idx = getelementptr inbounds i8, ptr %dst, i16 %idx.ext
422  %cmp.idx = icmp ult ptr %dst.add.idx, %upper
423  ret i1 %cmp.idx
424}
425
426define i1 @gep_sub_1_ult_var_idx_lower_bound(ptr %lower, ptr %src, i8 %len) {
427; CHECK-LABEL: @gep_sub_1_ult_var_idx_lower_bound(
428; CHECK-NEXT:  entry:
429; CHECK-NEXT:    [[SRC_UGE_LOWER:%.*]] = icmp uge ptr [[SRC:%.*]], [[LOWER:%.*]]
430; CHECK-NEXT:    call void @llvm.assume(i1 [[SRC_UGE_LOWER]])
431; CHECK-NEXT:    [[LEN_POS:%.*]] = icmp sge i8 [[LEN:%.*]], 0
432; CHECK-NEXT:    call void @llvm.assume(i1 [[LEN_POS]])
433; CHECK-NEXT:    [[GEP_LEN:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i8 [[LEN]]
434; CHECK-NEXT:    [[GEP_SUB_1:%.*]] = getelementptr inbounds i8, ptr [[GEP_LEN]], i8 -1
435; CHECK-NEXT:    [[RES:%.*]] = icmp ult ptr [[GEP_SUB_1]], [[LOWER]]
436; CHECK-NEXT:    ret i1 [[RES]]
437;
438entry:
439  %src.uge.lower = icmp uge ptr %src, %lower
440  call void @llvm.assume(i1 %src.uge.lower)
441
442  %len.pos = icmp sge i8 %len, 0
443  call void @llvm.assume(i1 %len.pos)
444
445  %gep.len = getelementptr inbounds i8, ptr %src, i8 %len
446  %gep.sub.1 = getelementptr inbounds i8, ptr %gep.len, i8 -1
447  %res = icmp ult ptr %gep.sub.1, %lower
448  ret i1 %res
449}
450
451define i1 @gep_sub_1_ult_var_idx_lower_bound_len_ne_0(ptr %lower, ptr %src, i8 %len) {
452; CHECK-LABEL: @gep_sub_1_ult_var_idx_lower_bound_len_ne_0(
453; CHECK-NEXT:  entry:
454; CHECK-NEXT:    [[LEN_NE_0:%.*]] = icmp ne i8 [[LEN:%.*]], 0
455; CHECK-NEXT:    call void @llvm.assume(i1 [[LEN_NE_0]])
456; CHECK-NEXT:    [[SRC_UGE_LOWER:%.*]] = icmp uge ptr [[SRC:%.*]], [[LOWER:%.*]]
457; CHECK-NEXT:    call void @llvm.assume(i1 [[SRC_UGE_LOWER]])
458; CHECK-NEXT:    [[LEN_POS:%.*]] = icmp sge i8 [[LEN]], 0
459; CHECK-NEXT:    call void @llvm.assume(i1 [[LEN_POS]])
460; CHECK-NEXT:    [[GEP_LEN:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i8 [[LEN]]
461; CHECK-NEXT:    [[GEP_SUB_1:%.*]] = getelementptr inbounds i8, ptr [[GEP_LEN]], i8 -1
462; CHECK-NEXT:    ret i1 false
463;
464entry:
465  %len.ne.0 = icmp ne i8 %len, 0
466  call void @llvm.assume(i1 %len.ne.0)
467
468  %src.uge.lower = icmp uge ptr %src, %lower
469  call void @llvm.assume(i1 %src.uge.lower)
470
471  %len.pos = icmp sge i8 %len, 0
472  call void @llvm.assume(i1 %len.pos)
473
474  %gep.len = getelementptr inbounds i8, ptr %src, i8 %len
475  %gep.sub.1 = getelementptr inbounds i8, ptr %gep.len, i8 -1
476  %res = icmp ult ptr %gep.sub.1, %lower
477  ret i1 %res
478}
479
480define i1 @gep_sub_2_ult_var_idx_lower_bound_len_ne_0(ptr %lower, ptr %src, i8 %len) {
481; CHECK-LABEL: @gep_sub_2_ult_var_idx_lower_bound_len_ne_0(
482; CHECK-NEXT:  entry:
483; CHECK-NEXT:    [[LEN_NE_0:%.*]] = icmp ne i8 [[LEN:%.*]], 0
484; CHECK-NEXT:    call void @llvm.assume(i1 [[LEN_NE_0]])
485; CHECK-NEXT:    [[SRC_UGE_LOWER:%.*]] = icmp uge ptr [[SRC:%.*]], [[LOWER:%.*]]
486; CHECK-NEXT:    call void @llvm.assume(i1 [[SRC_UGE_LOWER]])
487; CHECK-NEXT:    [[LEN_POS:%.*]] = icmp sge i8 [[LEN]], 0
488; CHECK-NEXT:    call void @llvm.assume(i1 [[LEN_POS]])
489; CHECK-NEXT:    [[GEP_LEN:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i8 [[LEN]]
490; CHECK-NEXT:    [[GEP_SUB_2:%.*]] = getelementptr inbounds i8, ptr [[GEP_LEN]], i8 -2
491; CHECK-NEXT:    [[RES:%.*]] = icmp ult ptr [[GEP_SUB_2]], [[LOWER]]
492; CHECK-NEXT:    ret i1 [[RES]]
493;
494entry:
495  %len.ne.0 = icmp ne i8 %len, 0
496  call void @llvm.assume(i1 %len.ne.0)
497
498  %src.uge.lower = icmp uge ptr %src, %lower
499  call void @llvm.assume(i1 %src.uge.lower)
500
501  %len.pos = icmp sge i8 %len, 0
502  call void @llvm.assume(i1 %len.pos)
503
504  %gep.len = getelementptr inbounds i8, ptr %src, i8 %len
505  %gep.sub.2 = getelementptr inbounds i8, ptr %gep.len, i8 -2
506  %res = icmp ult ptr %gep.sub.2, %lower
507  ret i1 %res
508}
509
510define i1 @gep_i16_sub_1_uge_inbounds(ptr %dst, ptr %lower) {
511; CHECK-LABEL: @gep_i16_sub_1_uge_inbounds(
512; CHECK-NEXT:    [[PRE:%.*]] = icmp uge ptr [[DST:%.*]], [[LOWER:%.*]]
513; CHECK-NEXT:    call void @llvm.assume(i1 [[PRE]])
514; CHECK-NEXT:    [[DST_ADD_3:%.*]] = getelementptr inbounds i8, ptr [[DST]], i64 3
515; CHECK-NEXT:    [[DST_SUB_1:%.*]] = getelementptr inbounds i16, ptr [[DST_ADD_3]], i64 -1
516; CHECK-NEXT:    [[DST_SUB_2:%.*]] = getelementptr inbounds i16, ptr [[DST_ADD_3]], i64 -2
517; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 false, true
518; CHECK-NEXT:    [[DST_SUB_3:%.*]] = getelementptr inbounds i16, ptr [[DST_ADD_3]], i64 -3
519; CHECK-NEXT:    [[CMP_SUB_3:%.*]] = icmp ule ptr [[DST_SUB_3]], [[LOWER]]
520; CHECK-NEXT:    [[RES_2:%.*]] = xor i1 [[RES_1]], [[CMP_SUB_3]]
521; CHECK-NEXT:    ret i1 [[RES_2]]
522;
523  %pre = icmp uge ptr %dst, %lower
524  call void @llvm.assume(i1 %pre)
525  %dst.add.3 = getelementptr inbounds i8, ptr %dst, i64 3
526  %dst.sub.1 = getelementptr inbounds i16, ptr %dst.add.3, i64 -1
527  %cmp.sub.1 = icmp ule ptr %dst.sub.1, %lower
528  %dst.sub.2 = getelementptr inbounds i16, ptr %dst.add.3, i64 -2
529  %cmp.sub.2 = icmp ule ptr %dst.sub.2, %dst
530  %res.1 = xor i1 %cmp.sub.1, %cmp.sub.2
531  %dst.sub.3 = getelementptr inbounds i16, ptr %dst.add.3, i64 -3
532  %cmp.sub.3 = icmp ule ptr %dst.sub.3, %lower
533  %res.2 = xor i1 %res.1, %cmp.sub.3
534  ret i1 %res.2
535}
536
537define i1 @gep_i16_sub_1_uge_inbounds_var_idx(ptr %dst, i64 %off) {
538; CHECK-LABEL: @gep_i16_sub_1_uge_inbounds_var_idx(
539; CHECK-NEXT:    [[OFF_UGE:%.*]] = icmp sge i64 [[OFF:%.*]], 1
540; CHECK-NEXT:    call void @llvm.assume(i1 [[OFF_UGE]])
541; CHECK-NEXT:    [[DST_ADD_3:%.*]] = getelementptr inbounds i8, ptr [[DST:%.*]], i64 [[OFF]]
542; CHECK-NEXT:    [[DST_SUB_1:%.*]] = getelementptr inbounds i16, ptr [[DST_ADD_3]], i32 -1
543; CHECK-NEXT:    [[CMP_SUB_1:%.*]] = icmp ule ptr [[DST_SUB_1]], [[DST]]
544; CHECK-NEXT:    [[DST_SUB_2:%.*]] = getelementptr inbounds i16, ptr [[DST_ADD_3]], i64 -2
545; CHECK-NEXT:    [[CMP_SUB_2:%.*]] = icmp ule ptr [[DST_SUB_2]], [[DST]]
546; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 [[CMP_SUB_1]], [[CMP_SUB_2]]
547; CHECK-NEXT:    [[DST_SUB_3:%.*]] = getelementptr inbounds i16, ptr [[DST_ADD_3]], i64 -3
548; CHECK-NEXT:    [[CMP_SUB_3:%.*]] = icmp ule ptr [[DST_SUB_3]], [[DST]]
549; CHECK-NEXT:    [[RES_2:%.*]] = xor i1 [[RES_1]], [[CMP_SUB_3]]
550; CHECK-NEXT:    ret i1 [[RES_2]]
551;
552  %off.uge = icmp sge i64 %off, 1
553  call void @llvm.assume(i1 %off.uge)
554  %dst.add.3 = getelementptr inbounds i8, ptr %dst, i64 %off
555  %dst.sub.1 = getelementptr inbounds i16, ptr %dst.add.3, i32 -1
556  %cmp.sub.1 = icmp ule ptr %dst.sub.1, %dst
557  %dst.sub.2 = getelementptr inbounds i16, ptr %dst.add.3, i64 -2
558  %cmp.sub.2 = icmp ule ptr %dst.sub.2, %dst
559  %res.1 = xor i1 %cmp.sub.1, %cmp.sub.2
560  %dst.sub.3 = getelementptr inbounds i16, ptr %dst.add.3, i64 -3
561  %cmp.sub.3 = icmp ule ptr %dst.sub.3, %dst
562  %res.2 = xor i1 %res.1, %cmp.sub.3
563  ret i1 %res.2
564}
565
566define i1 @gep_i32_two_indices_known_lt_and_positive(ptr %a, i8 %idx.1, i8 %idx.2) {
567; CHECK-LABEL: @gep_i32_two_indices_known_lt_and_positive(
568; CHECK-NEXT:    [[LT:%.*]] = icmp ult i8 [[IDX_1:%.*]], [[IDX_2:%.*]]
569; CHECK-NEXT:    call void @llvm.assume(i1 [[LT]])
570; CHECK-NEXT:    [[IDX_1_POS:%.*]] = icmp sge i8 [[IDX_1]], 0
571; CHECK-NEXT:    [[IDX_2_POS:%.*]] = icmp sge i8 [[IDX_2]], 0
572; CHECK-NEXT:    call void @llvm.assume(i1 [[IDX_1_POS]])
573; CHECK-NEXT:    call void @llvm.assume(i1 [[IDX_2_POS]])
574; CHECK-NEXT:    [[GEP_1:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i8 [[IDX_1]]
575; CHECK-NEXT:    [[GEP_2:%.*]] = getelementptr inbounds i32, ptr [[GEP_1]], i8 -3
576; CHECK-NEXT:    [[GEP_3:%.*]] = getelementptr inbounds i32, ptr [[A]], i8 [[IDX_2]]
577; CHECK-NEXT:    [[GEP_4:%.*]] = getelementptr inbounds i32, ptr [[GEP_3]], i8 -3
578; CHECK-NEXT:    ret i1 true
579;
580  %lt = icmp ult i8 %idx.1, %idx.2
581  call void @llvm.assume(i1 %lt)
582  %idx.1.pos = icmp sge i8 %idx.1, 0
583  %idx.2.pos = icmp sge i8 %idx.2, 0
584  call void @llvm.assume(i1 %idx.1.pos)
585  call void @llvm.assume(i1 %idx.2.pos)
586  %gep.1 = getelementptr inbounds i32, ptr %a, i8 %idx.1
587  %gep.2 = getelementptr inbounds i32, ptr %gep.1, i8 -3
588  %gep.3 = getelementptr inbounds i32, ptr %a, i8 %idx.2
589  %gep.4 = getelementptr inbounds i32, ptr %gep.3, i8 -3
590  %c = icmp ult ptr %gep.2, %gep.4
591  ret i1 %c
592}
593
594define i1 @gep_i32_two_indices_known_lt_and_not_known_positive(ptr %a, i8 %idx.1, i8 %idx.2) {
595; CHECK-LABEL: @gep_i32_two_indices_known_lt_and_not_known_positive(
596; CHECK-NEXT:    [[LT:%.*]] = icmp ult i8 [[IDX_1:%.*]], [[IDX_2:%.*]]
597; CHECK-NEXT:    call void @llvm.assume(i1 [[LT]])
598; CHECK-NEXT:    [[GEP_1:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i8 [[IDX_1]]
599; CHECK-NEXT:    [[GEP_2:%.*]] = getelementptr inbounds i32, ptr [[GEP_1]], i8 -3
600; CHECK-NEXT:    [[GEP_3:%.*]] = getelementptr inbounds i32, ptr [[A]], i8 [[IDX_2]]
601; CHECK-NEXT:    [[GEP_4:%.*]] = getelementptr inbounds i32, ptr [[GEP_3]], i8 -3
602; CHECK-NEXT:    [[C:%.*]] = icmp ult ptr [[GEP_2]], [[GEP_4]]
603; CHECK-NEXT:    ret i1 [[C]]
604;
605  %lt = icmp ult i8 %idx.1, %idx.2
606  call void @llvm.assume(i1 %lt)
607  %gep.1 = getelementptr inbounds i32, ptr %a, i8 %idx.1
608  %gep.2 = getelementptr inbounds i32, ptr %gep.1, i8 -3
609  %gep.3 = getelementptr inbounds i32, ptr %a, i8 %idx.2
610  %gep.4 = getelementptr inbounds i32, ptr %gep.3, i8 -3
611  %c = icmp ult ptr %gep.2, %gep.4
612  ret i1 %c
613}
614
615define i1 @gep_i32_two_indices_known_positive_but_not_lt(ptr %a, i8 %idx.1, i8 %idx.2) {
616; CHECK-LABEL: @gep_i32_two_indices_known_positive_but_not_lt(
617; CHECK-NEXT:    [[IDX_1_POS:%.*]] = icmp sge i8 [[IDX_1:%.*]], 0
618; CHECK-NEXT:    [[IDX_2_POS:%.*]] = icmp sge i8 [[IDX_2:%.*]], 0
619; CHECK-NEXT:    call void @llvm.assume(i1 [[IDX_1_POS]])
620; CHECK-NEXT:    call void @llvm.assume(i1 [[IDX_2_POS]])
621; CHECK-NEXT:    [[GEP_1:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i8 [[IDX_1]]
622; CHECK-NEXT:    [[GEP_2:%.*]] = getelementptr inbounds i32, ptr [[GEP_1]], i8 -3
623; CHECK-NEXT:    [[GEP_3:%.*]] = getelementptr inbounds i32, ptr [[A]], i8 [[IDX_2]]
624; CHECK-NEXT:    [[GEP_4:%.*]] = getelementptr inbounds i32, ptr [[GEP_3]], i8 -3
625; CHECK-NEXT:    [[C:%.*]] = icmp ult ptr [[GEP_2]], [[GEP_4]]
626; CHECK-NEXT:    ret i1 [[C]]
627;
628  %idx.1.pos = icmp sge i8 %idx.1, 0
629  %idx.2.pos = icmp sge i8 %idx.2, 0
630  call void @llvm.assume(i1 %idx.1.pos)
631  call void @llvm.assume(i1 %idx.2.pos)
632  %gep.1 = getelementptr inbounds i32, ptr %a, i8 %idx.1
633  %gep.2 = getelementptr inbounds i32, ptr %gep.1, i8 -3
634  %gep.3 = getelementptr inbounds i32, ptr %a, i8 %idx.2
635  %gep.4 = getelementptr inbounds i32, ptr %gep.3, i8 -3
636  %c = icmp ult ptr %gep.2, %gep.4
637  ret i1 %c
638}
639