xref: /llvm-project/llvm/test/Transforms/InstCombine/icmp-gep.ll (revision fac46469977da9c4e9c6eeaac21103c971190577)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -passes=instcombine -S  < %s | FileCheck %s
3
4target 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"
5
6declare ptr @getptr()
7declare void @use(ptr)
8declare void @use.i1(i1)
9
10define 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]]
14;
15  %g = getelementptr i8, ptr %x, i64 %y
16  %r = icmp eq ptr %g, %x
17  ret i1 %r
18}
19
20define 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]]
25;
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
30}
31
32define 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]]
36;
37  %g = getelementptr inbounds i8, ptr %x, i64 %y
38  %r = icmp ne ptr %g, %x
39  ret i1 %r
40}
41
42define 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]]
47;
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
52}
53
54define 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]]
59;
60  %g = getelementptr i8, ptr %x, i64 %y
61  %r = icmp slt ptr %g, %x
62  ret i1 %r
63}
64
65define 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]]
71;
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
76}
77
78define 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]]
83;
84  %g = getelementptr inbounds i8, ptr %x, i64 %y
85  %r = icmp slt ptr %g, %x
86  ret i1 %r
87}
88
89define 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]]
95;
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
100}
101
102define 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]]
107;
108  %g = getelementptr i8, ptr %x, i64 %y
109  %r = icmp ult ptr %g, %x
110  ret i1 %r
111}
112
113define 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]]
119;
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
124}
125
126define 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]]
130;
131  %g = getelementptr inbounds i8, ptr %x, i64 %y
132  %r = icmp ult ptr %g, %x
133  ret i1 %r
134}
135
136define i1 @ult_base_nusw(ptr %x, i64 %y) {
137; CHECK-LABEL: @ult_base_nusw(
138; CHECK-NEXT:    [[R:%.*]] = icmp slt i64 [[Y:%.*]], 0
139; CHECK-NEXT:    ret i1 [[R]]
140;
141  %g = getelementptr nusw i8, ptr %x, i64 %y
142  %r = icmp ult ptr %g, %x
143  ret i1 %r
144}
145
146define i1 @ugt_base_nuw(ptr %x, i64 %y) {
147; CHECK-LABEL: @ugt_base_nuw(
148; CHECK-NEXT:    [[R:%.*]] = icmp ne i64 [[Y:%.*]], 0
149; CHECK-NEXT:    ret i1 [[R]]
150;
151  %g = getelementptr nuw i8, ptr %x, i64 %y
152  %r = icmp ugt ptr %g, %x
153  ret i1 %r
154}
155
156define i1 @ugt_base_nusw_nuw(ptr %x, i64 %y) {
157; CHECK-LABEL: @ugt_base_nusw_nuw(
158; CHECK-NEXT:    [[R:%.*]] = icmp ne i64 [[Y:%.*]], 0
159; CHECK-NEXT:    ret i1 [[R]]
160;
161  %g = getelementptr nusw nuw i8, ptr %x, i64 %y
162  %r = icmp ugt ptr %g, %x
163  ret i1 %r
164}
165
166define i1 @uge_base_nuw(ptr %x, i64 %y) {
167; CHECK-LABEL: @uge_base_nuw(
168; CHECK-NEXT:    ret i1 true
169;
170  %g = getelementptr nuw i8, ptr %x, i64 %y
171  %r = icmp uge ptr %g, %x
172  ret i1 %r
173}
174
175define i1 @uge_base_nusw_nuw(ptr %x, i64 %y) {
176; CHECK-LABEL: @uge_base_nusw_nuw(
177; CHECK-NEXT:    ret i1 true
178;
179  %g = getelementptr nusw nuw i8, ptr %x, i64 %y
180  %r = icmp uge ptr %g, %x
181  ret i1 %r
182}
183
184define i1 @ugt_base_inbounds_commute(i64 %y) {
185; CHECK-LABEL: @ugt_base_inbounds_commute(
186; CHECK-NEXT:    [[X:%.*]] = call ptr @getptr()
187; CHECK-NEXT:    [[R:%.*]] = icmp slt i64 [[Y:%.*]], 0
188; CHECK-NEXT:    ret i1 [[R]]
189;
190  %x = call ptr @getptr() ; thwart complexity-based canonicalization
191  %g = getelementptr inbounds i8, ptr %x, i64 %y
192  %r = icmp ugt ptr %x, %g
193  ret i1 %r
194}
195
196define i1 @ne_base_inbounds_use(ptr %x, i64 %y) {
197; CHECK-LABEL: @ne_base_inbounds_use(
198; CHECK-NEXT:    [[G:%.*]] = getelementptr inbounds i8, ptr [[X:%.*]], i64 [[Y:%.*]]
199; CHECK-NEXT:    call void @use(ptr [[G]])
200; CHECK-NEXT:    [[R:%.*]] = icmp ne i64 [[Y]], 0
201; CHECK-NEXT:    ret i1 [[R]]
202;
203  %g = getelementptr inbounds i8, ptr %x, i64 %y
204  call void @use(ptr %g)
205  %r = icmp ne ptr %g, %x
206  ret i1 %r
207}
208
209define i1 @eq_base_inbounds_commute_use(i64 %y) {
210; CHECK-LABEL: @eq_base_inbounds_commute_use(
211; CHECK-NEXT:    [[X:%.*]] = call ptr @getptr()
212; CHECK-NEXT:    [[G:%.*]] = getelementptr inbounds i8, ptr [[X]], i64 [[Y:%.*]]
213; CHECK-NEXT:    call void @use(ptr [[G]])
214; CHECK-NEXT:    [[R:%.*]] = icmp eq i64 [[Y]], 0
215; CHECK-NEXT:    ret i1 [[R]]
216;
217  %x = call ptr @getptr() ; thwart complexity-based canonicalization
218  %g = getelementptr inbounds i8, ptr %x, i64 %y
219  call void @use(ptr %g)
220  %r = icmp eq ptr %x, %g
221  ret i1 %r
222}
223
224define i1 @eq_bitcast_base(ptr %p, i64 %x) {
225; CHECK-LABEL: @eq_bitcast_base(
226; CHECK-NEXT:    [[GEP_IDX_MASK:%.*]] = and i64 [[X:%.*]], 9223372036854775807
227; CHECK-NEXT:    [[R:%.*]] = icmp eq i64 [[GEP_IDX_MASK]], 0
228; CHECK-NEXT:    ret i1 [[R]]
229;
230  %gep = getelementptr [2 x i8], ptr %p, i64 %x, i64 0
231  %r = icmp eq ptr %gep, %p
232  ret i1 %r
233}
234
235define i1 @eq_bitcast_base_inbounds(ptr %p, i64 %x) {
236; CHECK-LABEL: @eq_bitcast_base_inbounds(
237; CHECK-NEXT:    [[R:%.*]] = icmp eq i64 [[X:%.*]], 0
238; CHECK-NEXT:    ret i1 [[R]]
239;
240  %gep = getelementptr inbounds [2 x i8], ptr %p, i64 %x, i64 0
241  %r = icmp eq ptr %gep, %p
242  ret i1 %r
243}
244
245@X = global [1000 x i32] zeroinitializer
246
247define i1 @PR8882(i64 %i) {
248; CHECK-LABEL: @PR8882(
249; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[I:%.*]], 1000
250; CHECK-NEXT:    ret i1 [[CMP]]
251;
252  %p1 = getelementptr inbounds i32, ptr @X, i64 %i
253  %cmp = icmp eq ptr %p1, getelementptr inbounds ([1000 x i32], ptr @X, i64 1, i64 0)
254  ret i1 %cmp
255}
256
257@X_as1 = addrspace(1) global [1000 x i32] zeroinitializer
258
259define i1 @test24_as1(i64 %i) {
260; CHECK-LABEL: @test24_as1(
261; CHECK-NEXT:    [[TMP1:%.*]] = and i64 [[I:%.*]], 65535
262; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[TMP1]], 1000
263; CHECK-NEXT:    ret i1 [[CMP]]
264;
265  %p1 = getelementptr inbounds i32, ptr addrspace(1) @X_as1, i64 %i
266  %cmp = icmp eq ptr addrspace(1) %p1, getelementptr inbounds ([1000 x i32], ptr addrspace(1) @X_as1, i64 1, i64 0)
267  ret i1 %cmp
268}
269
270; PR16244
271define i1 @test71(ptr %x) {
272; CHECK-LABEL: @test71(
273; CHECK-NEXT:    ret i1 false
274;
275  %a = getelementptr i8, ptr %x, i64 8
276  %b = getelementptr inbounds i8, ptr %x, i64 8
277  %c = icmp ugt ptr %a, %b
278  ret i1 %c
279}
280
281define i1 @test71_as1(ptr addrspace(1) %x) {
282; CHECK-LABEL: @test71_as1(
283; CHECK-NEXT:    ret i1 false
284;
285  %a = getelementptr i8, ptr addrspace(1) %x, i64 8
286  %b = getelementptr inbounds i8, ptr addrspace(1) %x, i64 8
287  %c = icmp ugt ptr addrspace(1) %a, %b
288  ret i1 %c
289}
290
291declare i32 @test58_d(i64)
292
293define i1 @test59(ptr %foo) {
294; CHECK-LABEL: @test59(
295; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr inbounds nuw i8, ptr [[FOO:%.*]], i64 8
296; CHECK-NEXT:    [[USE:%.*]] = ptrtoint ptr [[GEP1]] to i64
297; CHECK-NEXT:    [[CALL:%.*]] = call i32 @test58_d(i64 [[USE]])
298; CHECK-NEXT:    ret i1 true
299;
300  %gep1 = getelementptr inbounds i32, ptr %foo, i64 2
301  %gep2 = getelementptr inbounds i8, ptr %foo, i64 10
302  %cmp = icmp ult ptr %gep1, %gep2
303  %use = ptrtoint ptr %gep1 to i64
304  %call = call i32 @test58_d(i64 %use)
305  ret i1 %cmp
306}
307
308define i1 @test59_as1(ptr addrspace(1) %foo) {
309; CHECK-LABEL: @test59_as1(
310; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr inbounds nuw i8, ptr addrspace(1) [[FOO:%.*]], i16 8
311; CHECK-NEXT:    [[TMP1:%.*]] = ptrtoint ptr addrspace(1) [[GEP1]] to i16
312; CHECK-NEXT:    [[USE:%.*]] = zext i16 [[TMP1]] to i64
313; CHECK-NEXT:    [[CALL:%.*]] = call i32 @test58_d(i64 [[USE]])
314; CHECK-NEXT:    ret i1 true
315;
316  %gep1 = getelementptr inbounds i32, ptr addrspace(1) %foo, i64 2
317  %gep2 = getelementptr inbounds i8, ptr addrspace(1) %foo, i64 10
318  %cmp = icmp ult ptr addrspace(1) %gep1, %gep2
319  %use = ptrtoint ptr addrspace(1) %gep1 to i64
320  %call = call i32 @test58_d(i64 %use)
321  ret i1 %cmp
322}
323
324define i1 @test60(ptr %foo, i64 %i, i64 %j) {
325; CHECK-LABEL: @test60(
326; CHECK-NEXT:    [[GEP1_IDX:%.*]] = shl nsw i64 [[I:%.*]], 2
327; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i64 [[GEP1_IDX]], [[J:%.*]]
328; CHECK-NEXT:    ret i1 [[CMP]]
329;
330  %gep1 = getelementptr inbounds i32, ptr %foo, i64 %i
331  %gep2 = getelementptr inbounds i8, ptr %foo, i64 %j
332  %cmp = icmp ult ptr %gep1, %gep2
333  ret i1 %cmp
334}
335
336define i1 @test60_nusw(ptr %foo, i64 %i, i64 %j) {
337; CHECK-LABEL: @test60_nusw(
338; CHECK-NEXT:    [[GEP1_IDX:%.*]] = shl nsw i64 [[I:%.*]], 2
339; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i64 [[GEP1_IDX]], [[J:%.*]]
340; CHECK-NEXT:    ret i1 [[CMP]]
341;
342  %gep1 = getelementptr nusw i32, ptr %foo, i64 %i
343  %gep2 = getelementptr nusw i8, ptr %foo, i64 %j
344  %cmp = icmp ult ptr %gep1, %gep2
345  ret i1 %cmp
346}
347
348define i1 @test60_nusw_inbounds(ptr %foo, i64 %i, i64 %j) {
349; CHECK-LABEL: @test60_nusw_inbounds(
350; CHECK-NEXT:    [[GEP1_IDX:%.*]] = shl nsw i64 [[I:%.*]], 2
351; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i64 [[GEP1_IDX]], [[J:%.*]]
352; CHECK-NEXT:    ret i1 [[CMP]]
353;
354  %gep1 = getelementptr nusw i32, ptr %foo, i64 %i
355  %gep2 = getelementptr inbounds i8, ptr %foo, i64 %j
356  %cmp = icmp ult ptr %gep1, %gep2
357  ret i1 %cmp
358}
359
360define i1 @test60_nuw(ptr %foo, i64 %i, i64 %j) {
361; CHECK-LABEL: @test60_nuw(
362; CHECK-NEXT:    [[GEP1_IDX:%.*]] = shl nuw i64 [[I:%.*]], 2
363; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i64 [[GEP1_IDX]], [[J:%.*]]
364; CHECK-NEXT:    ret i1 [[CMP]]
365;
366  %gep1 = getelementptr nuw i32, ptr %foo, i64 %i
367  %gep2 = getelementptr nuw i8, ptr %foo, i64 %j
368  %cmp = icmp ult ptr %gep1, %gep2
369  ret i1 %cmp
370}
371
372define i1 @test60_nusw_nuw(ptr %foo, i64 %i, i64 %j) {
373; CHECK-LABEL: @test60_nusw_nuw(
374; CHECK-NEXT:    [[GEP1_IDX:%.*]] = shl nuw nsw i64 [[I:%.*]], 2
375; CHECK-NEXT:    [[CMP:%.*]] = icmp samesign ult i64 [[GEP1_IDX]], [[J:%.*]]
376; CHECK-NEXT:    ret i1 [[CMP]]
377;
378  %gep1 = getelementptr nusw nuw i32, ptr %foo, i64 %i
379  %gep2 = getelementptr nusw nuw i8, ptr %foo, i64 %j
380  %cmp = icmp ult ptr %gep1, %gep2
381  ret i1 %cmp
382}
383
384define i1 @test60_nusw_nuw_mix(ptr %foo, i64 %i, i64 %j) {
385; CHECK-LABEL: @test60_nusw_nuw_mix(
386; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr nuw i32, ptr [[FOO:%.*]], i64 [[I:%.*]]
387; CHECK-NEXT:    [[GEP2:%.*]] = getelementptr nusw i8, ptr [[FOO]], i64 [[J:%.*]]
388; CHECK-NEXT:    [[CMP:%.*]] = icmp ult ptr [[GEP1]], [[GEP2]]
389; CHECK-NEXT:    ret i1 [[CMP]]
390;
391  %gep1 = getelementptr nuw i32, ptr %foo, i64 %i
392  %gep2 = getelementptr nusw i8, ptr %foo, i64 %j
393  %cmp = icmp ult ptr %gep1, %gep2
394  ret i1 %cmp
395}
396
397define i1 @test_gep_ult_no_inbounds(ptr %foo, i64 %i, i64 %j) {
398; CHECK-LABEL: @test_gep_ult_no_inbounds(
399; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr i32, ptr [[FOO:%.*]], i64 [[I:%.*]]
400; CHECK-NEXT:    [[GEP2:%.*]] = getelementptr i8, ptr [[FOO]], i64 [[J:%.*]]
401; CHECK-NEXT:    [[CMP:%.*]] = icmp ult ptr [[GEP1]], [[GEP2]]
402; CHECK-NEXT:    ret i1 [[CMP]]
403;
404  %gep1 = getelementptr i32, ptr %foo, i64 %i
405  %gep2 = getelementptr i8, ptr %foo, i64 %j
406  %cmp = icmp ult ptr %gep1, %gep2
407  ret i1 %cmp
408}
409
410define i1 @test_gep_eq_no_inbounds(ptr %foo, i64 %i, i64 %j) {
411; CHECK-LABEL: @test_gep_eq_no_inbounds(
412; CHECK-NEXT:    [[GEP1_IDX:%.*]] = shl i64 [[I:%.*]], 2
413; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[GEP1_IDX]], [[J:%.*]]
414; CHECK-NEXT:    ret i1 [[CMP]]
415;
416  %gep1 = getelementptr i32, ptr %foo, i64 %i
417  %gep2 = getelementptr i8, ptr %foo, i64 %j
418  %cmp = icmp eq ptr %gep1, %gep2
419  ret i1 %cmp
420}
421
422define i1 @test60_as1(ptr addrspace(1) %foo, i64 %i, i64 %j) {
423; CHECK-LABEL: @test60_as1(
424; CHECK-NEXT:    [[TMP1:%.*]] = trunc i64 [[I:%.*]] to i16
425; CHECK-NEXT:    [[GEP1_IDX:%.*]] = shl nsw i16 [[TMP1]], 2
426; CHECK-NEXT:    [[TMP2:%.*]] = trunc i64 [[J:%.*]] to i16
427; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i16 [[GEP1_IDX]], [[TMP2]]
428; CHECK-NEXT:    ret i1 [[CMP]]
429;
430  %gep1 = getelementptr inbounds i32, ptr addrspace(1) %foo, i64 %i
431  %gep2 = getelementptr inbounds i8, ptr addrspace(1) %foo, i64 %j
432  %cmp = icmp ult ptr addrspace(1) %gep1, %gep2
433  ret i1 %cmp
434}
435
436; Same as test60, but look through an addrspacecast instead of a
437; bitcast. This uses the same sized addrspace.
438define i1 @test60_addrspacecast(ptr %foo, i64 %i, i64 %j) {
439; CHECK-LABEL: @test60_addrspacecast(
440; CHECK-NEXT:    [[GEP1_IDX:%.*]] = shl nsw i64 [[I:%.*]], 2
441; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i64 [[J:%.*]], [[GEP1_IDX]]
442; CHECK-NEXT:    ret i1 [[CMP]]
443;
444  %bit = addrspacecast ptr %foo to ptr addrspace(3)
445  %gep1 = getelementptr inbounds i32, ptr addrspace(3) %bit, i64 %i
446  %gep2 = getelementptr inbounds i8, ptr %foo, i64 %j
447  %cast1 = addrspacecast ptr addrspace(3) %gep1 to ptr
448  %cmp = icmp ult ptr %cast1, %gep2
449  ret i1 %cmp
450}
451
452define i1 @test60_addrspacecast_smaller(ptr %foo, i16 %i, i64 %j) {
453; CHECK-LABEL: @test60_addrspacecast_smaller(
454; CHECK-NEXT:    [[GEP1_IDX:%.*]] = shl nsw i16 [[I:%.*]], 2
455; CHECK-NEXT:    [[TMP1:%.*]] = trunc i64 [[J:%.*]] to i16
456; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i16 [[GEP1_IDX]], [[TMP1]]
457; CHECK-NEXT:    ret i1 [[CMP]]
458;
459  %bit = addrspacecast ptr %foo to ptr addrspace(1)
460  %gep1 = getelementptr inbounds i32, ptr addrspace(1) %bit, i16 %i
461  %gep2 = getelementptr inbounds i8, ptr %foo, i64 %j
462  %cast1 = addrspacecast ptr addrspace(1) %gep1 to ptr
463  %cmp = icmp ult ptr %cast1, %gep2
464  ret i1 %cmp
465}
466
467define i1 @test60_addrspacecast_larger(ptr addrspace(1) %foo, i32 %i, i16 %j) {
468; CHECK-LABEL: @test60_addrspacecast_larger(
469; CHECK-NEXT:    [[I_TR:%.*]] = trunc i32 [[I:%.*]] to i16
470; CHECK-NEXT:    [[TMP1:%.*]] = shl i16 [[I_TR]], 2
471; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i16 [[J:%.*]], [[TMP1]]
472; CHECK-NEXT:    ret i1 [[CMP]]
473;
474  %bit = addrspacecast ptr addrspace(1) %foo to ptr addrspace(2)
475  %gep1 = getelementptr inbounds i32, ptr addrspace(2) %bit, i32 %i
476  %gep2 = getelementptr inbounds i8, ptr addrspace(1) %foo, i16 %j
477  %cast1 = addrspacecast ptr addrspace(2) %gep1 to ptr addrspace(1)
478  %cmp = icmp ult ptr addrspace(1) %cast1, %gep2
479  ret i1 %cmp
480}
481
482define i1 @test61(ptr %foo, i64 %i, i64 %j) {
483; CHECK-LABEL: @test61(
484; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr i32, ptr [[FOO:%.*]], i64 [[I:%.*]]
485; CHECK-NEXT:    [[GEP2:%.*]] = getelementptr i8, ptr [[FOO]], i64 [[J:%.*]]
486; CHECK-NEXT:    [[CMP:%.*]] = icmp ult ptr [[GEP1]], [[GEP2]]
487; CHECK-NEXT:    ret i1 [[CMP]]
488;
489  %gep1 = getelementptr i32, ptr %foo, i64 %i
490  %gep2 = getelementptr  i8,  ptr %foo, i64 %j
491  %cmp = icmp ult ptr %gep1, %gep2
492  ret i1 %cmp
493; Don't transform non-inbounds GEPs.
494}
495
496define i1 @test61_as1(ptr addrspace(1) %foo, i16 %i, i16 %j) {
497; CHECK-LABEL: @test61_as1(
498; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr i32, ptr addrspace(1) [[FOO:%.*]], i16 [[I:%.*]]
499; CHECK-NEXT:    [[GEP2:%.*]] = getelementptr i8, ptr addrspace(1) [[FOO]], i16 [[J:%.*]]
500; CHECK-NEXT:    [[CMP:%.*]] = icmp ult ptr addrspace(1) [[GEP1]], [[GEP2]]
501; CHECK-NEXT:    ret i1 [[CMP]]
502;
503  %gep1 = getelementptr i32, ptr addrspace(1) %foo, i16 %i
504  %gep2 = getelementptr i8, ptr addrspace(1) %foo, i16 %j
505  %cmp = icmp ult ptr addrspace(1) %gep1, %gep2
506  ret i1 %cmp
507; Don't transform non-inbounds GEPs.
508}
509
510define i1 @test60_extra_use(ptr %foo, i64 %i, i64 %j) {
511; CHECK-LABEL: @test60_extra_use(
512; CHECK-NEXT:    [[GEP1_IDX:%.*]] = shl nsw i64 [[I:%.*]], 2
513; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr inbounds i8, ptr [[FOO:%.*]], i64 [[GEP1_IDX]]
514; CHECK-NEXT:    [[GEP2_IDX:%.*]] = shl nsw i64 [[J:%.*]], 1
515; CHECK-NEXT:    [[GEP2:%.*]] = getelementptr inbounds i8, ptr [[FOO]], i64 [[GEP2_IDX]]
516; CHECK-NEXT:    call void @use(ptr [[GEP1]])
517; CHECK-NEXT:    call void @use(ptr [[GEP2]])
518; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i64 [[GEP1_IDX]], [[GEP2_IDX]]
519; CHECK-NEXT:    ret i1 [[CMP]]
520;
521  %gep1 = getelementptr inbounds i32, ptr %foo, i64 %i
522  %gep2 = getelementptr inbounds i16, ptr %foo, i64 %j
523  call void @use(ptr %gep1)
524  call void @use(ptr %gep2)
525  %cmp = icmp ult ptr %gep1, %gep2
526  ret i1 %cmp
527}
528
529define i1 @test60_extra_use_const_operands_inbounds(ptr %foo, i64 %i, i64 %j) {
530; CHECK-LABEL: @test60_extra_use_const_operands_inbounds(
531; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr inbounds nuw i8, ptr [[FOO:%.*]], i64 4
532; CHECK-NEXT:    call void @use(ptr nonnull [[GEP1]])
533; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[J:%.*]], 2
534; CHECK-NEXT:    ret i1 [[CMP]]
535;
536  %gep1 = getelementptr inbounds i32, ptr %foo, i64 1
537  %gep2 = getelementptr inbounds i16, ptr %foo, i64 %j
538  call void @use(ptr %gep1)
539  %cmp = icmp eq ptr %gep1, %gep2
540  ret i1 %cmp
541}
542
543define i1 @test60_extra_use_const_operands_no_inbounds(ptr %foo, i64 %i, i64 %j) {
544; CHECK-LABEL: @test60_extra_use_const_operands_no_inbounds(
545; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr i8, ptr [[FOO:%.*]], i64 4
546; CHECK-NEXT:    call void @use(ptr [[GEP1]])
547; CHECK-NEXT:    [[GEP2_IDX_MASK:%.*]] = and i64 [[J:%.*]], 9223372036854775807
548; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[GEP2_IDX_MASK]], 2
549; CHECK-NEXT:    ret i1 [[CMP]]
550;
551  %gep1 = getelementptr i32, ptr %foo, i64 1
552  %gep2 = getelementptr i16, ptr %foo, i64 %j
553  call void @use(ptr %gep1)
554  %cmp = icmp eq ptr %gep1, %gep2
555  ret i1 %cmp
556}
557
558define void @test60_extra_use_fold(ptr %foo, i64 %start.idx, i64 %end.offset) {
559; CHECK-LABEL: @test60_extra_use_fold(
560; CHECK-NEXT:    [[GEP1_IDX:%.*]] = shl nsw i64 [[START_IDX:%.*]], 2
561; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr inbounds i8, ptr [[FOO:%.*]], i64 [[GEP1_IDX]]
562; CHECK-NEXT:    [[GEP2:%.*]] = getelementptr inbounds i8, ptr [[FOO]], i64 [[END_OFFSET:%.*]]
563; CHECK-NEXT:    call void @use(ptr [[GEP1]])
564; CHECK-NEXT:    call void @use(ptr [[GEP2]])
565; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i64 [[GEP1_IDX]], [[END_OFFSET]]
566; CHECK-NEXT:    call void @use.i1(i1 [[CMP1]])
567; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i64 [[GEP1_IDX]], [[END_OFFSET]]
568; CHECK-NEXT:    call void @use.i1(i1 [[CMP2]])
569; CHECK-NEXT:    ret void
570;
571  %gep1 = getelementptr inbounds i32, ptr %foo, i64 %start.idx
572  %gep2 = getelementptr inbounds i8, ptr %foo, i64 %end.offset
573  call void @use(ptr %gep1)
574  call void @use(ptr %gep2)
575  %cmp1 = icmp eq ptr %gep1, %gep2
576  call void @use.i1(i1 %cmp1)
577  %cmp2 = icmp ult ptr %gep1, %gep2
578  call void @use.i1(i1 %cmp2)
579  ret void
580}
581
582define i1 @test_scalable_same(ptr %x) {
583; CHECK-LABEL: @test_scalable_same(
584; CHECK-NEXT:    [[TMP1:%.*]] = call i64 @llvm.vscale.i64()
585; CHECK-NEXT:    [[A_IDX:%.*]] = shl i64 [[TMP1]], 5
586; CHECK-NEXT:    [[A:%.*]] = getelementptr i8, ptr [[X:%.*]], i64 [[A_IDX]]
587; CHECK-NEXT:    [[TMP2:%.*]] = call i64 @llvm.vscale.i64()
588; CHECK-NEXT:    [[B_IDX:%.*]] = shl i64 [[TMP2]], 5
589; CHECK-NEXT:    [[B:%.*]] = getelementptr inbounds i8, ptr [[X]], i64 [[B_IDX]]
590; CHECK-NEXT:    [[C:%.*]] = icmp ugt ptr [[A]], [[B]]
591; CHECK-NEXT:    ret i1 [[C]]
592;
593  %a = getelementptr <vscale x 4 x i8>, ptr %x, i64 8
594  %b = getelementptr inbounds <vscale x 4 x i8>, ptr %x, i64 8
595  %c = icmp ugt ptr %a, %b
596  ret i1 %c
597}
598
599define i1 @test_scalable_x(ptr %x) {
600; CHECK-LABEL: @test_scalable_x(
601; CHECK-NEXT:    [[TMP1:%.*]] = call i64 @llvm.vscale.i64()
602; CHECK-NEXT:    [[A_IDX_MASK:%.*]] = and i64 [[TMP1]], 576460752303423487
603; CHECK-NEXT:    [[C:%.*]] = icmp eq i64 [[A_IDX_MASK]], 0
604; CHECK-NEXT:    ret i1 [[C]]
605;
606  %a = getelementptr <vscale x 4 x i8>, ptr %x, i64 8
607  %c = icmp eq ptr %a, %x
608  ret i1 %c
609}
610
611define i1 @test_scalable_xc(ptr %x) {
612; CHECK-LABEL: @test_scalable_xc(
613; CHECK-NEXT:    [[TMP1:%.*]] = call i64 @llvm.vscale.i64()
614; CHECK-NEXT:    [[A_IDX_MASK:%.*]] = and i64 [[TMP1]], 576460752303423487
615; CHECK-NEXT:    [[C:%.*]] = icmp eq i64 [[A_IDX_MASK]], 0
616; CHECK-NEXT:    ret i1 [[C]]
617;
618  %a = getelementptr <vscale x 4 x i8>, ptr %x, i64 8
619  %c = icmp eq ptr %x, %a
620  ret i1 %c
621}
622
623define i1 @test_scalable_xy(ptr %foo, i64 %i, i64 %j) {
624; CHECK-LABEL: @test_scalable_xy(
625; CHECK-NEXT:    [[TMP1:%.*]] = call i64 @llvm.vscale.i64()
626; CHECK-NEXT:    [[TMP2:%.*]] = shl i64 [[TMP1]], 4
627; CHECK-NEXT:    [[GEP1_IDX:%.*]] = mul nsw i64 [[I:%.*]], [[TMP2]]
628; CHECK-NEXT:    [[TMP3:%.*]] = call i64 @llvm.vscale.i64()
629; CHECK-NEXT:    [[TMP4:%.*]] = shl i64 [[TMP3]], 2
630; CHECK-NEXT:    [[GEP2_IDX:%.*]] = mul nsw i64 [[J:%.*]], [[TMP4]]
631; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i64 [[GEP2_IDX]], [[GEP1_IDX]]
632; CHECK-NEXT:    ret i1 [[CMP]]
633;
634  %bit = addrspacecast ptr %foo to ptr addrspace(3)
635  %gep1 = getelementptr inbounds <vscale x 4 x i32>, ptr addrspace(3) %bit, i64 %i
636  %gep2 = getelementptr inbounds <vscale x 4 x i8>, ptr %foo, i64 %j
637  %cast1 = addrspacecast ptr addrspace(3) %gep1 to ptr
638  %cmp = icmp ult ptr %cast1, %gep2
639  ret i1 %cmp
640}
641
642define i1 @test_scalable_ij(ptr %foo, i64 %i, i64 %j) {
643; CHECK-LABEL: @test_scalable_ij(
644; CHECK-NEXT:    [[TMP1:%.*]] = call i64 @llvm.vscale.i64()
645; CHECK-NEXT:    [[TMP2:%.*]] = shl i64 [[TMP1]], 4
646; CHECK-NEXT:    [[GEP1_IDX:%.*]] = mul nsw i64 [[I:%.*]], [[TMP2]]
647; CHECK-NEXT:    [[TMP3:%.*]] = call i64 @llvm.vscale.i64()
648; CHECK-NEXT:    [[TMP4:%.*]] = shl i64 [[TMP3]], 2
649; CHECK-NEXT:    [[GEP2_IDX:%.*]] = mul nsw i64 [[J:%.*]], [[TMP4]]
650; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i64 [[GEP1_IDX]], [[GEP2_IDX]]
651; CHECK-NEXT:    ret i1 [[CMP]]
652;
653  %gep1 = getelementptr inbounds <vscale x 4 x i32>, ptr %foo, i64 %i
654  %gep2 = getelementptr inbounds <vscale x 4 x i8>, ptr %foo, i64 %j
655  %cmp = icmp ult ptr %gep1, %gep2
656  ret i1 %cmp
657}
658
659define i1 @gep_nuw(ptr %p, i64 %a, i64 %b, i64 %c, i64 %d) {
660; CHECK-LABEL: @gep_nuw(
661; CHECK-NEXT:    [[GEP1_IDX:%.*]] = shl nuw i64 [[A:%.*]], 2
662; CHECK-NEXT:    [[GEP1_IDX1:%.*]] = shl nuw i64 [[B:%.*]], 1
663; CHECK-NEXT:    [[GEP1_OFFS:%.*]] = add nuw i64 [[GEP1_IDX]], [[GEP1_IDX1]]
664; CHECK-NEXT:    [[GEP2_IDX:%.*]] = shl nuw i64 [[C:%.*]], 3
665; CHECK-NEXT:    [[GEP2_IDX2:%.*]] = shl nuw i64 [[D:%.*]], 2
666; CHECK-NEXT:    [[GEP2_OFFS:%.*]] = add nuw i64 [[GEP2_IDX]], [[GEP2_IDX2]]
667; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[GEP1_OFFS]], [[GEP2_OFFS]]
668; CHECK-NEXT:    ret i1 [[CMP]]
669;
670  %gep1 = getelementptr nuw [2 x i16], ptr %p, i64 %a, i64 %b
671  %gep2 = getelementptr nuw [2 x i32], ptr %p, i64 %c, i64 %d
672  %cmp = icmp eq ptr %gep1, %gep2
673  ret i1 %cmp
674}
675
676define i1 @gep_nusw(ptr %p, i64 %a, i64 %b, i64 %c, i64 %d) {
677; CHECK-LABEL: @gep_nusw(
678; CHECK-NEXT:    [[GEP1_IDX:%.*]] = shl nsw i64 [[A:%.*]], 2
679; CHECK-NEXT:    [[GEP1_IDX1:%.*]] = shl nsw i64 [[B:%.*]], 1
680; CHECK-NEXT:    [[GEP1_OFFS:%.*]] = add nsw i64 [[GEP1_IDX]], [[GEP1_IDX1]]
681; CHECK-NEXT:    [[GEP2_IDX:%.*]] = shl nsw i64 [[C:%.*]], 3
682; CHECK-NEXT:    [[GEP2_IDX2:%.*]] = shl nsw i64 [[D:%.*]], 2
683; CHECK-NEXT:    [[GEP2_OFFS:%.*]] = add nsw i64 [[GEP2_IDX]], [[GEP2_IDX2]]
684; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[GEP1_OFFS]], [[GEP2_OFFS]]
685; CHECK-NEXT:    ret i1 [[CMP]]
686;
687  %gep1 = getelementptr nusw [2 x i16], ptr %p, i64 %a, i64 %b
688  %gep2 = getelementptr nusw [2 x i32], ptr %p, i64 %c, i64 %d
689  %cmp = icmp eq ptr %gep1, %gep2
690  ret i1 %cmp
691}
692
693define i1 @pointer_icmp_aligned_with_offset(ptr align 8 %a, ptr align 8 %a2) {
694; CHECK-LABEL: @pointer_icmp_aligned_with_offset(
695; CHECK-NEXT:    ret i1 false
696;
697  %gep = getelementptr i8, ptr %a, i64 4
698  %cmp = icmp eq ptr %gep, %a2
699  ret i1 %cmp
700}
701
702define i1 @pointer_icmp_aligned_with_offset_negative(ptr align 8 %a, ptr align 8 %a2) {
703; CHECK-LABEL: @pointer_icmp_aligned_with_offset_negative(
704; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 8
705; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[GEP]], [[A2:%.*]]
706; CHECK-NEXT:    ret i1 [[CMP]]
707;
708  %gep = getelementptr i8, ptr %a, i64 8
709  %cmp = icmp eq ptr %gep, %a2
710  ret i1 %cmp
711}
712
713define i1 @gep_diff_base_same_indices(ptr %x, ptr %y, i64 %z) {
714; CHECK-LABEL: @gep_diff_base_same_indices(
715; CHECK-NEXT:    [[X:%.*]] = getelementptr i8, ptr [[X1:%.*]], i64 [[Z:%.*]]
716; CHECK-NEXT:    [[Y:%.*]] = getelementptr i8, ptr [[Y1:%.*]], i64 [[Z]]
717; CHECK-NEXT:    [[CMP:%.*]] = icmp ult ptr [[X]], [[Y]]
718; CHECK-NEXT:    ret i1 [[CMP]]
719;
720  %gep1 = getelementptr i8, ptr %x, i64 %z
721  %gep2 = getelementptr i8, ptr %y, i64 %z
722  %cmp = icmp ult ptr %gep1, %gep2
723  ret i1 %cmp
724}
725
726define i1 @gep_diff_base_same_indices_nuw(ptr %x, ptr %y, i64 %z) {
727; CHECK-LABEL: @gep_diff_base_same_indices_nuw(
728; CHECK-NEXT:    [[CMP:%.*]] = icmp ult ptr [[X:%.*]], [[Y:%.*]]
729; CHECK-NEXT:    ret i1 [[CMP]]
730;
731  %gep1 = getelementptr nuw i8, ptr %x, i64 %z
732  %gep2 = getelementptr nuw i8, ptr %y, i64 %z
733  %cmp = icmp ult ptr %gep1, %gep2
734  ret i1 %cmp
735}
736
737define i1 @gep_diff_base_same_indices_nusw(ptr %x, ptr %y, i64 %z) {
738; CHECK-LABEL: @gep_diff_base_same_indices_nusw(
739; CHECK-NEXT:    [[CMP:%.*]] = icmp ult ptr [[X:%.*]], [[Y:%.*]]
740; CHECK-NEXT:    ret i1 [[CMP]]
741;
742  %gep1 = getelementptr nusw i8, ptr %x, i64 %z
743  %gep2 = getelementptr nusw i8, ptr %y, i64 %z
744  %cmp = icmp ult ptr %gep1, %gep2
745  ret i1 %cmp
746}
747
748define i1 @gep_diff_base_same_indices_nuw_nusw(ptr %x, ptr %y, i64 %z) {
749; CHECK-LABEL: @gep_diff_base_same_indices_nuw_nusw(
750; CHECK-NEXT:    [[X:%.*]] = getelementptr nuw i8, ptr [[X1:%.*]], i64 [[Z:%.*]]
751; CHECK-NEXT:    [[Y:%.*]] = getelementptr nusw i8, ptr [[Y1:%.*]], i64 [[Z]]
752; CHECK-NEXT:    [[CMP:%.*]] = icmp ult ptr [[X]], [[Y]]
753; CHECK-NEXT:    ret i1 [[CMP]]
754;
755  %gep1 = getelementptr nuw i8, ptr %x, i64 %z
756  %gep2 = getelementptr nusw i8, ptr %y, i64 %z
757  %cmp = icmp ult ptr %gep1, %gep2
758  ret i1 %cmp
759}
760