[AArch64][NFC] NFC for const vector as Instruction operand (#116790)
[llvm-project.git] / llvm / test / Transforms / InstCombine / icmp-gep.ll
blob776716fe9087333a97d25d502a9260ea05736ce4
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -passes=instcombine -S  < %s | FileCheck %s
4 target datalayout = "e-p:64:64:64-p1:16:16:16-p2:32:32:32-p3:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
6 declare ptr @getptr()
7 declare void @use(ptr)
8 declare void @use.i1(i1)
10 define i1 @eq_base(ptr %x, i64 %y) {
11 ; CHECK-LABEL: @eq_base(
12 ; CHECK-NEXT:    [[R:%.*]] = icmp eq i64 [[Y:%.*]], 0
13 ; CHECK-NEXT:    ret i1 [[R]]
15   %g = getelementptr i8, ptr %x, i64 %y
16   %r = icmp eq ptr %g, %x
17   ret i1 %r
20 define i1 @ne_base_commute(i64 %y) {
21 ; CHECK-LABEL: @ne_base_commute(
22 ; CHECK-NEXT:    [[X:%.*]] = call ptr @getptr()
23 ; CHECK-NEXT:    [[R:%.*]] = icmp ne i64 [[Y:%.*]], 0
24 ; CHECK-NEXT:    ret i1 [[R]]
26   %x = call ptr @getptr() ; thwart complexity-based canonicalization
27   %g = getelementptr i8, ptr %x, i64 %y
28   %r = icmp ne ptr %x, %g
29   ret i1 %r
32 define i1 @ne_base_inbounds(ptr %x, i64 %y) {
33 ; CHECK-LABEL: @ne_base_inbounds(
34 ; CHECK-NEXT:    [[R:%.*]] = icmp ne i64 [[Y:%.*]], 0
35 ; CHECK-NEXT:    ret i1 [[R]]
37   %g = getelementptr inbounds i8, ptr %x, i64 %y
38   %r = icmp ne ptr %g, %x
39   ret i1 %r
42 define i1 @eq_base_inbounds_commute(i64 %y) {
43 ; CHECK-LABEL: @eq_base_inbounds_commute(
44 ; CHECK-NEXT:    [[X:%.*]] = call ptr @getptr()
45 ; CHECK-NEXT:    [[R:%.*]] = icmp eq i64 [[Y:%.*]], 0
46 ; CHECK-NEXT:    ret i1 [[R]]
48   %x = call ptr @getptr() ; thwart complexity-based canonicalization
49   %g = getelementptr inbounds i8, ptr %x, i64 %y
50   %r = icmp eq ptr %x, %g
51   ret i1 %r
54 define i1 @slt_base(ptr %x, i64 %y) {
55 ; CHECK-LABEL: @slt_base(
56 ; CHECK-NEXT:    [[G:%.*]] = getelementptr i8, ptr [[X:%.*]], i64 [[Y:%.*]]
57 ; CHECK-NEXT:    [[R:%.*]] = icmp slt ptr [[G]], [[X]]
58 ; CHECK-NEXT:    ret i1 [[R]]
60   %g = getelementptr i8, ptr %x, i64 %y
61   %r = icmp slt ptr %g, %x
62   ret i1 %r
65 define i1 @sgt_base_commute(i64 %y) {
66 ; CHECK-LABEL: @sgt_base_commute(
67 ; CHECK-NEXT:    [[X:%.*]] = call ptr @getptr()
68 ; CHECK-NEXT:    [[G:%.*]] = getelementptr i8, ptr [[X]], i64 [[Y:%.*]]
69 ; CHECK-NEXT:    [[R:%.*]] = icmp sgt ptr [[X]], [[G]]
70 ; CHECK-NEXT:    ret i1 [[R]]
72   %x = call ptr @getptr() ; thwart complexity-based canonicalization
73   %g = getelementptr i8, ptr %x, i64 %y
74   %r = icmp sgt ptr %x, %g
75   ret i1 %r
78 define i1 @slt_base_inbounds(ptr %x, i64 %y) {
79 ; CHECK-LABEL: @slt_base_inbounds(
80 ; CHECK-NEXT:    [[G:%.*]] = getelementptr inbounds i8, ptr [[X:%.*]], i64 [[Y:%.*]]
81 ; CHECK-NEXT:    [[R:%.*]] = icmp slt ptr [[G]], [[X]]
82 ; CHECK-NEXT:    ret i1 [[R]]
84   %g = getelementptr inbounds i8, ptr %x, i64 %y
85   %r = icmp slt ptr %g, %x
86   ret i1 %r
89 define i1 @sgt_base_inbounds_commute(i64 %y) {
90 ; CHECK-LABEL: @sgt_base_inbounds_commute(
91 ; CHECK-NEXT:    [[X:%.*]] = call ptr @getptr()
92 ; CHECK-NEXT:    [[G:%.*]] = getelementptr inbounds i8, ptr [[X]], i64 [[Y:%.*]]
93 ; CHECK-NEXT:    [[R:%.*]] = icmp sgt ptr [[X]], [[G]]
94 ; CHECK-NEXT:    ret i1 [[R]]
96   %x = call ptr @getptr() ; thwart complexity-based canonicalization
97   %g = getelementptr inbounds i8, ptr %x, i64 %y
98   %r = icmp sgt ptr %x, %g
99   ret i1 %r
102 define i1 @ult_base(ptr %x, i64 %y) {
103 ; CHECK-LABEL: @ult_base(
104 ; CHECK-NEXT:    [[G:%.*]] = getelementptr i8, ptr [[X:%.*]], i64 [[Y:%.*]]
105 ; CHECK-NEXT:    [[R:%.*]] = icmp ult ptr [[G]], [[X]]
106 ; CHECK-NEXT:    ret i1 [[R]]
108   %g = getelementptr i8, ptr %x, i64 %y
109   %r = icmp ult ptr %g, %x
110   ret i1 %r
113 define i1 @ugt_base_commute(i64 %y) {
114 ; CHECK-LABEL: @ugt_base_commute(
115 ; CHECK-NEXT:    [[X:%.*]] = call ptr @getptr()
116 ; CHECK-NEXT:    [[G:%.*]] = getelementptr i8, ptr [[X]], i64 [[Y:%.*]]
117 ; CHECK-NEXT:    [[R:%.*]] = icmp ugt ptr [[X]], [[G]]
118 ; CHECK-NEXT:    ret i1 [[R]]
120   %x = call ptr @getptr() ; thwart complexity-based canonicalization
121   %g = getelementptr i8, ptr %x, i64 %y
122   %r = icmp ugt ptr %x, %g
123   ret i1 %r
126 define i1 @ult_base_inbounds(ptr %x, i64 %y) {
127 ; CHECK-LABEL: @ult_base_inbounds(
128 ; CHECK-NEXT:    [[R:%.*]] = icmp slt i64 [[Y:%.*]], 0
129 ; CHECK-NEXT:    ret i1 [[R]]
131   %g = getelementptr inbounds i8, ptr %x, i64 %y
132   %r = icmp ult ptr %g, %x
133   ret i1 %r
136 define i1 @ugt_base_inbounds_commute(i64 %y) {
137 ; CHECK-LABEL: @ugt_base_inbounds_commute(
138 ; CHECK-NEXT:    [[X:%.*]] = call ptr @getptr()
139 ; CHECK-NEXT:    [[R:%.*]] = icmp slt i64 [[Y:%.*]], 0
140 ; CHECK-NEXT:    ret i1 [[R]]
142   %x = call ptr @getptr() ; thwart complexity-based canonicalization
143   %g = getelementptr inbounds i8, ptr %x, i64 %y
144   %r = icmp ugt ptr %x, %g
145   ret i1 %r
148 define i1 @ne_base_inbounds_use(ptr %x, i64 %y) {
149 ; CHECK-LABEL: @ne_base_inbounds_use(
150 ; CHECK-NEXT:    [[G:%.*]] = getelementptr inbounds i8, ptr [[X:%.*]], i64 [[Y:%.*]]
151 ; CHECK-NEXT:    call void @use(ptr [[G]])
152 ; CHECK-NEXT:    [[R:%.*]] = icmp ne i64 [[Y]], 0
153 ; CHECK-NEXT:    ret i1 [[R]]
155   %g = getelementptr inbounds i8, ptr %x, i64 %y
156   call void @use(ptr %g)
157   %r = icmp ne ptr %g, %x
158   ret i1 %r
161 define i1 @eq_base_inbounds_commute_use(i64 %y) {
162 ; CHECK-LABEL: @eq_base_inbounds_commute_use(
163 ; CHECK-NEXT:    [[X:%.*]] = call ptr @getptr()
164 ; CHECK-NEXT:    [[G:%.*]] = getelementptr inbounds i8, ptr [[X]], i64 [[Y:%.*]]
165 ; CHECK-NEXT:    call void @use(ptr [[G]])
166 ; CHECK-NEXT:    [[R:%.*]] = icmp eq i64 [[Y]], 0
167 ; CHECK-NEXT:    ret i1 [[R]]
169   %x = call ptr @getptr() ; thwart complexity-based canonicalization
170   %g = getelementptr inbounds i8, ptr %x, i64 %y
171   call void @use(ptr %g)
172   %r = icmp eq ptr %x, %g
173   ret i1 %r
176 define i1 @eq_bitcast_base(ptr %p, i64 %x) {
177 ; CHECK-LABEL: @eq_bitcast_base(
178 ; CHECK-NEXT:    [[GEP_IDX_MASK:%.*]] = and i64 [[X:%.*]], 9223372036854775807
179 ; CHECK-NEXT:    [[R:%.*]] = icmp eq i64 [[GEP_IDX_MASK]], 0
180 ; CHECK-NEXT:    ret i1 [[R]]
182   %gep = getelementptr [2 x i8], ptr %p, i64 %x, i64 0
183   %r = icmp eq ptr %gep, %p
184   ret i1 %r
187 define i1 @eq_bitcast_base_inbounds(ptr %p, i64 %x) {
188 ; CHECK-LABEL: @eq_bitcast_base_inbounds(
189 ; CHECK-NEXT:    [[R:%.*]] = icmp eq i64 [[X:%.*]], 0
190 ; CHECK-NEXT:    ret i1 [[R]]
192   %gep = getelementptr inbounds [2 x i8], ptr %p, i64 %x, i64 0
193   %r = icmp eq ptr %gep, %p
194   ret i1 %r
197 @X = global [1000 x i32] zeroinitializer
199 define i1 @PR8882(i64 %i) {
200 ; CHECK-LABEL: @PR8882(
201 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[I:%.*]], 1000
202 ; CHECK-NEXT:    ret i1 [[CMP]]
204   %p1 = getelementptr inbounds i32, ptr @X, i64 %i
205   %cmp = icmp eq ptr %p1, getelementptr inbounds ([1000 x i32], ptr @X, i64 1, i64 0)
206   ret i1 %cmp
209 @X_as1 = addrspace(1) global [1000 x i32] zeroinitializer
211 define i1 @test24_as1(i64 %i) {
212 ; CHECK-LABEL: @test24_as1(
213 ; CHECK-NEXT:    [[TMP1:%.*]] = and i64 [[I:%.*]], 65535
214 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[TMP1]], 1000
215 ; CHECK-NEXT:    ret i1 [[CMP]]
217   %p1 = getelementptr inbounds i32, ptr addrspace(1) @X_as1, i64 %i
218   %cmp = icmp eq ptr addrspace(1) %p1, getelementptr inbounds ([1000 x i32], ptr addrspace(1) @X_as1, i64 1, i64 0)
219   ret i1 %cmp
222 ; PR16244
223 define i1 @test71(ptr %x) {
224 ; CHECK-LABEL: @test71(
225 ; CHECK-NEXT:    ret i1 false
227   %a = getelementptr i8, ptr %x, i64 8
228   %b = getelementptr inbounds i8, ptr %x, i64 8
229   %c = icmp ugt ptr %a, %b
230   ret i1 %c
233 define i1 @test71_as1(ptr addrspace(1) %x) {
234 ; CHECK-LABEL: @test71_as1(
235 ; CHECK-NEXT:    ret i1 false
237   %a = getelementptr i8, ptr addrspace(1) %x, i64 8
238   %b = getelementptr inbounds i8, ptr addrspace(1) %x, i64 8
239   %c = icmp ugt ptr addrspace(1) %a, %b
240   ret i1 %c
243 declare i32 @test58_d(i64)
245 define i1 @test59(ptr %foo) {
246 ; CHECK-LABEL: @test59(
247 ; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr inbounds i8, ptr [[FOO:%.*]], i64 8
248 ; CHECK-NEXT:    [[USE:%.*]] = ptrtoint ptr [[GEP1]] to i64
249 ; CHECK-NEXT:    [[CALL:%.*]] = call i32 @test58_d(i64 [[USE]])
250 ; CHECK-NEXT:    ret i1 true
252   %gep1 = getelementptr inbounds i32, ptr %foo, i64 2
253   %gep2 = getelementptr inbounds i8, ptr %foo, i64 10
254   %cmp = icmp ult ptr %gep1, %gep2
255   %use = ptrtoint ptr %gep1 to i64
256   %call = call i32 @test58_d(i64 %use)
257   ret i1 %cmp
260 define i1 @test59_as1(ptr addrspace(1) %foo) {
261 ; CHECK-LABEL: @test59_as1(
262 ; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr inbounds i8, ptr addrspace(1) [[FOO:%.*]], i16 8
263 ; CHECK-NEXT:    [[TMP1:%.*]] = ptrtoint ptr addrspace(1) [[GEP1]] to i16
264 ; CHECK-NEXT:    [[USE:%.*]] = zext i16 [[TMP1]] to i64
265 ; CHECK-NEXT:    [[CALL:%.*]] = call i32 @test58_d(i64 [[USE]])
266 ; CHECK-NEXT:    ret i1 true
268   %gep1 = getelementptr inbounds i32, ptr addrspace(1) %foo, i64 2
269   %gep2 = getelementptr inbounds i8, ptr addrspace(1) %foo, i64 10
270   %cmp = icmp ult ptr addrspace(1) %gep1, %gep2
271   %use = ptrtoint ptr addrspace(1) %gep1 to i64
272   %call = call i32 @test58_d(i64 %use)
273   ret i1 %cmp
276 define i1 @test60(ptr %foo, i64 %i, i64 %j) {
277 ; CHECK-LABEL: @test60(
278 ; CHECK-NEXT:    [[GEP1_IDX:%.*]] = shl nsw i64 [[I:%.*]], 2
279 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i64 [[GEP1_IDX]], [[J:%.*]]
280 ; CHECK-NEXT:    ret i1 [[CMP]]
282   %gep1 = getelementptr inbounds i32, ptr %foo, i64 %i
283   %gep2 = getelementptr inbounds i8, ptr %foo, i64 %j
284   %cmp = icmp ult ptr %gep1, %gep2
285   ret i1 %cmp
288 define i1 @test_gep_ult_no_inbounds(ptr %foo, i64 %i, i64 %j) {
289 ; CHECK-LABEL: @test_gep_ult_no_inbounds(
290 ; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr i32, ptr [[FOO:%.*]], i64 [[I:%.*]]
291 ; CHECK-NEXT:    [[GEP2:%.*]] = getelementptr i8, ptr [[FOO]], i64 [[J:%.*]]
292 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult ptr [[GEP1]], [[GEP2]]
293 ; CHECK-NEXT:    ret i1 [[CMP]]
295   %gep1 = getelementptr i32, ptr %foo, i64 %i
296   %gep2 = getelementptr i8, ptr %foo, i64 %j
297   %cmp = icmp ult ptr %gep1, %gep2
298   ret i1 %cmp
301 define i1 @test_gep_eq_no_inbounds(ptr %foo, i64 %i, i64 %j) {
302 ; CHECK-LABEL: @test_gep_eq_no_inbounds(
303 ; CHECK-NEXT:    [[GEP1_IDX:%.*]] = shl i64 [[I:%.*]], 2
304 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[GEP1_IDX]], [[J:%.*]]
305 ; CHECK-NEXT:    ret i1 [[CMP]]
307   %gep1 = getelementptr i32, ptr %foo, i64 %i
308   %gep2 = getelementptr i8, ptr %foo, i64 %j
309   %cmp = icmp eq ptr %gep1, %gep2
310   ret i1 %cmp
313 define i1 @test60_as1(ptr addrspace(1) %foo, i64 %i, i64 %j) {
314 ; CHECK-LABEL: @test60_as1(
315 ; CHECK-NEXT:    [[TMP1:%.*]] = trunc i64 [[I:%.*]] to i16
316 ; CHECK-NEXT:    [[GEP1_IDX:%.*]] = shl nsw i16 [[TMP1]], 2
317 ; CHECK-NEXT:    [[TMP2:%.*]] = trunc i64 [[J:%.*]] to i16
318 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i16 [[GEP1_IDX]], [[TMP2]]
319 ; CHECK-NEXT:    ret i1 [[CMP]]
321   %gep1 = getelementptr inbounds i32, ptr addrspace(1) %foo, i64 %i
322   %gep2 = getelementptr inbounds i8, ptr addrspace(1) %foo, i64 %j
323   %cmp = icmp ult ptr addrspace(1) %gep1, %gep2
324   ret i1 %cmp
327 ; Same as test60, but look through an addrspacecast instead of a
328 ; bitcast. This uses the same sized addrspace.
329 define i1 @test60_addrspacecast(ptr %foo, i64 %i, i64 %j) {
330 ; CHECK-LABEL: @test60_addrspacecast(
331 ; CHECK-NEXT:    [[GEP1_IDX:%.*]] = shl nsw i64 [[I:%.*]], 2
332 ; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i64 [[J:%.*]], [[GEP1_IDX]]
333 ; CHECK-NEXT:    ret i1 [[CMP]]
335   %bit = addrspacecast ptr %foo to ptr addrspace(3)
336   %gep1 = getelementptr inbounds i32, ptr addrspace(3) %bit, i64 %i
337   %gep2 = getelementptr inbounds i8, ptr %foo, i64 %j
338   %cast1 = addrspacecast ptr addrspace(3) %gep1 to ptr
339   %cmp = icmp ult ptr %cast1, %gep2
340   ret i1 %cmp
343 define i1 @test60_addrspacecast_smaller(ptr %foo, i16 %i, i64 %j) {
344 ; CHECK-LABEL: @test60_addrspacecast_smaller(
345 ; CHECK-NEXT:    [[GEP1_IDX:%.*]] = shl nsw i16 [[I:%.*]], 2
346 ; CHECK-NEXT:    [[TMP1:%.*]] = trunc i64 [[J:%.*]] to i16
347 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i16 [[GEP1_IDX]], [[TMP1]]
348 ; CHECK-NEXT:    ret i1 [[CMP]]
350   %bit = addrspacecast ptr %foo to ptr addrspace(1)
351   %gep1 = getelementptr inbounds i32, ptr addrspace(1) %bit, i16 %i
352   %gep2 = getelementptr inbounds i8, ptr %foo, i64 %j
353   %cast1 = addrspacecast ptr addrspace(1) %gep1 to ptr
354   %cmp = icmp ult ptr %cast1, %gep2
355   ret i1 %cmp
358 define i1 @test60_addrspacecast_larger(ptr addrspace(1) %foo, i32 %i, i16 %j) {
359 ; CHECK-LABEL: @test60_addrspacecast_larger(
360 ; CHECK-NEXT:    [[I_TR:%.*]] = trunc i32 [[I:%.*]] to i16
361 ; CHECK-NEXT:    [[TMP1:%.*]] = shl i16 [[I_TR]], 2
362 ; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i16 [[J:%.*]], [[TMP1]]
363 ; CHECK-NEXT:    ret i1 [[CMP]]
365   %bit = addrspacecast ptr addrspace(1) %foo to ptr addrspace(2)
366   %gep1 = getelementptr inbounds i32, ptr addrspace(2) %bit, i32 %i
367   %gep2 = getelementptr inbounds i8, ptr addrspace(1) %foo, i16 %j
368   %cast1 = addrspacecast ptr addrspace(2) %gep1 to ptr addrspace(1)
369   %cmp = icmp ult ptr addrspace(1) %cast1, %gep2
370   ret i1 %cmp
373 define i1 @test61(ptr %foo, i64 %i, i64 %j) {
374 ; CHECK-LABEL: @test61(
375 ; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr i32, ptr [[FOO:%.*]], i64 [[I:%.*]]
376 ; CHECK-NEXT:    [[GEP2:%.*]] = getelementptr i8, ptr [[FOO]], i64 [[J:%.*]]
377 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult ptr [[GEP1]], [[GEP2]]
378 ; CHECK-NEXT:    ret i1 [[CMP]]
380   %gep1 = getelementptr i32, ptr %foo, i64 %i
381   %gep2 = getelementptr  i8,  ptr %foo, i64 %j
382   %cmp = icmp ult ptr %gep1, %gep2
383   ret i1 %cmp
384 ; Don't transform non-inbounds GEPs.
387 define i1 @test61_as1(ptr addrspace(1) %foo, i16 %i, i16 %j) {
388 ; CHECK-LABEL: @test61_as1(
389 ; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr i32, ptr addrspace(1) [[FOO:%.*]], i16 [[I:%.*]]
390 ; CHECK-NEXT:    [[GEP2:%.*]] = getelementptr i8, ptr addrspace(1) [[FOO]], i16 [[J:%.*]]
391 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult ptr addrspace(1) [[GEP1]], [[GEP2]]
392 ; CHECK-NEXT:    ret i1 [[CMP]]
394   %gep1 = getelementptr i32, ptr addrspace(1) %foo, i16 %i
395   %gep2 = getelementptr i8, ptr addrspace(1) %foo, i16 %j
396   %cmp = icmp ult ptr addrspace(1) %gep1, %gep2
397   ret i1 %cmp
398 ; Don't transform non-inbounds GEPs.
401 define i1 @test60_extra_use(ptr %foo, i64 %i, i64 %j) {
402 ; CHECK-LABEL: @test60_extra_use(
403 ; CHECK-NEXT:    [[GEP1_IDX:%.*]] = shl nsw i64 [[I:%.*]], 2
404 ; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr inbounds i8, ptr [[FOO:%.*]], i64 [[GEP1_IDX]]
405 ; CHECK-NEXT:    [[GEP2_IDX:%.*]] = shl nsw i64 [[J:%.*]], 1
406 ; CHECK-NEXT:    [[GEP2:%.*]] = getelementptr inbounds i8, ptr [[FOO]], i64 [[GEP2_IDX]]
407 ; CHECK-NEXT:    call void @use(ptr [[GEP1]])
408 ; CHECK-NEXT:    call void @use(ptr [[GEP2]])
409 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i64 [[GEP1_IDX]], [[GEP2_IDX]]
410 ; CHECK-NEXT:    ret i1 [[CMP]]
412   %gep1 = getelementptr inbounds i32, ptr %foo, i64 %i
413   %gep2 = getelementptr inbounds i16, ptr %foo, i64 %j
414   call void @use(ptr %gep1)
415   call void @use(ptr %gep2)
416   %cmp = icmp ult ptr %gep1, %gep2
417   ret i1 %cmp
420 define i1 @test60_extra_use_const_operands_inbounds(ptr %foo, i64 %i, i64 %j) {
421 ; CHECK-LABEL: @test60_extra_use_const_operands_inbounds(
422 ; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr inbounds i8, ptr [[FOO:%.*]], i64 4
423 ; CHECK-NEXT:    call void @use(ptr nonnull [[GEP1]])
424 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[J:%.*]], 2
425 ; CHECK-NEXT:    ret i1 [[CMP]]
427   %gep1 = getelementptr inbounds i32, ptr %foo, i64 1
428   %gep2 = getelementptr inbounds i16, ptr %foo, i64 %j
429   call void @use(ptr %gep1)
430   %cmp = icmp eq ptr %gep1, %gep2
431   ret i1 %cmp
434 define i1 @test60_extra_use_const_operands_no_inbounds(ptr %foo, i64 %i, i64 %j) {
435 ; CHECK-LABEL: @test60_extra_use_const_operands_no_inbounds(
436 ; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr i8, ptr [[FOO:%.*]], i64 4
437 ; CHECK-NEXT:    call void @use(ptr [[GEP1]])
438 ; CHECK-NEXT:    [[GEP2_IDX_MASK:%.*]] = and i64 [[J:%.*]], 9223372036854775807
439 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[GEP2_IDX_MASK]], 2
440 ; CHECK-NEXT:    ret i1 [[CMP]]
442   %gep1 = getelementptr i32, ptr %foo, i64 1
443   %gep2 = getelementptr i16, ptr %foo, i64 %j
444   call void @use(ptr %gep1)
445   %cmp = icmp eq ptr %gep1, %gep2
446   ret i1 %cmp
449 define void @test60_extra_use_fold(ptr %foo, i64 %start.idx, i64 %end.offset) {
450 ; CHECK-LABEL: @test60_extra_use_fold(
451 ; CHECK-NEXT:    [[GEP1_IDX:%.*]] = shl nsw i64 [[START_IDX:%.*]], 2
452 ; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr inbounds i8, ptr [[FOO:%.*]], i64 [[GEP1_IDX]]
453 ; CHECK-NEXT:    [[GEP2:%.*]] = getelementptr inbounds i8, ptr [[FOO]], i64 [[END_OFFSET:%.*]]
454 ; CHECK-NEXT:    call void @use(ptr [[GEP1]])
455 ; CHECK-NEXT:    call void @use(ptr [[GEP2]])
456 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i64 [[GEP1_IDX]], [[END_OFFSET]]
457 ; CHECK-NEXT:    call void @use.i1(i1 [[CMP1]])
458 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i64 [[GEP1_IDX]], [[END_OFFSET]]
459 ; CHECK-NEXT:    call void @use.i1(i1 [[CMP2]])
460 ; CHECK-NEXT:    ret void
462   %gep1 = getelementptr inbounds i32, ptr %foo, i64 %start.idx
463   %gep2 = getelementptr inbounds i8, ptr %foo, i64 %end.offset
464   call void @use(ptr %gep1)
465   call void @use(ptr %gep2)
466   %cmp1 = icmp eq ptr %gep1, %gep2
467   call void @use.i1(i1 %cmp1)
468   %cmp2 = icmp ult ptr %gep1, %gep2
469   call void @use.i1(i1 %cmp2)
470   ret void
473 define i1 @test_scalable_same(ptr %x) {
474 ; CHECK-LABEL: @test_scalable_same(
475 ; CHECK-NEXT:    [[TMP1:%.*]] = call i64 @llvm.vscale.i64()
476 ; CHECK-NEXT:    [[A_IDX:%.*]] = shl i64 [[TMP1]], 5
477 ; CHECK-NEXT:    [[A:%.*]] = getelementptr i8, ptr [[X:%.*]], i64 [[A_IDX]]
478 ; CHECK-NEXT:    [[TMP2:%.*]] = call i64 @llvm.vscale.i64()
479 ; CHECK-NEXT:    [[B_IDX:%.*]] = shl i64 [[TMP2]], 5
480 ; CHECK-NEXT:    [[B:%.*]] = getelementptr inbounds i8, ptr [[X]], i64 [[B_IDX]]
481 ; CHECK-NEXT:    [[C:%.*]] = icmp ugt ptr [[A]], [[B]]
482 ; CHECK-NEXT:    ret i1 [[C]]
484   %a = getelementptr <vscale x 4 x i8>, ptr %x, i64 8
485   %b = getelementptr inbounds <vscale x 4 x i8>, ptr %x, i64 8
486   %c = icmp ugt ptr %a, %b
487   ret i1 %c
490 define i1 @test_scalable_x(ptr %x) {
491 ; CHECK-LABEL: @test_scalable_x(
492 ; CHECK-NEXT:    [[TMP1:%.*]] = call i64 @llvm.vscale.i64()
493 ; CHECK-NEXT:    [[A_IDX_MASK:%.*]] = and i64 [[TMP1]], 576460752303423487
494 ; CHECK-NEXT:    [[C:%.*]] = icmp eq i64 [[A_IDX_MASK]], 0
495 ; CHECK-NEXT:    ret i1 [[C]]
497   %a = getelementptr <vscale x 4 x i8>, ptr %x, i64 8
498   %c = icmp eq ptr %a, %x
499   ret i1 %c
502 define i1 @test_scalable_xc(ptr %x) {
503 ; CHECK-LABEL: @test_scalable_xc(
504 ; CHECK-NEXT:    [[TMP1:%.*]] = call i64 @llvm.vscale.i64()
505 ; CHECK-NEXT:    [[A_IDX_MASK:%.*]] = and i64 [[TMP1]], 576460752303423487
506 ; CHECK-NEXT:    [[C:%.*]] = icmp eq i64 [[A_IDX_MASK]], 0
507 ; CHECK-NEXT:    ret i1 [[C]]
509   %a = getelementptr <vscale x 4 x i8>, ptr %x, i64 8
510   %c = icmp eq ptr %x, %a
511   ret i1 %c
514 define i1 @test_scalable_xy(ptr %foo, i64 %i, i64 %j) {
515 ; CHECK-LABEL: @test_scalable_xy(
516 ; CHECK-NEXT:    [[TMP1:%.*]] = call i64 @llvm.vscale.i64()
517 ; CHECK-NEXT:    [[TMP2:%.*]] = shl i64 [[TMP1]], 4
518 ; CHECK-NEXT:    [[GEP1_IDX:%.*]] = mul nsw i64 [[I:%.*]], [[TMP2]]
519 ; CHECK-NEXT:    [[TMP3:%.*]] = call i64 @llvm.vscale.i64()
520 ; CHECK-NEXT:    [[TMP4:%.*]] = shl i64 [[TMP3]], 2
521 ; CHECK-NEXT:    [[GEP2_IDX:%.*]] = mul nsw i64 [[J:%.*]], [[TMP4]]
522 ; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i64 [[GEP2_IDX]], [[GEP1_IDX]]
523 ; CHECK-NEXT:    ret i1 [[CMP]]
525   %bit = addrspacecast ptr %foo to ptr addrspace(3)
526   %gep1 = getelementptr inbounds <vscale x 4 x i32>, ptr addrspace(3) %bit, i64 %i
527   %gep2 = getelementptr inbounds <vscale x 4 x i8>, ptr %foo, i64 %j
528   %cast1 = addrspacecast ptr addrspace(3) %gep1 to ptr
529   %cmp = icmp ult ptr %cast1, %gep2
530   ret i1 %cmp
533 define i1 @test_scalable_ij(ptr %foo, i64 %i, i64 %j) {
534 ; CHECK-LABEL: @test_scalable_ij(
535 ; CHECK-NEXT:    [[TMP1:%.*]] = call i64 @llvm.vscale.i64()
536 ; CHECK-NEXT:    [[TMP2:%.*]] = shl i64 [[TMP1]], 4
537 ; CHECK-NEXT:    [[GEP1_IDX:%.*]] = mul nsw i64 [[I:%.*]], [[TMP2]]
538 ; CHECK-NEXT:    [[TMP3:%.*]] = call i64 @llvm.vscale.i64()
539 ; CHECK-NEXT:    [[TMP4:%.*]] = shl i64 [[TMP3]], 2
540 ; CHECK-NEXT:    [[GEP2_IDX:%.*]] = mul nsw i64 [[J:%.*]], [[TMP4]]
541 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i64 [[GEP1_IDX]], [[GEP2_IDX]]
542 ; CHECK-NEXT:    ret i1 [[CMP]]
544   %gep1 = getelementptr inbounds <vscale x 4 x i32>, ptr %foo, i64 %i
545   %gep2 = getelementptr inbounds <vscale x 4 x i8>, ptr %foo, i64 %j
546   %cmp = icmp ult ptr %gep1, %gep2
547   ret i1 %cmp
550 define i1 @gep_nuw(ptr %p, i64 %a, i64 %b, i64 %c, i64 %d) {
551 ; CHECK-LABEL: @gep_nuw(
552 ; CHECK-NEXT:    [[GEP1_IDX:%.*]] = shl nuw i64 [[A:%.*]], 2
553 ; CHECK-NEXT:    [[GEP1_IDX1:%.*]] = shl nuw i64 [[B:%.*]], 1
554 ; CHECK-NEXT:    [[GEP1_OFFS:%.*]] = add nuw i64 [[GEP1_IDX]], [[GEP1_IDX1]]
555 ; CHECK-NEXT:    [[GEP2_IDX:%.*]] = shl nuw i64 [[C:%.*]], 3
556 ; CHECK-NEXT:    [[GEP2_IDX2:%.*]] = shl nuw i64 [[D:%.*]], 2
557 ; CHECK-NEXT:    [[GEP2_OFFS:%.*]] = add nuw i64 [[GEP2_IDX]], [[GEP2_IDX2]]
558 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[GEP1_OFFS]], [[GEP2_OFFS]]
559 ; CHECK-NEXT:    ret i1 [[CMP]]
561   %gep1 = getelementptr nuw [2 x i16], ptr %p, i64 %a, i64 %b
562   %gep2 = getelementptr nuw [2 x i32], ptr %p, i64 %c, i64 %d
563   %cmp = icmp eq ptr %gep1, %gep2
564   ret i1 %cmp
567 define i1 @gep_nusw(ptr %p, i64 %a, i64 %b, i64 %c, i64 %d) {
568 ; CHECK-LABEL: @gep_nusw(
569 ; CHECK-NEXT:    [[GEP1_IDX:%.*]] = shl nsw i64 [[A:%.*]], 2
570 ; CHECK-NEXT:    [[GEP1_IDX1:%.*]] = shl nsw i64 [[B:%.*]], 1
571 ; CHECK-NEXT:    [[GEP1_OFFS:%.*]] = add nsw i64 [[GEP1_IDX]], [[GEP1_IDX1]]
572 ; CHECK-NEXT:    [[GEP2_IDX:%.*]] = shl nsw i64 [[C:%.*]], 3
573 ; CHECK-NEXT:    [[GEP2_IDX2:%.*]] = shl nsw i64 [[D:%.*]], 2
574 ; CHECK-NEXT:    [[GEP2_OFFS:%.*]] = add nsw i64 [[GEP2_IDX]], [[GEP2_IDX2]]
575 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[GEP1_OFFS]], [[GEP2_OFFS]]
576 ; CHECK-NEXT:    ret i1 [[CMP]]
578   %gep1 = getelementptr nusw [2 x i16], ptr %p, i64 %a, i64 %b
579   %gep2 = getelementptr nusw [2 x i32], ptr %p, i64 %c, i64 %d
580   %cmp = icmp eq ptr %gep1, %gep2
581   ret i1 %cmp
584 define i1 @pointer_icmp_aligned_with_offset(ptr align 8 %a, ptr align 8 %a2) {
585 ; CHECK-LABEL: @pointer_icmp_aligned_with_offset(
586 ; CHECK-NEXT:    ret i1 false
588   %gep = getelementptr i8, ptr %a, i64 4
589   %cmp = icmp eq ptr %gep, %a2
590   ret i1 %cmp
593 define i1 @pointer_icmp_aligned_with_offset_negative(ptr align 8 %a, ptr align 8 %a2) {
594 ; CHECK-LABEL: @pointer_icmp_aligned_with_offset_negative(
595 ; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 8
596 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[GEP]], [[A2:%.*]]
597 ; CHECK-NEXT:    ret i1 [[CMP]]
599   %gep = getelementptr i8, ptr %a, i64 8
600   %cmp = icmp eq ptr %gep, %a2
601   ret i1 %cmp