xref: /llvm-project/llvm/test/Transforms/ConstraintElimination/gep-arithmetic-different-types.ll (revision 13ffde316a8541d77116bd18f73efada236617f3)
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 %A, ptr %upper) {
7; CHECK-LABEL: @gep_constant_positive_index(
8; CHECK-NEXT:    [[ADD_I8_4:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i64 4
9; CHECK-NEXT:    [[C_0:%.*]] = icmp ult ptr [[ADD_I8_4]], [[UPPER:%.*]]
10; CHECK-NEXT:    call void @llvm.assume(i1 [[C_0]])
11; CHECK-NEXT:    [[ADD_I16_4:%.*]] = getelementptr inbounds i16, ptr [[A]], i64 4
12; CHECK-NEXT:    [[C_1:%.*]] = icmp ult ptr [[ADD_I16_4]], [[UPPER]]
13; CHECK-NEXT:    [[ADD_I16_2:%.*]] = getelementptr inbounds i16, ptr [[A]], i64 2
14; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 [[C_1]], true
15; CHECK-NEXT:    ret i1 [[RES_1]]
16;
17  %add.i8.4 = getelementptr inbounds i8, ptr %A, i64 4
18  %c.0 = icmp ult ptr %add.i8.4, %upper
19  call void @llvm.assume(i1 %c.0)
20
21  %add.i16.4 = getelementptr inbounds i16, ptr %A, i64 4
22  %c.1 = icmp ult ptr %add.i16.4, %upper
23
24  %add.i16.2 = getelementptr inbounds i16, ptr %A, i64 2
25  %t.1 = icmp ult ptr %add.i16.2, %upper
26  %res.1 = xor i1 %c.1, %t.1
27  ret i1 %res.1
28}
29
30define i1 @gep_constant_positive_index_chained(ptr %A, ptr %upper) {
31; CHECK-LABEL: @gep_constant_positive_index_chained(
32; CHECK-NEXT:    [[ADD_I8_4:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i64 4
33; CHECK-NEXT:    [[C_0:%.*]] = icmp ult ptr [[ADD_I8_4]], [[UPPER:%.*]]
34; CHECK-NEXT:    call void @llvm.assume(i1 [[C_0]])
35; CHECK-NEXT:    [[ADD_I8_1:%.*]] = getelementptr inbounds i8, ptr [[A]], i64 1
36; CHECK-NEXT:    [[ADD_I16_1:%.*]] = getelementptr inbounds i16, ptr [[ADD_I8_1]], i64 1
37; CHECK-NEXT:    [[ADD_I16_2:%.*]] = getelementptr inbounds i16, ptr [[ADD_I8_1]], i64 2
38; CHECK-NEXT:    [[C_1:%.*]] = icmp ult ptr [[ADD_I16_2]], [[UPPER]]
39; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 true, [[C_1]]
40; CHECK-NEXT:    ret i1 [[RES_1]]
41;
42  %add.i8.4 = getelementptr inbounds i8, ptr %A, i64 4
43  %c.0 = icmp ult ptr %add.i8.4, %upper
44  call void @llvm.assume(i1 %c.0)
45
46  %add.i8.1 = getelementptr inbounds i8, ptr %A, i64 1
47
48  %add.i16.1 = getelementptr inbounds i16, ptr %add.i8.1, i64 1
49  %t.1 = icmp ult ptr %add.i16.1, %upper
50  %add.i16.2 = getelementptr inbounds i16, ptr %add.i8.1, i64 2
51  %c.1 = icmp ult ptr %add.i16.2, %upper
52  %res.1 = xor i1 %t.1, %c.1
53  ret i1 %res.1
54}
55
56define i1 @gep_var_positive_index(ptr %A, ptr %upper, i8 %idx) {
57; CHECK-LABEL: @gep_var_positive_index(
58; CHECK-NEXT:    [[IDX_POS:%.*]] = icmp sge i8 [[IDX:%.*]], 0
59; CHECK-NEXT:    call void @llvm.assume(i1 [[IDX_POS]])
60; CHECK-NEXT:    [[ADD_I16_IDX:%.*]] = getelementptr inbounds i16, ptr [[A:%.*]], i8 [[IDX]]
61; CHECK-NEXT:    [[C_0:%.*]] = icmp ult ptr [[ADD_I16_IDX]], [[UPPER:%.*]]
62; CHECK-NEXT:    call void @llvm.assume(i1 [[C_0]])
63; CHECK-NEXT:    [[ADD_I32_IDX:%.*]] = getelementptr inbounds i32, ptr [[A]], i8 [[IDX]]
64; CHECK-NEXT:    [[C_1:%.*]] = icmp ult ptr [[ADD_I32_IDX]], [[UPPER]]
65; CHECK-NEXT:    [[ADD_I8_IDX:%.*]] = getelementptr inbounds i8, ptr [[A]], i8 [[IDX]]
66; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 [[C_1]], true
67; CHECK-NEXT:    ret i1 [[RES_1]]
68;
69  %idx.pos = icmp sge i8 %idx, 0
70  call void @llvm.assume(i1 %idx.pos)
71  %add.i16.idx = getelementptr inbounds i16, ptr %A, i8 %idx
72  %c.0 = icmp ult ptr %add.i16.idx, %upper
73  call void @llvm.assume(i1 %c.0)
74
75  %add.i32.idx = getelementptr inbounds i32, ptr %A, i8 %idx
76  %c.1 = icmp ult ptr %add.i32.idx, %upper
77  %add.i8.idx = getelementptr inbounds i8, ptr %A, i8 %idx
78  %t.1 = icmp ult ptr %add.i8.idx, %upper
79  %res.1 = xor i1 %c.1, %t.1
80  ret i1 %res.1
81}
82
83define i1 @gep_add_nsw_positive_index(ptr %A, ptr %upper, i8 %idx) {
84; CHECK-LABEL: @gep_add_nsw_positive_index(
85; CHECK-NEXT:    [[IDX_POS:%.*]] = icmp sge i8 [[IDX:%.*]], 0
86; CHECK-NEXT:    call void @llvm.assume(i1 [[IDX_POS]])
87; CHECK-NEXT:    [[IDX_3:%.*]] = add nsw i8 [[IDX]], 3
88; CHECK-NEXT:    [[ADD_I8_IDX_3:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i8 [[IDX_3]]
89; CHECK-NEXT:    [[C_0:%.*]] = icmp ult ptr [[ADD_I8_IDX_3]], [[UPPER:%.*]]
90; CHECK-NEXT:    call void @llvm.assume(i1 [[C_0]])
91; CHECK-NEXT:    [[IDX_1:%.*]] = add nsw i8 [[IDX]], 1
92; CHECK-NEXT:    [[ADD_I32_IDX_1:%.*]] = getelementptr inbounds i32, ptr [[A]], i8 [[IDX_1]]
93; CHECK-NEXT:    [[C_1:%.*]] = icmp ult ptr [[ADD_I32_IDX_1]], [[UPPER]]
94; CHECK-NEXT:    [[ADD_I8_IDX_1:%.*]] = getelementptr inbounds i8, ptr [[A]], i8 [[IDX_1]]
95; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 [[C_1]], true
96; CHECK-NEXT:    [[ADD_I16_IDX_1:%.*]] = getelementptr inbounds i16, ptr [[A]], i8 [[IDX_1]]
97; CHECK-NEXT:    [[C_2:%.*]] = icmp ult ptr [[ADD_I16_IDX_1]], [[UPPER]]
98; CHECK-NEXT:    [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_2]]
99; CHECK-NEXT:    ret i1 [[RES_2]]
100;
101  %idx.pos = icmp sge i8 %idx, 0
102  call void @llvm.assume(i1 %idx.pos)
103  %idx.3 = add nsw i8 %idx, 3
104  %add.i8.idx.3 = getelementptr inbounds i8, ptr %A, i8 %idx.3
105  %c.0 = icmp ult ptr %add.i8.idx.3, %upper
106  call void @llvm.assume(i1 %c.0)
107
108  %idx.1 = add nsw i8 %idx, 1
109  %add.i32.idx.1 = getelementptr inbounds i32, ptr %A, i8 %idx.1
110  %c.1 = icmp ult ptr %add.i32.idx.1, %upper
111  %add.i8.idx.1 = getelementptr inbounds i8, ptr %A, i8 %idx.1
112  %t.1 = icmp ult ptr %add.i8.idx.1, %upper
113  %res.1 = xor i1 %c.1, %t.1
114
115  %add.i16.idx.1 = getelementptr inbounds i16, ptr %A, i8 %idx.1
116  %c.2 = icmp ult ptr %add.i16.idx.1, %upper
117  %res.2 = xor i1 %res.1, %c.2
118  ret i1 %res.2
119}
120
121
122define i1 @gep_shl_nsw_positive_index(ptr %A, ptr %upper, i8 %idx) {
123; CHECK-LABEL: @gep_shl_nsw_positive_index(
124; CHECK-NEXT:    [[IDX_POS:%.*]] = icmp sge i8 [[IDX:%.*]], 0
125; CHECK-NEXT:    call void @llvm.assume(i1 [[IDX_POS]])
126; CHECK-NEXT:    [[IDX_2:%.*]] = shl nsw i8 [[IDX]], 2
127; CHECK-NEXT:    [[ADD_I8_IDX_2:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i8 [[IDX_2]]
128; CHECK-NEXT:    [[C_0:%.*]] = icmp ult ptr [[ADD_I8_IDX_2]], [[UPPER:%.*]]
129; CHECK-NEXT:    call void @llvm.assume(i1 [[C_0]])
130; CHECK-NEXT:    [[IDX_1:%.*]] = shl nsw i8 [[IDX]], 1
131; CHECK-NEXT:    [[ADD_I32_IDX_1:%.*]] = getelementptr inbounds i32, ptr [[A]], i8 [[IDX_1]]
132; CHECK-NEXT:    [[C_1:%.*]] = icmp ult ptr [[ADD_I32_IDX_1]], [[UPPER]]
133; CHECK-NEXT:    [[ADD_I8_IDX_1:%.*]] = getelementptr inbounds i8, ptr [[A]], i8 [[IDX_1]]
134; CHECK-NEXT:    [[T_1:%.*]] = icmp ult ptr [[ADD_I8_IDX_1]], [[UPPER]]
135; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 [[C_1]], [[T_1]]
136; CHECK-NEXT:    ret i1 [[RES_1]]
137;
138  %idx.pos = icmp sge i8 %idx, 0
139  call void @llvm.assume(i1 %idx.pos)
140  %idx.2 = shl nsw i8 %idx, 2
141  %add.i8.idx.2 = getelementptr inbounds i8, ptr %A, i8 %idx.2
142  %c.0 = icmp ult ptr %add.i8.idx.2, %upper
143  call void @llvm.assume(i1 %c.0)
144
145  %idx.1 = shl nsw i8 %idx, 1
146  %add.i32.idx.1 = getelementptr inbounds i32, ptr %A, i8 %idx.1
147  %c.1 = icmp ult ptr %add.i32.idx.1, %upper
148  %add.i8.idx.1 = getelementptr inbounds i8, ptr %A, i8 %idx.1
149  %t.1 = icmp ult ptr %add.i8.idx.1, %upper
150  %res.1 = xor i1 %c.1, %t.1
151  ret i1 %res.1
152}
153
154define i1 @gep_zext_add_nuw_nsw_index(ptr %A, ptr %upper, i8 %idx) {
155; CHECK-LABEL: @gep_zext_add_nuw_nsw_index(
156; CHECK-NEXT:    [[IDX_3:%.*]] = add nuw nsw i8 [[IDX:%.*]], 3
157; CHECK-NEXT:    [[IDX_3_EXT:%.*]] = zext i8 [[IDX_3]] to i16
158; CHECK-NEXT:    [[ADD_I8_IDX_3:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i16 [[IDX_3_EXT]]
159; CHECK-NEXT:    [[C_0:%.*]] = icmp ult ptr [[ADD_I8_IDX_3]], [[UPPER:%.*]]
160; CHECK-NEXT:    call void @llvm.assume(i1 [[C_0]])
161; CHECK-NEXT:    [[IDX_1:%.*]] = add nuw nsw i8 [[IDX]], 1
162; CHECK-NEXT:    [[IDX_1_EXT:%.*]] = zext i8 [[IDX_1]] to i16
163; CHECK-NEXT:    [[ADD_I32_IDX_1:%.*]] = getelementptr inbounds i32, ptr [[A]], i16 [[IDX_1_EXT]]
164; CHECK-NEXT:    [[C_1:%.*]] = icmp ult ptr [[ADD_I32_IDX_1]], [[UPPER]]
165; CHECK-NEXT:    [[ADD_I8_IDX_1:%.*]] = getelementptr inbounds i8, ptr [[A]], i16 [[IDX_1_EXT]]
166; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 [[C_1]], true
167; CHECK-NEXT:    [[ADD_I16_IDX_1:%.*]] = getelementptr inbounds i16, ptr [[A]], i16 [[IDX_1_EXT]]
168; CHECK-NEXT:    [[C_2:%.*]] = icmp ult ptr [[ADD_I16_IDX_1]], [[UPPER]]
169; CHECK-NEXT:    [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_2]]
170; CHECK-NEXT:    ret i1 [[RES_2]]
171;
172  %idx.3 = add nuw nsw i8 %idx, 3
173  %idx.3.ext = zext i8 %idx.3 to i16
174  %add.i8.idx.3 = getelementptr inbounds i8, ptr %A, i16 %idx.3.ext
175  %c.0 = icmp ult ptr %add.i8.idx.3, %upper
176  call void @llvm.assume(i1 %c.0)
177
178  %idx.1 = add nuw nsw i8 %idx, 1
179  %idx.1.ext = zext i8 %idx.1 to i16
180  %add.i32.idx.1 = getelementptr inbounds i32, ptr %A, i16 %idx.1.ext
181  %c.1 = icmp ult ptr %add.i32.idx.1, %upper
182  %add.i8.idx.1 = getelementptr inbounds i8, ptr %A, i16 %idx.1.ext
183  %t.1 = icmp ult ptr %add.i8.idx.1, %upper
184  %res.1 = xor i1 %c.1, %t.1
185
186  %add.i16.idx.1 = getelementptr inbounds i16, ptr %A, i16 %idx.1.ext
187  %c.2 = icmp ult ptr %add.i16.idx.1, %upper
188  %res.2 = xor i1 %res.1, %c.2
189
190  ret i1 %res.2
191}
192
193define i1 @gep_zext_add_nuw_index(ptr %A, ptr %upper, i8 %idx) {
194; CHECK-LABEL: @gep_zext_add_nuw_index(
195; CHECK-NEXT:    [[IDX_2:%.*]] = add nuw i8 [[IDX:%.*]], 2
196; CHECK-NEXT:    [[IDX_2_EXT:%.*]] = zext i8 [[IDX_2]] to i16
197; CHECK-NEXT:    [[ADD_I8_IDX_2:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i16 [[IDX_2_EXT]]
198; CHECK-NEXT:    [[C_0:%.*]] = icmp ult ptr [[ADD_I8_IDX_2]], [[UPPER:%.*]]
199; CHECK-NEXT:    call void @llvm.assume(i1 [[C_0]])
200; CHECK-NEXT:    [[IDX_1:%.*]] = add nuw i8 [[IDX]], 1
201; CHECK-NEXT:    [[IDX_1_EXT:%.*]] = zext i8 [[IDX_1]] to i16
202; CHECK-NEXT:    [[ADD_I32_IDX_1:%.*]] = getelementptr inbounds i32, ptr [[A]], i16 [[IDX_1_EXT]]
203; CHECK-NEXT:    [[C_1:%.*]] = icmp ult ptr [[ADD_I32_IDX_1]], [[UPPER]]
204; CHECK-NEXT:    [[ADD_I8_IDX_1:%.*]] = getelementptr inbounds i8, ptr [[A]], i16 [[IDX_1_EXT]]
205; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 [[C_1]], true
206; CHECK-NEXT:    ret i1 [[RES_1]]
207;
208  %idx.2 = add nuw i8 %idx, 2
209  %idx.2.ext = zext i8 %idx.2 to i16
210  %add.i8.idx.2 = getelementptr inbounds i8, ptr %A, i16 %idx.2.ext
211  %c.0 = icmp ult ptr %add.i8.idx.2, %upper
212  call void @llvm.assume(i1 %c.0)
213
214  %idx.1 = add nuw i8 %idx, 1
215  %idx.1.ext = zext i8 %idx.1 to i16
216  %add.i32.idx.1 = getelementptr inbounds i32, ptr %A, i16 %idx.1.ext
217  %c.1 = icmp ult ptr %add.i32.idx.1, %upper
218  %add.i8.idx.1 = getelementptr inbounds i8, ptr %A, i16 %idx.1.ext
219  %t.1 = icmp ult ptr %add.i8.idx.1, %upper
220  %res.1 = xor i1 %c.1, %t.1
221  ret i1 %res.1
222}
223
224define i1 @gep_zext_add_nsw_index(ptr %A, ptr %upper, i8 %idx) {
225; CHECK-LABEL: @gep_zext_add_nsw_index(
226; CHECK-NEXT:    [[IDX_2:%.*]] = add nsw i8 [[IDX:%.*]], 2
227; CHECK-NEXT:    [[IDX_2_EXT:%.*]] = zext i8 [[IDX_2]] to i16
228; CHECK-NEXT:    [[ADD_I8_IDX_2:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i16 [[IDX_2_EXT]]
229; CHECK-NEXT:    [[C_0:%.*]] = icmp ult ptr [[ADD_I8_IDX_2]], [[UPPER:%.*]]
230; CHECK-NEXT:    call void @llvm.assume(i1 [[C_0]])
231; CHECK-NEXT:    [[IDX_1:%.*]] = add nsw i8 [[IDX]], 1
232; CHECK-NEXT:    [[IDX_1_EXT:%.*]] = zext i8 [[IDX_1]] to i16
233; CHECK-NEXT:    [[ADD_I32_IDX_1:%.*]] = getelementptr inbounds i32, ptr [[A]], i16 [[IDX_1_EXT]]
234; CHECK-NEXT:    [[C_1:%.*]] = icmp ult ptr [[ADD_I32_IDX_1]], [[UPPER]]
235; CHECK-NEXT:    [[ADD_I8_IDX_1:%.*]] = getelementptr inbounds i8, ptr [[A]], i16 [[IDX_1_EXT]]
236; CHECK-NEXT:    [[T_1:%.*]] = icmp ult ptr [[ADD_I8_IDX_1]], [[UPPER]]
237; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 [[C_1]], [[T_1]]
238; CHECK-NEXT:    ret i1 [[RES_1]]
239;
240  %idx.2 = add nsw i8 %idx, 2
241  %idx.2.ext = zext i8 %idx.2 to i16
242  %add.i8.idx.2 = getelementptr inbounds i8, ptr %A, i16 %idx.2.ext
243  %c.0 = icmp ult ptr %add.i8.idx.2, %upper
244  call void @llvm.assume(i1 %c.0)
245
246  %idx.1 = add nsw i8 %idx, 1
247  %idx.1.ext = zext i8 %idx.1 to i16
248  %add.i32.idx.1 = getelementptr inbounds i32, ptr %A, i16 %idx.1.ext
249  %c.1 = icmp ult ptr %add.i32.idx.1, %upper
250  %add.i8.idx.1 = getelementptr inbounds i8, ptr %A, i16 %idx.1.ext
251  %t.1 = icmp ult ptr %add.i8.idx.1, %upper
252  %res.1 = xor i1 %c.1, %t.1
253  ret i1 %res.1
254}
255
256define i1 @gep_zext_index(ptr %A, ptr %upper, i8 %idx.1, i8 %idx.2) {
257; CHECK-LABEL: @gep_zext_index(
258; CHECK-NEXT:    [[C_0:%.*]] = icmp ult i8 [[IDX_1:%.*]], [[IDX_2:%.*]]
259; CHECK-NEXT:    call void @llvm.assume(i1 [[C_0]])
260; CHECK-NEXT:    [[IDX_2_EXT:%.*]] = zext i8 [[IDX_2]] to i16
261; CHECK-NEXT:    [[ADD_I8_IDX_2:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i16 [[IDX_2_EXT]]
262; CHECK-NEXT:    [[IDX_1_EXT:%.*]] = zext i8 [[IDX_1]] to i16
263; CHECK-NEXT:    [[ADD_I32_IDX_1:%.*]] = getelementptr inbounds i32, ptr [[A]], i16 [[IDX_1_EXT]]
264; CHECK-NEXT:    [[C_1:%.*]] = icmp ult ptr [[ADD_I32_IDX_1]], [[ADD_I8_IDX_2]]
265; CHECK-NEXT:    [[ADD_I8_IDX_1:%.*]] = getelementptr inbounds i8, ptr [[A]], i16 [[IDX_1_EXT]]
266; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 [[C_1]], true
267; CHECK-NEXT:    ret i1 [[RES_1]]
268;
269  %c.0 = icmp ult i8 %idx.1, %idx.2
270  call void @llvm.assume(i1 %c.0)
271
272
273  %idx.2.ext = zext i8 %idx.2 to i16
274  %add.i8.idx.2 = getelementptr inbounds i8, ptr %A, i16 %idx.2.ext
275  %idx.1.ext = zext i8 %idx.1 to i16
276  %add.i32.idx.1 = getelementptr inbounds i32, ptr %A, i16 %idx.1.ext
277  %c.1 = icmp ult ptr %add.i32.idx.1, %add.i8.idx.2
278  %add.i8.idx.1 = getelementptr inbounds i8, ptr %A, i16 %idx.1.ext
279  %t.1 = icmp ult ptr %add.i8.idx.1, %add.i8.idx.2
280  %res.1 = xor i1 %c.1, %t.1
281  ret i1 %res.1
282}
283
284define i1 @gep_zext_shl_nsw_index(ptr %A, ptr %upper, i8 %idx) {
285; CHECK-LABEL: @gep_zext_shl_nsw_index(
286; CHECK-NEXT:    [[IDX_2:%.*]] = shl nsw i8 [[IDX:%.*]], 2
287; CHECK-NEXT:    [[IDX_2_EXT:%.*]] = zext i8 [[IDX_2]] to i16
288; CHECK-NEXT:    [[ADD_I8_IDX_2:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i16 [[IDX_2_EXT]]
289; CHECK-NEXT:    [[C_0:%.*]] = icmp ult ptr [[ADD_I8_IDX_2]], [[UPPER:%.*]]
290; CHECK-NEXT:    call void @llvm.assume(i1 [[C_0]])
291; CHECK-NEXT:    [[IDX_1:%.*]] = shl nsw i8 [[IDX]], 1
292; CHECK-NEXT:    [[IDX_1_EXT:%.*]] = zext i8 [[IDX_1]] to i16
293; CHECK-NEXT:    [[ADD_I32_IDX_1:%.*]] = getelementptr inbounds i32, ptr [[A]], i16 [[IDX_1_EXT]]
294; CHECK-NEXT:    [[C_1:%.*]] = icmp ult ptr [[ADD_I32_IDX_1]], [[UPPER]]
295; CHECK-NEXT:    [[ADD_I8_IDX_1:%.*]] = getelementptr inbounds i8, ptr [[A]], i16 [[IDX_1_EXT]]
296; CHECK-NEXT:    [[T_1:%.*]] = icmp ult ptr [[ADD_I8_IDX_1]], [[UPPER]]
297; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 [[C_1]], [[T_1]]
298; CHECK-NEXT:    ret i1 [[RES_1]]
299;
300  %idx.2 = shl nsw i8 %idx, 2
301  %idx.2.ext = zext i8 %idx.2 to i16
302  %add.i8.idx.2 = getelementptr inbounds i8, ptr %A, i16 %idx.2.ext
303  %c.0 = icmp ult ptr %add.i8.idx.2, %upper
304  call void @llvm.assume(i1 %c.0)
305
306  %idx.1 = shl nsw i8 %idx, 1
307  %idx.1.ext = zext i8 %idx.1 to i16
308  %add.i32.idx.1 = getelementptr inbounds i32, ptr %A, i16 %idx.1.ext
309  %c.1 = icmp ult ptr %add.i32.idx.1, %upper
310  %add.i8.idx.1 = getelementptr inbounds i8, ptr %A, i16 %idx.1.ext
311  %t.1 = icmp ult ptr %add.i8.idx.1, %upper
312  %res.1 = xor i1 %c.1, %t.1
313  ret i1 %res.1
314}
315
316define i1 @gep_zext_shl_nuw_index(ptr %A, ptr %upper, i8 %idx) {
317; CHECK-LABEL: @gep_zext_shl_nuw_index(
318; CHECK-NEXT:    [[IDX_POS:%.*]] = icmp sgt i8 [[IDX:%.*]], 0
319; CHECK-NEXT:    call void @llvm.assume(i1 [[IDX_POS]])
320; CHECK-NEXT:    [[IDX_2:%.*]] = shl nuw i8 [[IDX]], 2
321; CHECK-NEXT:    [[IDX_2_EXT:%.*]] = zext i8 [[IDX_2]] to i16
322; CHECK-NEXT:    [[ADD_I8_IDX_2:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i16 [[IDX_2_EXT]]
323; CHECK-NEXT:    [[C_0:%.*]] = icmp ult ptr [[ADD_I8_IDX_2]], [[UPPER:%.*]]
324; CHECK-NEXT:    call void @llvm.assume(i1 [[C_0]])
325; CHECK-NEXT:    [[IDX_1:%.*]] = shl nuw i8 [[IDX]], 1
326; CHECK-NEXT:    [[IDX_1_EXT:%.*]] = zext i8 [[IDX_1]] to i16
327; CHECK-NEXT:    [[ADD_I32_IDX_1:%.*]] = getelementptr inbounds i32, ptr [[A]], i16 [[IDX_1_EXT]]
328; CHECK-NEXT:    [[C_1:%.*]] = icmp ult ptr [[ADD_I32_IDX_1]], [[UPPER]]
329; CHECK-NEXT:    [[ADD_I8_IDX_1:%.*]] = getelementptr inbounds i8, ptr [[A]], i16 [[IDX_1_EXT]]
330; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 [[C_1]], true
331; CHECK-NEXT:    ret i1 [[RES_1]]
332;
333  %idx.pos = icmp sgt i8 %idx, 0
334  call void @llvm.assume(i1 %idx.pos)
335  %idx.2 = shl nuw i8 %idx, 2
336  %idx.2.ext = zext i8 %idx.2 to i16
337  %add.i8.idx.2 = getelementptr inbounds i8, ptr %A, i16 %idx.2.ext
338  %c.0 = icmp ult ptr %add.i8.idx.2, %upper
339  call void @llvm.assume(i1 %c.0)
340
341  %idx.1 = shl nuw i8 %idx, 1
342  %idx.1.ext = zext i8 %idx.1 to i16
343  %add.i32.idx.1 = getelementptr inbounds i32, ptr %A, i16 %idx.1.ext
344  %c.1 = icmp ult ptr %add.i32.idx.1, %upper
345  %add.i8.idx.1 = getelementptr inbounds i8, ptr %A, i16 %idx.1.ext
346  %t.1 = icmp ult ptr %add.i8.idx.1, %upper
347  %res.1 = xor i1 %c.1, %t.1
348  ret i1 %res.1
349}
350
351%struct.t = type { i8, i8 }
352
353define i1 @gep_add_nsw_positive_index_struct(ptr %A, ptr %upper, i8 %idx) {
354; CHECK-LABEL: @gep_add_nsw_positive_index_struct(
355; CHECK-NEXT:    [[IDX_POS:%.*]] = icmp sge i8 [[IDX:%.*]], 0
356; CHECK-NEXT:    call void @llvm.assume(i1 [[IDX_POS]])
357; CHECK-NEXT:    [[IDX_3:%.*]] = add nsw i8 [[IDX]], 2
358; CHECK-NEXT:    [[ADD_I8_IDX_3:%.*]] = getelementptr inbounds [[STRUCT_T:%.*]], ptr [[A:%.*]], i8 [[IDX_3]]
359; CHECK-NEXT:    [[C_0:%.*]] = icmp ult ptr [[ADD_I8_IDX_3]], [[UPPER:%.*]]
360; CHECK-NEXT:    call void @llvm.assume(i1 [[C_0]])
361; CHECK-NEXT:    [[IDX_1:%.*]] = add nsw i8 [[IDX]], 1
362; CHECK-NEXT:    [[ADD_I32_IDX_1:%.*]] = getelementptr inbounds i32, ptr [[A]], i8 [[IDX_1]]
363; CHECK-NEXT:    [[T_1:%.*]] = icmp ult ptr [[ADD_I32_IDX_1]], [[UPPER]]
364; CHECK-NEXT:    [[ADD_I8_IDX_1:%.*]] = getelementptr inbounds i8, ptr [[A]], i8 [[IDX_1]]
365; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 [[T_1]], true
366; CHECK-NEXT:    [[ADD_I16_IDX_1:%.*]] = getelementptr inbounds i16, ptr [[A]], i8 [[IDX_1]]
367; CHECK-NEXT:    [[RES_2:%.*]] = xor i1 [[RES_1]], true
368; CHECK-NEXT:    [[ADD_I64_IDX_1:%.*]] = getelementptr inbounds i64, ptr [[A]], i8 [[IDX_1]]
369; CHECK-NEXT:    [[C_1:%.*]] = icmp ult ptr [[ADD_I64_IDX_1]], [[UPPER]]
370; CHECK-NEXT:    [[RES_3:%.*]] = xor i1 [[RES_2]], [[C_1]]
371; CHECK-NEXT:    ret i1 [[RES_3]]
372;
373  %idx.pos = icmp sge i8 %idx, 0
374  call void @llvm.assume(i1 %idx.pos)
375  %idx.3 = add nsw i8 %idx, 2
376  %add.i8.idx.3 = getelementptr inbounds %struct.t, ptr %A, i8 %idx.3
377  %c.0 = icmp ult ptr %add.i8.idx.3, %upper
378  call void @llvm.assume(i1 %c.0)
379
380  %idx.1 = add nsw i8 %idx, 1
381  %add.i32.idx.1 = getelementptr inbounds i32, ptr %A, i8 %idx.1
382  %t.1 = icmp ult ptr %add.i32.idx.1, %upper
383  %add.i8.idx.1 = getelementptr inbounds i8, ptr %A, i8 %idx.1
384  %t.2 = icmp ult ptr %add.i8.idx.1, %upper
385  %res.1 = xor i1 %t.1, %t.2
386
387  %add.i16.idx.1 = getelementptr inbounds i16, ptr %A, i8 %idx.1
388  %t.3 = icmp ult ptr %add.i16.idx.1, %upper
389  %res.2 = xor i1 %res.1, %t.3
390
391  %add.i64.idx.1 = getelementptr inbounds i64, ptr %A, i8 %idx.1
392  %c.1 = icmp ult ptr %add.i64.idx.1, %upper
393  %res.3 = xor i1 %res.2, %c.1
394
395  ret i1 %res.3
396}
397
398define i1 @gep_constant_positive_index_fixed_vector_ty(ptr %A, ptr %upper) {
399; CHECK-LABEL: @gep_constant_positive_index_fixed_vector_ty(
400; CHECK-NEXT:    [[ADD_I8_4:%.*]] = getelementptr inbounds <4 x i8>, ptr [[A:%.*]], i64 4
401; CHECK-NEXT:    [[C_0:%.*]] = icmp ult ptr [[ADD_I8_4]], [[UPPER:%.*]]
402; CHECK-NEXT:    call void @llvm.assume(i1 [[C_0]])
403; CHECK-NEXT:    [[ADD_I16_4:%.*]] = getelementptr inbounds <4 x i16>, ptr [[A]], i64 4
404; CHECK-NEXT:    [[C_1:%.*]] = icmp ult ptr [[ADD_I16_4]], [[UPPER]]
405; CHECK-NEXT:    [[ADD_I16_2:%.*]] = getelementptr inbounds <4 x i16>, ptr [[A]], i64 2
406; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 [[C_1]], true
407; CHECK-NEXT:    ret i1 [[RES_1]]
408;
409  %add.i8.4 = getelementptr inbounds <4 x i8>, ptr %A, i64 4
410  %c.0 = icmp ult ptr %add.i8.4, %upper
411  call void @llvm.assume(i1 %c.0)
412
413  %add.i16.4 = getelementptr inbounds <4 x i16>, ptr %A, i64 4
414  %c.1 = icmp ult ptr %add.i16.4, %upper
415
416  %add.i16.2 = getelementptr inbounds <4 x i16>, ptr %A, i64 2
417  %t.1 = icmp ult ptr %add.i16.2, %upper
418  %res.1 = xor i1 %c.1, %t.1
419  ret i1 %res.1
420}
421
422define i1 @gep_constant_positive_index_scalable_vector_ty(ptr %A, ptr %upper) {
423; CHECK-LABEL: @gep_constant_positive_index_scalable_vector_ty(
424; CHECK-NEXT:    [[ADD_I8_4:%.*]] = getelementptr inbounds <vscale x 4 x i8>, ptr [[A:%.*]], i64 4
425; CHECK-NEXT:    [[C_0:%.*]] = icmp ult ptr [[ADD_I8_4]], [[UPPER:%.*]]
426; CHECK-NEXT:    call void @llvm.assume(i1 [[C_0]])
427; CHECK-NEXT:    [[ADD_I16_4:%.*]] = getelementptr inbounds <vscale x 4 x i16>, ptr [[A]], i64 4
428; CHECK-NEXT:    [[C_1:%.*]] = icmp ult ptr [[ADD_I16_4]], [[UPPER]]
429; CHECK-NEXT:    [[ADD_I16_2:%.*]] = getelementptr inbounds <vscale x 4 x i16>, ptr [[A]], i64 2
430; CHECK-NEXT:    [[T_1:%.*]] = icmp ult ptr [[ADD_I16_2]], [[UPPER]]
431; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 [[C_1]], [[T_1]]
432; CHECK-NEXT:    ret i1 [[RES_1]]
433;
434  %add.i8.4 = getelementptr inbounds <vscale x 4 x i8>, ptr %A, i64 4
435  %c.0 = icmp ult ptr %add.i8.4, %upper
436  call void @llvm.assume(i1 %c.0)
437
438  %add.i16.4 = getelementptr inbounds <vscale x 4 x i16>, ptr %A, i64 4
439  %c.1 = icmp ult ptr %add.i16.4, %upper
440
441  %add.i16.2 = getelementptr inbounds <vscale x 4 x i16>, ptr %A, i64 2
442  %t.1 = icmp ult ptr %add.i16.2, %upper
443  %res.1 = xor i1 %c.1, %t.1
444  ret i1 %res.1
445}
446