xref: /llvm-project/llvm/test/Transforms/InstCombine/getelementptr.ll (revision da5f45f5937d3cde4ff76aeeb208e72ee504baaf)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3
4target datalayout = "e-p:64:64-p1:16:16-p2:32:32:32-p3:64:64:64-f16:32"
5
6%intstruct = type { i32 }
7%pair = type { i32, i32 }
8%struct.B = type { double }
9%struct.A = type { %struct.B, i32, i32 }
10%struct.C = type { [7 x i8] }
11
12
13@Global = external global [10 x i8]
14@Global_as1 = external addrspace(1) global [10 x i8]
15
16declare void @use(ptr)
17
18; Test noop elimination
19define ptr @test1(ptr %I) {
20; CHECK-LABEL: @test1(
21; CHECK-NEXT:    ret ptr [[I:%.*]]
22;
23  ret ptr %I
24}
25
26define ptr addrspace(1) @test1_as1(ptr addrspace(1) %I) {
27; CHECK-LABEL: @test1_as1(
28; CHECK-NEXT:    ret ptr addrspace(1) [[I:%.*]]
29;
30  ret ptr addrspace(1) %I
31}
32
33; Test noop elimination
34define ptr @test2(ptr %I) {
35; CHECK-LABEL: @test2(
36; CHECK-NEXT:    ret ptr [[I:%.*]]
37;
38  %A = getelementptr i32, ptr %I
39  ret ptr %A
40}
41
42; Test that two array indexing geps fold
43define ptr @test3(ptr %I) {
44; CHECK-LABEL: @test3(
45; CHECK-NEXT:    [[B:%.*]] = getelementptr i8, ptr [[I:%.*]], i64 84
46; CHECK-NEXT:    ret ptr [[B]]
47;
48  %A = getelementptr i32, ptr %I, i64 17
49  %B = getelementptr i32, ptr %A, i64 4
50  ret ptr %B
51}
52
53; Test that two getelementptr insts fold
54define ptr @test4(ptr %I) {
55; CHECK-LABEL: @test4(
56; CHECK-NEXT:    [[A:%.*]] = getelementptr i8, ptr [[I:%.*]], i64 4
57; CHECK-NEXT:    ret ptr [[A]]
58;
59  %A = getelementptr { i32 }, ptr %I, i64 1
60  ret ptr %A
61}
62
63define void @test5(i8 %B) {
64        ; This should be turned into a constexpr instead of being an instruction
65; CHECK-LABEL: @test5(
66; CHECK-NEXT:    store i8 [[B:%.*]], ptr getelementptr inbounds (i8, ptr @Global, i64 4), align 1
67; CHECK-NEXT:    ret void
68;
69  %A = getelementptr [10 x i8], ptr @Global, i64 0, i64 4
70  store i8 %B, ptr %A
71  ret void
72}
73
74define void @test5_as1(i8 %B) {
75        ; This should be turned into a constexpr instead of being an instruction
76; CHECK-LABEL: @test5_as1(
77; CHECK-NEXT:    store i8 [[B:%.*]], ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) @Global_as1, i16 4), align 1
78; CHECK-NEXT:    ret void
79;
80  %A = getelementptr [10 x i8], ptr addrspace(1) @Global_as1, i16 0, i16 4
81  store i8 %B, ptr addrspace(1) %A
82  ret void
83}
84
85%as1_ptr_struct = type { ptr addrspace(1) }
86%as2_ptr_struct = type { ptr addrspace(2) }
87
88@global_as2 = addrspace(2) global i32 zeroinitializer
89@global_as1_as2_ptr = addrspace(1) global %as2_ptr_struct { ptr addrspace(2) @global_as2 }
90
91; This should be turned into a constexpr instead of being an instruction
92define void @test_evaluate_gep_nested_as_ptrs(ptr addrspace(2) %B) {
93; CHECK-LABEL: @test_evaluate_gep_nested_as_ptrs(
94; CHECK-NEXT:    store ptr addrspace(2) [[B:%.*]], ptr addrspace(1) @global_as1_as2_ptr, align 4
95; CHECK-NEXT:    ret void
96;
97  store ptr addrspace(2) %B, ptr addrspace(1) @global_as1_as2_ptr
98  ret void
99}
100
101@arst = addrspace(1) global [4 x ptr addrspace(2)] zeroinitializer
102
103define void @test_evaluate_gep_as_ptrs_array(ptr addrspace(2) %B) {
104; CHECK-LABEL: @test_evaluate_gep_as_ptrs_array(
105; CHECK-NEXT:    store ptr addrspace(2) [[B:%.*]], ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) @arst, i16 8), align 4
106; CHECK-NEXT:    ret void
107;
108
109  %A = getelementptr [4 x ptr addrspace(2)], ptr addrspace(1) @arst, i16 0, i16 2
110  store ptr addrspace(2) %B, ptr addrspace(1) %A
111  ret void
112}
113
114; This should be turned into a constexpr instead of being an instruction
115define void @test_overaligned_vec(i8 %B) {
116; CHECK-LABEL: @test_overaligned_vec(
117; CHECK-NEXT:    store i8 [[B:%.*]], ptr getelementptr inbounds (i8, ptr @Global, i64 2), align 1
118; CHECK-NEXT:    ret void
119;
120  %A = getelementptr <2 x half>, ptr @Global, i64 0, i64 1
121  store i8 %B, ptr %A
122  ret void
123}
124
125define ptr @test7(ptr %I, i64 %C, i64 %D) {
126; CHECK-LABEL: @test7(
127; CHECK-NEXT:    [[A:%.*]] = getelementptr i32, ptr [[I:%.*]], i64 [[C:%.*]]
128; CHECK-NEXT:    [[B:%.*]] = getelementptr i32, ptr [[A]], i64 [[D:%.*]]
129; CHECK-NEXT:    ret ptr [[B]]
130;
131  %A = getelementptr i32, ptr %I, i64 %C
132  %B = getelementptr i32, ptr %A, i64 %D
133  ret ptr %B
134}
135
136define ptr @test8(ptr %X) {
137        ;; Fold into the cast.
138; CHECK-LABEL: @test8(
139; CHECK-NEXT:    ret ptr [[X:%.*]]
140;
141  ret ptr %X
142}
143
144define i32 @test9() {
145; CHECK-LABEL: @test9(
146; CHECK-NEXT:    ret i32 8
147;
148  %A = getelementptr { i32, double }, ptr null, i32 0, i32 1
149  %B = ptrtoint ptr %A to i32
150  ret i32 %B
151}
152
153define i1 @test10(ptr %x, ptr %y) {
154; CHECK-LABEL: @test10(
155; CHECK-NEXT:    [[T4:%.*]] = icmp eq ptr [[X:%.*]], [[Y:%.*]]
156; CHECK-NEXT:    ret i1 [[T4]]
157;
158  %t1 = getelementptr { i32, i32 }, ptr %x, i32 0, i32 1
159  %t3 = getelementptr { i32, i32 }, ptr %y, i32 0, i32 1
160  %t4 = icmp eq ptr %t1, %t3
161  ret i1 %t4
162}
163
164define i1 @test10_addrspacecast(ptr %x, ptr addrspace(3) %y) {
165; CHECK-LABEL: @test10_addrspacecast(
166; CHECK-NEXT:    [[T1:%.*]] = getelementptr i8, ptr [[X:%.*]], i64 4
167; CHECK-NEXT:    [[T3:%.*]] = getelementptr i8, ptr addrspace(3) [[Y:%.*]], i64 4
168; CHECK-NEXT:    [[T3_C:%.*]] = addrspacecast ptr addrspace(3) [[T3]] to ptr
169; CHECK-NEXT:    [[T4:%.*]] = icmp eq ptr [[T1]], [[T3_C]]
170; CHECK-NEXT:    ret i1 [[T4]]
171;
172  %t1 = getelementptr { i32, i32 }, ptr %x, i32 0, i32 1
173  %t3 = getelementptr { i32, i32 }, ptr addrspace(3) %y, i32 0, i32 1
174  %t3.c = addrspacecast ptr addrspace(3) %t3 to ptr
175  %t4 = icmp eq ptr %t1, %t3.c
176  ret i1 %t4
177}
178
179define i1 @test11(ptr %X) {
180; CHECK-LABEL: @test11(
181; CHECK-NEXT:    [[Q:%.*]] = icmp eq ptr [[X:%.*]], null
182; CHECK-NEXT:    ret i1 [[Q]]
183;
184  %P = getelementptr { i32, i32 }, ptr %X, i32 0, i32 0
185  %Q = icmp eq ptr %P, null
186  ret i1 %Q
187}
188
189
190; PR4748
191define i32 @test12(ptr %a) {
192; CHECK-LABEL: @test12(
193; CHECK-NEXT:  entry:
194; CHECK-NEXT:    [[G3:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 8
195; CHECK-NEXT:    store i32 10, ptr [[G3]], align 4
196; CHECK-NEXT:    ret i32 10
197;
198entry:
199  %g3 = getelementptr %struct.A, ptr %a, i32 0, i32 1
200  store i32 10, ptr %g3, align 4
201
202
203
204  %g5 = getelementptr %struct.A, ptr %a, i32 0, i32 1
205  %a_a = load i32, ptr %g5, align 4
206  ret i32 %a_a
207}
208
209
210; PR2235
211%S = type { i32, [ 100 x i32] }
212define i1 @test13(i64 %X, ptr %P) {
213; CHECK-LABEL: @test13(
214; CHECK-NEXT:    [[C:%.*]] = icmp eq i64 [[X:%.*]], -1
215; CHECK-NEXT:    ret i1 [[C]]
216;
217  %A = getelementptr inbounds %S, ptr %P, i32 0, i32 1, i64 %X
218  %C = icmp eq ptr %A, %P
219  ret i1 %C
220}
221
222define <2 x i1> @test13_vector(<2 x i64> %X, <2 x ptr> %P) nounwind {
223; CHECK-LABEL: @test13_vector(
224; CHECK-NEXT:    [[C:%.*]] = icmp eq <2 x i64> [[X:%.*]], <i64 -1, i64 -1>
225; CHECK-NEXT:    ret <2 x i1> [[C]]
226;
227  %A = getelementptr inbounds %S, <2 x ptr> %P, <2 x i64> zeroinitializer, <2 x i32> <i32 1, i32 1>, <2 x i64> %X
228  %B = getelementptr inbounds %S, <2 x ptr> %P, <2 x i64> <i64 0, i64 0>, <2 x i32> <i32 0, i32 0>
229  %C = icmp eq <2 x ptr> %A, %B
230  ret <2 x i1> %C
231}
232
233define <2 x i1> @test13_vector2(i64 %X, <2 x ptr> %P) nounwind {
234; CHECK-LABEL: @test13_vector2(
235; CHECK-NEXT:    [[DOTSPLATINSERT:%.*]] = insertelement <2 x i64> poison, i64 [[X:%.*]], i64 0
236; CHECK-NEXT:    [[TMP1:%.*]] = shl <2 x i64> [[DOTSPLATINSERT]], <i64 2, i64 0>
237; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq <2 x i64> [[TMP1]], <i64 -4, i64 poison>
238; CHECK-NEXT:    [[C:%.*]] = shufflevector <2 x i1> [[TMP2]], <2 x i1> poison, <2 x i32> zeroinitializer
239; CHECK-NEXT:    ret <2 x i1> [[C]]
240;
241  %A = getelementptr inbounds %S, <2 x ptr> %P, <2 x i64> zeroinitializer, <2 x i32> <i32 1, i32 1>, i64 %X
242  %B = getelementptr inbounds %S, <2 x ptr> %P, <2 x i64> <i64 0, i64 0>, <2 x i32> <i32 0, i32 0>
243  %C = icmp eq <2 x ptr> %A, %B
244  ret <2 x i1> %C
245}
246
247define <2 x i1> @test13_fixed_fixed(i64 %X, ptr %P, <2 x i64> %y) nounwind {
248; CHECK-LABEL: @test13_fixed_fixed(
249; CHECK-NEXT:    [[DOTSPLATINSERT:%.*]] = insertelement <2 x i64> poison, i64 [[X:%.*]], i64 0
250; CHECK-NEXT:    [[TMP1:%.*]] = shl <2 x i64> [[DOTSPLATINSERT]], <i64 3, i64 0>
251; CHECK-NEXT:    [[A_IDX:%.*]] = shufflevector <2 x i64> [[TMP1]], <2 x i64> poison, <2 x i32> zeroinitializer
252; CHECK-NEXT:    [[B_IDX:%.*]] = shl nsw <2 x i64> [[Y:%.*]], <i64 4, i64 4>
253; CHECK-NEXT:    [[C:%.*]] = icmp eq <2 x i64> [[A_IDX]], [[B_IDX]]
254; CHECK-NEXT:    ret <2 x i1> [[C]]
255;
256  %A = getelementptr inbounds <2 x i64>, ptr %P, <2 x i64> zeroinitializer, i64 %X
257  %B = getelementptr inbounds <2 x i64>, ptr %P, <2 x i64> %y
258  %C = icmp eq <2 x ptr> %A, %B
259  ret <2 x i1> %C
260}
261
262define <2 x i1> @test13_fixed_scalable(i64 %X, ptr %P, <2 x i64> %y) nounwind {
263; CHECK-LABEL: @test13_fixed_scalable(
264; CHECK-NEXT:    [[DOTSPLATINSERT:%.*]] = insertelement <2 x i64> poison, i64 [[X:%.*]], i64 0
265; CHECK-NEXT:    [[TMP1:%.*]] = shl <2 x i64> [[DOTSPLATINSERT]], <i64 3, i64 0>
266; CHECK-NEXT:    [[A_IDX:%.*]] = shufflevector <2 x i64> [[TMP1]], <2 x i64> poison, <2 x i32> zeroinitializer
267; CHECK-NEXT:    [[TMP2:%.*]] = call i64 @llvm.vscale.i64()
268; CHECK-NEXT:    [[TMP3:%.*]] = shl i64 [[TMP2]], 4
269; CHECK-NEXT:    [[DOTSPLATINSERT1:%.*]] = insertelement <2 x i64> poison, i64 [[TMP3]], i64 0
270; CHECK-NEXT:    [[DOTSPLAT:%.*]] = shufflevector <2 x i64> [[DOTSPLATINSERT1]], <2 x i64> poison, <2 x i32> zeroinitializer
271; CHECK-NEXT:    [[B_IDX:%.*]] = mul nsw <2 x i64> [[DOTSPLAT]], [[Y:%.*]]
272; CHECK-NEXT:    [[C:%.*]] = icmp eq <2 x i64> [[A_IDX]], [[B_IDX]]
273; CHECK-NEXT:    ret <2 x i1> [[C]]
274;
275  %A = getelementptr inbounds <vscale x 2 x i64>, ptr %P, <2 x i64> zeroinitializer, i64 %X
276  %B = getelementptr inbounds <vscale x 2 x i64>, ptr %P, <2 x i64> %y
277  %C = icmp eq <2 x ptr> %A, %B
278  ret <2 x i1> %C
279}
280
281define <vscale x 2 x i1> @test13_scalable_scalable(i64 %X, ptr %P, <vscale x 2 x i64> %y) nounwind {
282; CHECK-LABEL: @test13_scalable_scalable(
283; CHECK-NEXT:    [[DOTSPLATINSERT:%.*]] = insertelement <vscale x 2 x i64> poison, i64 [[X:%.*]], i64 0
284; CHECK-NEXT:    [[DOTSPLAT:%.*]] = shufflevector <vscale x 2 x i64> [[DOTSPLATINSERT]], <vscale x 2 x i64> poison, <vscale x 2 x i32> zeroinitializer
285; CHECK-NEXT:    [[A_IDX:%.*]] = shl nsw <vscale x 2 x i64> [[DOTSPLAT]], shufflevector (<vscale x 2 x i64> insertelement (<vscale x 2 x i64> poison, i64 3, i64 0), <vscale x 2 x i64> poison, <vscale x 2 x i32> zeroinitializer)
286; CHECK-NEXT:    [[TMP1:%.*]] = call i64 @llvm.vscale.i64()
287; CHECK-NEXT:    [[TMP2:%.*]] = shl i64 [[TMP1]], 4
288; CHECK-NEXT:    [[DOTSPLATINSERT1:%.*]] = insertelement <vscale x 2 x i64> poison, i64 [[TMP2]], i64 0
289; CHECK-NEXT:    [[DOTSPLAT2:%.*]] = shufflevector <vscale x 2 x i64> [[DOTSPLATINSERT1]], <vscale x 2 x i64> poison, <vscale x 2 x i32> zeroinitializer
290; CHECK-NEXT:    [[B_IDX:%.*]] = mul nsw <vscale x 2 x i64> [[DOTSPLAT2]], [[Y:%.*]]
291; CHECK-NEXT:    [[C:%.*]] = icmp eq <vscale x 2 x i64> [[A_IDX]], [[B_IDX]]
292; CHECK-NEXT:    ret <vscale x 2 x i1> [[C]]
293;
294  %A = getelementptr inbounds <vscale x 2 x i64>, ptr %P, <vscale x 2 x i64> zeroinitializer, i64 %X
295  %B = getelementptr inbounds <vscale x 2 x i64>, ptr %P, <vscale x 2 x i64> %y
296  %C = icmp eq <vscale x 2 x ptr> %A, %B
297  ret <vscale x 2 x i1> %C
298}
299
300; This is a test of icmp + shl nuw in disguise - 4611... is 0x3fff...
301define <2 x i1> @test13_vector3(i64 %X, <2 x ptr> %P) nounwind {
302; CHECK-LABEL: @test13_vector3(
303; CHECK-NEXT:    [[DOTSPLATINSERT:%.*]] = insertelement <2 x i64> poison, i64 [[X:%.*]], i64 0
304; CHECK-NEXT:    [[TMP1:%.*]] = shl <2 x i64> [[DOTSPLATINSERT]], <i64 2, i64 0>
305; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq <2 x i64> [[TMP1]], <i64 4, i64 poison>
306; CHECK-NEXT:    [[C:%.*]] = shufflevector <2 x i1> [[TMP2]], <2 x i1> poison, <2 x i32> zeroinitializer
307; CHECK-NEXT:    ret <2 x i1> [[C]]
308;
309  %A = getelementptr inbounds %S, <2 x ptr> %P, <2 x i64> zeroinitializer, <2 x i32> <i32 1, i32 1>, i64 %X
310  %B = getelementptr inbounds %S, <2 x ptr> %P, <2 x i64> <i64 0, i64 0>, <2 x i32> <i32 1, i32 1>, i64 1
311  %C = icmp eq <2 x ptr> %A, %B
312  ret <2 x i1> %C
313}
314
315define i1 @test13_as1(i16 %X, ptr addrspace(1) %P) {
316; CHECK-LABEL: @test13_as1(
317; CHECK-NEXT:    [[C:%.*]] = icmp eq i16 [[X:%.*]], -1
318; CHECK-NEXT:    ret i1 [[C]]
319;
320  %A = getelementptr inbounds %S, ptr addrspace(1) %P, i16 0, i32 1, i16 %X
321  %C = icmp eq ptr addrspace(1) %A, %P
322  ret i1 %C
323}
324
325define <2 x i1> @test13_vector_as1(<2 x i16> %X, <2 x ptr addrspace(1)> %P) {
326; CHECK-LABEL: @test13_vector_as1(
327; CHECK-NEXT:    [[C:%.*]] = icmp eq <2 x i16> [[X:%.*]], <i16 -1, i16 -1>
328; CHECK-NEXT:    ret <2 x i1> [[C]]
329;
330  %A = getelementptr inbounds %S, <2 x ptr addrspace(1)> %P, <2 x i16> <i16 0, i16 0>, <2 x i32> <i32 1, i32 1>, <2 x i16> %X
331  %B = getelementptr inbounds %S, <2 x ptr addrspace(1)> %P, <2 x i16> <i16 0, i16 0>, <2 x i32> <i32 0, i32 0>
332  %C = icmp eq <2 x ptr addrspace(1)> %A, %B
333  ret <2 x i1> %C
334}
335
336define i1 @test13_i32(i32 %X, ptr %P) {
337; CHECK-LABEL: @test13_i32(
338; CHECK-NEXT:    [[C:%.*]] = icmp eq i32 [[X:%.*]], -1
339; CHECK-NEXT:    ret i1 [[C]]
340;
341  %A = getelementptr inbounds %S, ptr %P, i32 0, i32 1, i32 %X
342  %C = icmp eq ptr %A, %P
343  ret i1 %C
344}
345
346define i1 @test13_i16(i16 %X, ptr %P) {
347; CHECK-LABEL: @test13_i16(
348; CHECK-NEXT:    [[C:%.*]] = icmp eq i16 [[X:%.*]], -1
349; CHECK-NEXT:    ret i1 [[C]]
350;
351  %A = getelementptr inbounds %S, ptr %P, i16 0, i32 1, i16 %X
352  %C = icmp eq ptr %A, %P
353  ret i1 %C
354}
355
356define i1 @test13_i128(i128 %X, ptr %P) {
357; CHECK-LABEL: @test13_i128(
358; CHECK-NEXT:    [[TMP1:%.*]] = trunc i128 [[X:%.*]] to i64
359; CHECK-NEXT:    [[C:%.*]] = icmp eq i64 [[TMP1]], -1
360; CHECK-NEXT:    ret i1 [[C]]
361;
362  %A = getelementptr inbounds %S, ptr %P, i128 0, i32 1, i128 %X
363  %C = icmp eq ptr %A, %P
364  ret i1 %C
365}
366
367
368@G = external global [3 x i8]
369define ptr @test14(i32 %idx) {
370; CHECK-LABEL: @test14(
371; CHECK-NEXT:    [[ZEXT:%.*]] = zext i32 [[IDX:%.*]] to i64
372; CHECK-NEXT:    [[T:%.*]] = getelementptr i8, ptr @G, i64 [[ZEXT]]
373; CHECK-NEXT:    ret ptr [[T]]
374;
375  %zext = zext i32 %idx to i64
376  %t = getelementptr i8, ptr @G, i64 %zext
377  ret ptr %t
378}
379
380
381; Test folding of constantexpr geps into normal geps.
382@Array = external global [40 x i32]
383define ptr @test15(i64 %X) {
384; CHECK-LABEL: @test15(
385; CHECK-NEXT:    [[A:%.*]] = getelementptr i32, ptr @Array, i64 [[X:%.*]]
386; CHECK-NEXT:    ret ptr [[A]]
387;
388  %A = getelementptr i32, ptr @Array, i64 %X
389  ret ptr %A
390}
391
392define ptr @test_index_canon(ptr %X, i32 %Idx) {
393; CHECK-LABEL: @test_index_canon(
394; CHECK-NEXT:    [[TMP1:%.*]] = sext i32 [[IDX:%.*]] to i64
395; CHECK-NEXT:    [[R:%.*]] = getelementptr i32, ptr [[X:%.*]], i64 [[TMP1]]
396; CHECK-NEXT:    ret ptr [[R]]
397;
398  %R = getelementptr i32, ptr %X, i32 %Idx
399  ret ptr %R
400}
401
402define ptr @test_index_canon_inbounds(ptr %X, i32 %Idx) {
403; CHECK-LABEL: @test_index_canon_inbounds(
404; CHECK-NEXT:    [[TMP1:%.*]] = sext i32 [[IDX:%.*]] to i64
405; CHECK-NEXT:    [[R:%.*]] = getelementptr inbounds i32, ptr [[X:%.*]], i64 [[TMP1]]
406; CHECK-NEXT:    ret ptr [[R]]
407;
408  %R = getelementptr inbounds i32, ptr %X, i32 %Idx
409  ret ptr %R
410}
411
412define ptr @test_index_canon_nusw_nuw(ptr %X, i32 %Idx) {
413; CHECK-LABEL: @test_index_canon_nusw_nuw(
414; CHECK-NEXT:    [[TMP1:%.*]] = sext i32 [[IDX:%.*]] to i64
415; CHECK-NEXT:    [[R:%.*]] = getelementptr nusw nuw i32, ptr [[X:%.*]], i64 [[TMP1]]
416; CHECK-NEXT:    ret ptr [[R]]
417;
418  %R = getelementptr nusw nuw i32, ptr %X, i32 %Idx
419  ret ptr %R
420}
421
422define ptr @test_index_canon_const_expr_inbounds() {
423; CHECK-LABEL: @test_index_canon_const_expr_inbounds(
424; CHECK-NEXT:    ret ptr getelementptr inbounds (i8, ptr @Global, i64 123)
425;
426  ret ptr getelementptr inbounds (i8, ptr @Global, i32 123)
427}
428
429define ptr @test_index_canon_const_expr_nuw_nusw() {
430; CHECK-LABEL: @test_index_canon_const_expr_nuw_nusw(
431; CHECK-NEXT:    ret ptr getelementptr nusw nuw (i8, ptr @Global, i64 123)
432;
433  ret ptr getelementptr nusw nuw (i8, ptr @Global, i32 123)
434}
435
436define ptr @test_const_gep_gep_nuw() {
437; CHECK-LABEL: @test_const_gep_gep_nuw(
438; CHECK-NEXT:    ret ptr getelementptr nuw (i8, ptr @Global, i64 246)
439;
440  ret ptr getelementptr nuw (i8, ptr getelementptr nuw (i8, ptr @Global, i64 123), i64 123)
441}
442
443define ptr @test_const_gep_gep_nusw_no_overflow() {
444; CHECK-LABEL: @test_const_gep_gep_nusw_no_overflow(
445; CHECK-NEXT:    ret ptr getelementptr nusw (i8, ptr @Global, i64 246)
446;
447  ret ptr getelementptr nusw (i8, ptr getelementptr nusw (i8, ptr @Global, i64 123), i64 123)
448}
449
450define ptr @test_const_gep_gep_nusw_no_overflow_neg() {
451; CHECK-LABEL: @test_const_gep_gep_nusw_no_overflow_neg(
452; CHECK-NEXT:    ret ptr getelementptr nusw (i8, ptr @Global, i64 -246)
453;
454  ret ptr getelementptr nusw (i8, ptr getelementptr nusw (i8, ptr @Global, i64 -123), i64 -123)
455}
456
457define ptr @test_const_gep_gep_nusw_overflow() {
458; CHECK-LABEL: @test_const_gep_gep_nusw_overflow(
459; CHECK-NEXT:    ret ptr getelementptr (i8, ptr @Global, i64 -2)
460;
461  ret ptr getelementptr nusw (i8, ptr getelementptr nusw (i8, ptr @Global, i64 u0x7fffffffffffffff), i64 u0x7fffffffffffffff)
462}
463
464define i1 @test17(ptr %P, i32 %I, i32 %J) {
465; CHECK-LABEL: @test17(
466; CHECK-NEXT:    [[C:%.*]] = icmp slt i32 [[I:%.*]], [[J:%.*]]
467; CHECK-NEXT:    ret i1 [[C]]
468;
469  %X = getelementptr inbounds i16, ptr %P, i32 %I
470  %Y = getelementptr inbounds i16, ptr %P, i32 %J
471  %C = icmp ult ptr %X, %Y
472  ret i1 %C
473}
474
475define i1 @test18(ptr %P, i32 %I) {
476; CHECK-LABEL: @test18(
477; CHECK-NEXT:    [[C:%.*]] = icmp slt i32 [[I:%.*]], 0
478; CHECK-NEXT:    ret i1 [[C]]
479;
480  %X = getelementptr inbounds i16, ptr %P, i32 %I
481  %C = icmp ult ptr %X, %P
482  ret i1 %C
483}
484
485; Larger than the pointer size for a non-zero address space
486define i1 @test18_as1(ptr addrspace(1) %P, i32 %I) {
487; CHECK-LABEL: @test18_as1(
488; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[I:%.*]], 32768
489; CHECK-NEXT:    [[C:%.*]] = icmp ne i32 [[TMP1]], 0
490; CHECK-NEXT:    ret i1 [[C]]
491;
492  %X = getelementptr inbounds i16, ptr addrspace(1) %P, i32 %I
493  %C = icmp ult ptr addrspace(1) %X, %P
494  ret i1 %C
495}
496
497; Smaller than the pointer size for a non-zero address space
498define i1 @test18_as1_i32(ptr addrspace(1) %P, i32 %I) {
499; CHECK-LABEL: @test18_as1_i32(
500; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[I:%.*]], 32768
501; CHECK-NEXT:    [[C:%.*]] = icmp ne i32 [[TMP1]], 0
502; CHECK-NEXT:    ret i1 [[C]]
503;
504  %X = getelementptr inbounds i16, ptr addrspace(1) %P, i32 %I
505  %C = icmp ult ptr addrspace(1) %X, %P
506  ret i1 %C
507}
508
509; Smaller than pointer size
510define i1 @test18_i16(ptr %P, i16 %I) {
511; CHECK-LABEL: @test18_i16(
512; CHECK-NEXT:    [[C:%.*]] = icmp slt i16 [[I:%.*]], 0
513; CHECK-NEXT:    ret i1 [[C]]
514;
515  %X = getelementptr inbounds i16, ptr %P, i16 %I
516  %C = icmp ult ptr %X, %P
517  ret i1 %C
518}
519
520; Same as pointer size
521define i1 @test18_i64(ptr %P, i64 %I) {
522; CHECK-LABEL: @test18_i64(
523; CHECK-NEXT:    [[C:%.*]] = icmp slt i64 [[I:%.*]], 0
524; CHECK-NEXT:    ret i1 [[C]]
525;
526  %X = getelementptr inbounds i16, ptr %P, i64 %I
527  %C = icmp ult ptr %X, %P
528  ret i1 %C
529}
530
531; Larger than the pointer size
532define i1 @test18_i128(ptr %P, i128 %I) {
533; CHECK-LABEL: @test18_i128(
534; CHECK-NEXT:    [[TMP1:%.*]] = and i128 [[I:%.*]], 9223372036854775808
535; CHECK-NEXT:    [[C:%.*]] = icmp ne i128 [[TMP1]], 0
536; CHECK-NEXT:    ret i1 [[C]]
537;
538  %X = getelementptr inbounds i16, ptr %P, i128 %I
539  %C = icmp ult ptr %X, %P
540  ret i1 %C
541}
542
543define i32 @test19(ptr %P, i32 %A, i32 %B) {
544; CHECK-LABEL: @test19(
545; CHECK-NEXT:    [[T10:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
546; CHECK-NEXT:    [[T11:%.*]] = zext i1 [[T10]] to i32
547; CHECK-NEXT:    ret i32 [[T11]]
548;
549  %t4 = getelementptr inbounds i32, ptr %P, i32 %A
550  %t9 = getelementptr inbounds i32, ptr %P, i32 %B
551  %t10 = icmp eq ptr %t4, %t9
552  %t11 = zext i1 %t10 to i32
553  ret i32 %t11
554}
555
556define i32 @test20(ptr %P, i32 %A, i32 %B) {
557; CHECK-LABEL: @test20(
558; CHECK-NEXT:    [[T6:%.*]] = icmp eq i32 [[A:%.*]], 0
559; CHECK-NEXT:    [[T7:%.*]] = zext i1 [[T6]] to i32
560; CHECK-NEXT:    ret i32 [[T7]]
561;
562  %t4 = getelementptr inbounds i32, ptr %P, i32 %A
563  %t6 = icmp eq ptr %t4, %P
564  %t7 = zext i1 %t6 to i32
565  ret i32 %t7
566}
567
568define i32 @test20_as1(ptr addrspace(1) %P, i32 %A, i32 %B) {
569; CHECK-LABEL: @test20_as1(
570; CHECK-NEXT:    [[TMP1:%.*]] = trunc i32 [[A:%.*]] to i16
571; CHECK-NEXT:    [[T6:%.*]] = icmp eq i16 [[TMP1]], 0
572; CHECK-NEXT:    [[T7:%.*]] = zext i1 [[T6]] to i32
573; CHECK-NEXT:    ret i32 [[T7]]
574;
575  %t4 = getelementptr inbounds i32, ptr addrspace(1) %P, i32 %A
576  %t6 = icmp eq ptr addrspace(1) %t4, %P
577  %t7 = zext i1 %t6 to i32
578  ret i32 %t7
579}
580
581
582define i32 @test21() {
583; CHECK-LABEL: @test21(
584; CHECK-NEXT:    [[PBOB1:%.*]] = alloca [[INTSTRUCT:%.*]], align 8
585; CHECK-NEXT:    [[RVAL:%.*]] = load i32, ptr [[PBOB1]], align 4
586; CHECK-NEXT:    ret i32 [[RVAL]]
587;
588  %pbob1 = alloca %intstruct
589  %pbob2 = getelementptr %intstruct, ptr %pbob1
590  %rval = load i32, ptr %pbob2
591  ret i32 %rval
592}
593
594
595@A = global i32 1               ; <ptr> [#uses=1]
596@B = global i32 2               ; <ptr> [#uses=1]
597
598define i1 @test22() {
599; CHECK-LABEL: @test22(
600; CHECK-NEXT:    [[C:%.*]] = icmp ult ptr getelementptr inbounds (i8, ptr @A, i64 4), getelementptr (i8, ptr @B, i64 8)
601; CHECK-NEXT:    ret i1 [[C]]
602;
603  %C = icmp ult ptr getelementptr (i32, ptr @A, i64 1),
604  getelementptr (i32, ptr @B, i64 2)
605  ret i1 %C
606}
607
608
609%X = type { [10 x i32], float }
610
611define i1 @test23() {
612; CHECK-LABEL: @test23(
613; CHECK-NEXT:    ret i1 false
614;
615  %A = getelementptr %X, ptr null, i64 0, i32 0, i64 0                ; <ptr> [#uses=1]
616  %B = icmp ne ptr %A, null              ; <i1> [#uses=1]
617  ret i1 %B
618}
619
620define void @test25() {
621; CHECK-LABEL: @test25(
622; CHECK-NEXT:  entry:
623; CHECK-NEXT:    unreachable
624;
625entry:
626  %t = getelementptr { i64, i64, i64, i64 }, ptr null, i32 0, i32 3
627  %t.upgrd.1 = load i64, ptr %t
628  %t8.ui = load i64, ptr null
629  %t8 = bitcast i64 %t8.ui to i64
630  %t9 = and i64 %t8, %t.upgrd.1
631  %sext = trunc i64 %t9 to i32
632  %t27.i = sext i32 %sext to i64
633  tail call void @foo25( i32 0, i64 %t27.i )
634  unreachable
635}
636
637declare void @foo25(i32, i64)
638
639
640; PR1637
641define i1 @test26(ptr %arr) {
642; CHECK-LABEL: @test26(
643; CHECK-NEXT:    ret i1 true
644;
645  %X = getelementptr i8, ptr %arr, i32 1
646  %Y = getelementptr i8, ptr %arr, i32 1
647  %test = icmp uge ptr %X, %Y
648  ret i1 %test
649}
650
651  %struct.__large_struct = type { [100 x i64] }
652  %struct.compat_siginfo = type { i32, i32, i32, { [29 x i32] } }
653  %struct.siginfo_t = type { i32, i32, i32, { { i32, i32, [0 x i8], %struct.sigval_t, i32 }, [88 x i8] } }
654  %struct.sigval_t = type { ptr }
655
656define i32 @test27(ptr %to, ptr %from) {
657; CHECK-LABEL: @test27(
658; CHECK-NEXT:  entry:
659; CHECK-NEXT:    [[FROM_ADDR:%.*]] = alloca ptr, align 8
660; CHECK-NEXT:    [[T344:%.*]] = load ptr, ptr [[FROM_ADDR]], align 8
661; CHECK-NEXT:    [[T348:%.*]] = getelementptr i8, ptr [[T344]], i64 24
662; CHECK-NEXT:    [[T351:%.*]] = load i32, ptr [[T348]], align 8
663; CHECK-NEXT:    [[T360:%.*]] = call i32 asm sideeffect "...", "=r,ir,*m,i,0,~{dirflag},~{fpsr},~{flags}"(i32 [[T351]], ptr elementtype([[STRUCT___LARGE_STRUCT:%.*]]) null, i32 -14, i32 0) #[[ATTR0:[0-9]+]]
664; CHECK-NEXT:    unreachable
665;
666entry:
667  %from_addr = alloca ptr
668  %t344 = load ptr, ptr %from_addr, align 8
669  %t345 = getelementptr %struct.siginfo_t, ptr %t344, i32 0, i32 3
670  %t346 = getelementptr { { i32, i32, [0 x i8], %struct.sigval_t, i32 }, [88 x i8] }, ptr %t345, i32 0, i32 0
671  %t348 = getelementptr { i32, i32, %struct.sigval_t }, ptr %t346, i32 0, i32 2
672  %t351 = load i32, ptr %t348, align 8
673  %t360 = call i32 asm sideeffect "...",
674  "=r,ir,*m,i,0,~{dirflag},~{fpsr},~{flags}"( i32 %t351, ptr elementtype(%struct.__large_struct) null, i32 -14, i32 0 )
675  unreachable
676}
677
678; PR1978
679  %struct.x = type <{ i8 }>
680@.str = internal constant [6 x i8] c"Main!\00"
681@.str1 = internal constant [12 x i8] c"destroy %p\0A\00"
682
683define i32 @test28() nounwind  {
684; CHECK-LABEL: @test28(
685; CHECK-NEXT:  entry:
686; CHECK-NEXT:    [[ORIENTATIONS:%.*]] = alloca [1 x [1 x %struct.x]], align 8
687; CHECK-NEXT:    [[T3:%.*]] = call i32 @puts(ptr noundef nonnull dereferenceable(1) @.str) #[[ATTR0]]
688; CHECK-NEXT:    [[T45:%.*]] = getelementptr inbounds i8, ptr [[ORIENTATIONS]], i64 1
689; CHECK-NEXT:    br label [[BB10:%.*]]
690; CHECK:       bb10:
691; CHECK-NEXT:    [[INDVAR:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[BB10]] ]
692; CHECK-NEXT:    [[T12_REC:%.*]] = xor i32 [[INDVAR]], -1
693; CHECK-NEXT:    [[TMP0:%.*]] = sext i32 [[T12_REC]] to i64
694; CHECK-NEXT:    [[T12:%.*]] = getelementptr inbounds [[STRUCT_X:%.*]], ptr [[T45]], i64 [[TMP0]]
695; CHECK-NEXT:    [[T16:%.*]] = call i32 (ptr, ...) @printf(ptr noundef nonnull dereferenceable(1) @.str1, ptr nonnull [[T12]]) #[[ATTR0]]
696; CHECK-NEXT:    [[T84:%.*]] = icmp eq ptr [[T12]], [[ORIENTATIONS]]
697; CHECK-NEXT:    [[INDVAR_NEXT]] = add i32 [[INDVAR]], 1
698; CHECK-NEXT:    br i1 [[T84]], label [[BB17:%.*]], label [[BB10]]
699; CHECK:       bb17:
700; CHECK-NEXT:    ret i32 0
701;
702entry:
703  %orientations = alloca [1 x [1 x %struct.x]]
704  %t3 = call i32 @puts( ptr @.str ) nounwind
705  %t45 = getelementptr inbounds [1 x [1 x %struct.x]], ptr %orientations, i32 1, i32 0, i32 0
706  br label %bb10
707
708bb10:
709  %indvar = phi i32 [ 0, %entry ], [ %indvar.next, %bb10 ]
710  %t.0.reg2mem.0.rec = mul i32 %indvar, -1
711  %t12.rec = add i32 %t.0.reg2mem.0.rec, -1
712  %t12 = getelementptr inbounds %struct.x, ptr %t45, i32 %t12.rec
713  %t16 = call i32 (ptr, ...) @printf( ptr nonnull dereferenceable(1) @.str1, ptr %t12 ) nounwind
714  %t84 = icmp eq ptr %t12, %orientations
715  %indvar.next = add i32 %indvar, 1
716  br i1 %t84, label %bb17, label %bb10
717
718bb17:
719  ret i32 0
720}
721
722declare i32 @puts(ptr)
723
724declare i32 @printf(ptr, ...)
725
726
727
728
729; rdar://6762290
730  %T = type <{ i64, i64, i64 }>
731define i32 @test29(ptr %start, i32 %X) nounwind {
732; CHECK-LABEL: @test29(
733; CHECK-NEXT:  entry:
734; CHECK-NEXT:    store i1 true, ptr poison, align 1
735; CHECK-NEXT:    br i1 poison, label [[IF_THEN216:%.*]], label [[IF_END363:%.*]]
736; CHECK:       if.then216:
737; CHECK-NEXT:    ret i32 1
738; CHECK:       if.end363:
739; CHECK-NEXT:    ret i32 0
740;
741entry:
742  %t3 = load i64, ptr null
743  %add.ptr = getelementptr i8, ptr %start, i64 %t3
744  %t158 = load i32, ptr null
745  %add.ptr159 = getelementptr %T, ptr null, i32 %t158
746  %add.ptr212 = getelementptr i8, ptr %start, i32 %X
747  %cmp214 = icmp ugt ptr %add.ptr212, %add.ptr
748  br i1 %cmp214, label %if.then216, label %if.end363
749
750if.then216:
751  ret i32 1
752
753if.end363:
754  ret i32 0
755}
756
757
758; PR3694
759define i32 @test30(i32 %m, i32 %n) nounwind {
760; CHECK-LABEL: @test30(
761; CHECK-NEXT:  entry:
762; CHECK-NEXT:    [[TMP0:%.*]] = zext i32 [[N:%.*]] to i64
763; CHECK-NEXT:    [[TMP1:%.*]] = alloca i32, i64 [[TMP0]], align 4
764; CHECK-NEXT:    call void @test30f(ptr nonnull [[TMP1]]) #[[ATTR0]]
765; CHECK-NEXT:    [[TMP2:%.*]] = sext i32 [[M:%.*]] to i64
766; CHECK-NEXT:    [[TMP3:%.*]] = getelementptr [0 x i32], ptr [[TMP1]], i64 0, i64 [[TMP2]]
767; CHECK-NEXT:    [[TMP4:%.*]] = load i32, ptr [[TMP3]], align 4
768; CHECK-NEXT:    ret i32 [[TMP4]]
769;
770entry:
771  %0 = alloca i32, i32 %n, align 4
772  call void @test30f(ptr %0) nounwind
773  %1 = getelementptr [0 x i32], ptr %0, i32 0, i32 %m
774  %2 = load i32, ptr %1, align 4
775  ret i32 %2
776}
777
778declare void @test30f(ptr)
779
780
781
782define i1 @test31(ptr %A) {
783; CHECK-LABEL: @test31(
784; CHECK-NEXT:    ret i1 true
785;
786  %B = getelementptr i32, ptr %A, i32 1
787  %C = getelementptr i32, ptr %A, i64 1
788  %V = icmp eq ptr %B, %C
789  ret i1 %V
790}
791
792
793; PR1345
794define ptr @test32(ptr %v) {
795; CHECK-LABEL: @test32(
796; CHECK-NEXT:    [[A:%.*]] = alloca [4 x ptr], align 16
797; CHECK-NEXT:    store ptr null, ptr [[A]], align 8
798; CHECK-NEXT:    [[D:%.*]] = getelementptr inbounds i8, ptr [[A]], i64 8
799; CHECK-NEXT:    store ptr [[V:%.*]], ptr [[D]], align 8
800; CHECK-NEXT:    [[F:%.*]] = getelementptr inbounds i8, ptr [[A]], i64 16
801; CHECK-NEXT:    [[G:%.*]] = load ptr, ptr [[F]], align 8
802; CHECK-NEXT:    ret ptr [[G]]
803;
804  %A = alloca [4 x ptr], align 16
805  store ptr null, ptr %A
806  %D = getelementptr { [16 x i8] }, ptr %A, i32 0, i32 0, i32 8
807  store ptr %v, ptr %D
808  %F = getelementptr [4 x ptr], ptr %A, i32 0, i32 2
809  %G = load ptr, ptr %F
810  ret ptr %G
811}
812
813; PR3290
814%struct.Key = type { { i32, i32 } }
815%struct.anon = type <{ i8, [3 x i8], i32 }>
816
817define ptr @test33(ptr %A) {
818; CHECK-LABEL: @test33(
819; CHECK-NEXT:    [[C:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 4
820; CHECK-NEXT:    ret ptr [[C]]
821;
822  %C = getelementptr %struct.anon, ptr %A, i32 0, i32 2
823  ret ptr %C
824}
825
826define ptr addrspace(1) @test33_as1(ptr addrspace(1) %A) {
827; CHECK-LABEL: @test33_as1(
828; CHECK-NEXT:    [[C:%.*]] = getelementptr i8, ptr addrspace(1) [[A:%.*]], i16 4
829; CHECK-NEXT:    ret ptr addrspace(1) [[C]]
830;
831  %C = getelementptr %struct.anon, ptr addrspace(1) %A, i32 0, i32 2
832  ret ptr addrspace(1) %C
833}
834
835define ptr addrspace(1) @test33_array_as1(ptr addrspace(1) %A) {
836; CHECK-LABEL: @test33_array_as1(
837; CHECK-NEXT:    [[C:%.*]] = getelementptr i8, ptr addrspace(1) [[A:%.*]], i16 8
838; CHECK-NEXT:    ret ptr addrspace(1) [[C]]
839;
840  %C = getelementptr [5 x i32], ptr addrspace(1) %A, i32 0, i32 2
841  ret ptr addrspace(1) %C
842}
843
844; Make sure the GEP indices use the right pointer sized integer
845define ptr addrspace(1) @test33_array_struct_as1(ptr addrspace(1) %A) {
846; CHECK-LABEL: @test33_array_struct_as1(
847; CHECK-NEXT:    [[C:%.*]] = getelementptr i8, ptr addrspace(1) [[A:%.*]], i16 8
848; CHECK-NEXT:    ret ptr addrspace(1) [[C]]
849;
850  %C = getelementptr [20 x i32], ptr addrspace(1) %A, i32 0, i32 2
851  ret ptr addrspace(1) %C
852}
853
854define ptr addrspace(1) @test33_addrspacecast(ptr %A) {
855; CHECK-LABEL: @test33_addrspacecast(
856; CHECK-NEXT:    [[B:%.*]] = addrspacecast ptr [[A:%.*]] to ptr addrspace(1)
857; CHECK-NEXT:    [[C:%.*]] = getelementptr i8, ptr addrspace(1) [[B]], i16 4
858; CHECK-NEXT:    ret ptr addrspace(1) [[C]]
859;
860  %B = addrspacecast ptr %A to ptr addrspace(1)
861  %C = getelementptr %struct.anon, ptr addrspace(1) %B, i32 0, i32 2
862  ret ptr addrspace(1) %C
863}
864
865  %T2 = type { ptr, i8 }
866define ptr @test34(ptr %Val, i64 %V) nounwind {
867; CHECK-LABEL: @test34(
868; CHECK-NEXT:  entry:
869; CHECK-NEXT:    [[C_CAST:%.*]] = inttoptr i64 [[V:%.*]] to ptr
870; CHECK-NEXT:    ret ptr [[C_CAST]]
871;
872entry:
873  %A = alloca %T2, align 8
874
875  store i64 %V, ptr %A
876  %C = load ptr, ptr %A, align 8
877  ret ptr %C
878}
879
880%t0 = type { ptr, [19 x i8] }
881%t1 = type { ptr, [0 x i8] }
882
883@array = external global [11 x i8]
884
885@s = external global %t0
886@"\01LC8" = external constant [17 x i8]
887
888; Instcombine should be able to fold this getelementptr.
889
890define i32 @test35() nounwind {
891; CHECK-LABEL: @test35(
892; CHECK-NEXT:    [[TMP1:%.*]] = call i32 (ptr, ...) @printf(ptr noundef nonnull dereferenceable(1) @"\01LC8", ptr nonnull getelementptr inbounds (i8, ptr @s, i64 8)) #[[ATTR0]]
893; CHECK-NEXT:    ret i32 0
894;
895  call i32 (ptr, ...) @printf(ptr @"\01LC8",
896  ptr getelementptr (%t1, ptr @s, i32 0, i32 1, i32 0)) nounwind
897  ret i32 0
898}
899
900; Don't treat signed offsets as unsigned.
901define ptr @test36() nounwind {
902; CHECK-LABEL: @test36(
903; CHECK-NEXT:    ret ptr getelementptr (i8, ptr @array, i64 -1)
904;
905  ret ptr getelementptr ([11 x i8], ptr @array, i32 0, i64 -1)
906}
907
908; Instcombine shouldn't assume that gep(A,0,1) != gep(A,1,0).
909@A37 = external constant [1 x i8]
910define i1 @test37() nounwind {
911; CHECK-LABEL: @test37(
912; CHECK-NEXT:    ret i1 true
913;
914  %t = icmp eq ptr getelementptr ([1 x i8], ptr @A37, i64 0, i64 1),
915  getelementptr ([1 x i8], ptr @A37, i64 1, i64 0)
916  ret i1 %t
917}
918
919; Test index promotion
920define ptr @test38(ptr %I, i32 %n) {
921; CHECK-LABEL: @test38(
922; CHECK-NEXT:    [[TMP1:%.*]] = sext i32 [[N:%.*]] to i64
923; CHECK-NEXT:    [[A:%.*]] = getelementptr i32, ptr [[I:%.*]], i64 [[TMP1]]
924; CHECK-NEXT:    ret ptr [[A]]
925;
926  %A = getelementptr i32, ptr %I, i32 %n
927  ret ptr %A
928}
929
930; Test that we don't duplicate work when the second gep is a "bitcast".
931%pr10322_t = type { ptr }
932declare void @pr10322_f2(ptr)
933declare void @pr10322_f3(ptr)
934define void @pr10322_f1(ptr %foo) {
935; CHECK-LABEL: @pr10322_f1(
936; CHECK-NEXT:  entry:
937; CHECK-NEXT:    [[ARRAYIDX8:%.*]] = getelementptr inbounds i8, ptr [[FOO:%.*]], i64 16
938; CHECK-NEXT:    call void @pr10322_f2(ptr nonnull [[ARRAYIDX8]]) #[[ATTR0]]
939; CHECK-NEXT:    call void @pr10322_f3(ptr nonnull [[ARRAYIDX8]]) #[[ATTR0]]
940; CHECK-NEXT:    ret void
941;
942entry:
943  %arrayidx8 = getelementptr inbounds %pr10322_t, ptr %foo, i64 2
944  call void @pr10322_f2(ptr %arrayidx8) nounwind
945  call void @pr10322_f3(ptr %arrayidx8) nounwind
946  ret void
947
948}
949
950; Test that we combine the last two geps in this sequence, before we
951; would wait for gep1 and gep2 to be combined and never combine 2 and 3.
952%three_gep_t = type {i32}
953%three_gep_t2 = type {%three_gep_t}
954
955define void @three_gep_f(ptr %x) {
956; CHECK-LABEL: @three_gep_f(
957; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr i8, ptr [[X:%.*]], i64 8
958; CHECK-NEXT:    call void @three_gep_h(ptr [[GEP1]])
959; CHECK-NEXT:    call void @three_gep_g(ptr [[GEP1]])
960; CHECK-NEXT:    ret void
961;
962  %gep1 = getelementptr %three_gep_t2, ptr %x, i64 2
963  call void @three_gep_h(ptr %gep1)
964  call void @three_gep_g(ptr %gep1)
965
966  ret void
967}
968
969declare void @three_gep_g(ptr)
970declare void @three_gep_h(ptr)
971
972%struct.ham = type { i32, ptr, ptr, ptr }
973%struct.zot = type { i64, i8 }
974
975define void @test39(ptr %arg, i8 %arg1) nounwind {
976; CHECK-LABEL: @test39(
977; CHECK-NEXT:    [[T:%.*]] = getelementptr inbounds i8, ptr [[ARG:%.*]], i64 16
978; CHECK-NEXT:    [[T2:%.*]] = load ptr, ptr [[T]], align 8
979; CHECK-NEXT:    [[T4:%.*]] = getelementptr inbounds i8, ptr [[T2]], i64 -8
980; CHECK-NEXT:    store i8 [[ARG1:%.*]], ptr [[T4]], align 8
981; CHECK-NEXT:    ret void
982;
983  %t = getelementptr inbounds %struct.ham, ptr %arg, i64 0, i32 2
984  %t2 = load ptr, ptr %t, align 8
985  %t4 = getelementptr inbounds i8, ptr %t2, i64 -8
986  store i8 %arg1, ptr %t4, align 8
987  ret void
988
989}
990
991define i1 @pr16483(ptr %a, ptr %b) {
992; CHECK-LABEL: @pr16483(
993; CHECK-NEXT:    [[CMP:%.*]] = icmp ult ptr [[A:%.*]], [[B:%.*]]
994; CHECK-NEXT:    ret i1 [[CMP]]
995;
996  %cmp = icmp ult ptr %a, %b
997  ret i1 %cmp
998
999}
1000
1001define i8 @test_gep_bitcast_as1(ptr addrspace(1) %arr, i16 %N) {
1002; CHECK-LABEL: @test_gep_bitcast_as1(
1003; CHECK-NEXT:    [[V:%.*]] = shl i16 [[N:%.*]], 2
1004; CHECK-NEXT:    [[T:%.*]] = getelementptr i8, ptr addrspace(1) [[ARR:%.*]], i16 [[V]]
1005; CHECK-NEXT:    [[X:%.*]] = load i8, ptr addrspace(1) [[T]], align 1
1006; CHECK-NEXT:    ret i8 [[X]]
1007;
1008  %V = mul i16 %N, 4
1009  %t = getelementptr i8, ptr addrspace(1) %arr, i16 %V
1010  %x = load i8, ptr addrspace(1) %t
1011  ret i8 %x
1012}
1013
1014; The element size of the array matches the element size of the pointer
1015define i64 @test_gep_bitcast_array_same_size_element(ptr %arr, i64 %N) {
1016; CHECK-LABEL: @test_gep_bitcast_array_same_size_element(
1017; CHECK-NEXT:    [[V:%.*]] = shl i64 [[N:%.*]], 3
1018; CHECK-NEXT:    [[T:%.*]] = getelementptr i64, ptr [[ARR:%.*]], i64 [[V]]
1019; CHECK-NEXT:    [[X:%.*]] = load i64, ptr [[T]], align 4
1020; CHECK-NEXT:    ret i64 [[X]]
1021;
1022  %V = mul i64 %N, 8
1023  %t = getelementptr i64, ptr %arr, i64 %V
1024  %x = load i64, ptr %t
1025  ret i64 %x
1026}
1027
1028; gep should be done in the original address space.
1029define i64 @test_gep_bitcast_array_same_size_element_addrspacecast(ptr %arr, i64 %N) {
1030; CHECK-LABEL: @test_gep_bitcast_array_same_size_element_addrspacecast(
1031; CHECK-NEXT:    [[CAST:%.*]] = addrspacecast ptr [[ARR:%.*]] to ptr addrspace(3)
1032; CHECK-NEXT:    [[V:%.*]] = shl i64 [[N:%.*]], 3
1033; CHECK-NEXT:    [[T:%.*]] = getelementptr i64, ptr addrspace(3) [[CAST]], i64 [[V]]
1034; CHECK-NEXT:    [[X:%.*]] = load i64, ptr addrspace(3) [[T]], align 4
1035; CHECK-NEXT:    ret i64 [[X]]
1036;
1037  %cast = addrspacecast ptr %arr to ptr addrspace(3)
1038  %V = mul i64 %N, 8
1039  %t = getelementptr i64, ptr addrspace(3) %cast, i64 %V
1040  %x = load i64, ptr addrspace(3) %t
1041  ret i64 %x
1042}
1043
1044; The element size of the array is different the element size of the pointer
1045define i8 @test_gep_bitcast_array_different_size_element(ptr %arr, i64 %N) {
1046; CHECK-LABEL: @test_gep_bitcast_array_different_size_element(
1047; CHECK-NEXT:    [[V:%.*]] = shl i64 [[N:%.*]], 3
1048; CHECK-NEXT:    [[T:%.*]] = getelementptr i8, ptr [[ARR:%.*]], i64 [[V]]
1049; CHECK-NEXT:    [[X:%.*]] = load i8, ptr [[T]], align 1
1050; CHECK-NEXT:    ret i8 [[X]]
1051;
1052  %V = mul i64 %N, 8
1053  %t = getelementptr i8, ptr %arr, i64 %V
1054  %x = load i8, ptr %t
1055  ret i8 %x
1056}
1057
1058define i64 @test_gep_bitcast_array_same_size_element_as1(ptr addrspace(1) %arr, i16 %N) {
1059; CHECK-LABEL: @test_gep_bitcast_array_same_size_element_as1(
1060; CHECK-NEXT:    [[V:%.*]] = shl i16 [[N:%.*]], 3
1061; CHECK-NEXT:    [[T:%.*]] = getelementptr i64, ptr addrspace(1) [[ARR:%.*]], i16 [[V]]
1062; CHECK-NEXT:    [[X:%.*]] = load i64, ptr addrspace(1) [[T]], align 4
1063; CHECK-NEXT:    ret i64 [[X]]
1064;
1065  %V = mul i16 %N, 8
1066  %t = getelementptr i64, ptr addrspace(1) %arr, i16 %V
1067  %x = load i64, ptr addrspace(1) %t
1068  ret i64 %x
1069}
1070
1071define i8 @test_gep_bitcast_array_different_size_element_as1(ptr addrspace(1) %arr, i16 %N) {
1072; CHECK-LABEL: @test_gep_bitcast_array_different_size_element_as1(
1073; CHECK-NEXT:    [[V:%.*]] = shl i16 [[N:%.*]], 3
1074; CHECK-NEXT:    [[T:%.*]] = getelementptr i8, ptr addrspace(1) [[ARR:%.*]], i16 [[V]]
1075; CHECK-NEXT:    [[X:%.*]] = load i8, ptr addrspace(1) [[T]], align 1
1076; CHECK-NEXT:    ret i8 [[X]]
1077;
1078  %V = mul i16 %N, 8
1079  %t = getelementptr i8, ptr addrspace(1) %arr, i16 %V
1080  %x = load i8, ptr addrspace(1) %t
1081  ret i8 %x
1082}
1083
1084define i64 @test40() {
1085; CHECK-LABEL: @test40(
1086; CHECK-NEXT:    ret i64 8
1087;
1088  %array = alloca [3 x i32], align 4
1089  %gep = getelementptr inbounds [3 x i32], ptr %array, i64 0, i64 2
1090  %p = ptrtoint ptr %array to i64
1091  %np = sub i64 0, %p
1092  %gep2 = getelementptr i8, ptr %gep, i64 %np
1093  %ret = ptrtoint ptr %gep2 to i64
1094  ret i64 %ret
1095
1096}
1097
1098define i16 @test41(ptr addrspace(1) %array) {
1099; CHECK-LABEL: @test41(
1100; CHECK-NEXT:    ret i16 8
1101;
1102  %gep = getelementptr inbounds [3 x i32], ptr addrspace(1) %array, i16 0, i16 2
1103  %p = ptrtoint ptr addrspace(1) %array to i16
1104  %np = sub i16 0, %p
1105  %gep2 = getelementptr i8, ptr addrspace(1) %gep, i16 %np
1106  %ret = ptrtoint ptr addrspace(1) %gep2 to i16
1107  ret i16 %ret
1108
1109}
1110
1111define ptr @test42i(ptr %c1, ptr %c2) {
1112; CHECK-LABEL: @test42i(
1113; CHECK-NEXT:    [[PTRTOINT:%.*]] = ptrtoint ptr [[C1:%.*]] to i64
1114; CHECK-NEXT:    [[SUB:%.*]] = sub i64 0, [[PTRTOINT]]
1115; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds i8, ptr [[C2:%.*]], i64 [[SUB]]
1116; CHECK-NEXT:    ret ptr [[GEP]]
1117;
1118  %ptrtoint = ptrtoint ptr %c1 to i64
1119  %sub = sub i64 0, %ptrtoint
1120  %gep = getelementptr inbounds i8, ptr %c2, i64 %sub
1121  ret ptr %gep
1122
1123}
1124
1125define ptr @test42(ptr %c1, ptr %c2) {
1126; CHECK-LABEL: @test42(
1127; CHECK-NEXT:    [[PTRTOINT:%.*]] = ptrtoint ptr [[C1:%.*]] to i64
1128; CHECK-NEXT:    [[SUB:%.*]] = sub i64 0, [[PTRTOINT]]
1129; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i8, ptr [[C2:%.*]], i64 [[SUB]]
1130; CHECK-NEXT:    ret ptr [[GEP]]
1131;
1132  %ptrtoint = ptrtoint ptr %c1 to i64
1133  %sub = sub i64 0, %ptrtoint
1134  %gep = getelementptr i8, ptr %c2, i64 %sub
1135  ret ptr %gep
1136
1137}
1138
1139define ptr @test43i(ptr %c1, ptr %c2) {
1140; CHECK-LABEL: @test43i(
1141; CHECK-NEXT:    [[PTRTOINT:%.*]] = ptrtoint ptr [[C1:%.*]] to i64
1142; CHECK-NEXT:    [[SUB:%.*]] = sub i64 0, [[PTRTOINT]]
1143; CHECK-NEXT:    [[SHR:%.*]] = ashr i64 [[SUB]], 1
1144; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds i16, ptr [[C2:%.*]], i64 [[SHR]]
1145; CHECK-NEXT:    ret ptr [[GEP]]
1146;
1147  %ptrtoint = ptrtoint ptr %c1 to i64
1148  %sub = sub i64 0, %ptrtoint
1149  %shr = ashr i64 %sub, 1
1150  %gep = getelementptr inbounds i16, ptr %c2, i64 %shr
1151  ret ptr %gep
1152
1153}
1154
1155define ptr @test44i(ptr %c1, ptr %c2) {
1156; CHECK-LABEL: @test44i(
1157; CHECK-NEXT:    [[PTRTOINT:%.*]] = ptrtoint ptr [[C1:%.*]] to i64
1158; CHECK-NEXT:    [[SUB:%.*]] = sub i64 0, [[PTRTOINT]]
1159; CHECK-NEXT:    [[SHR:%.*]] = sdiv i64 [[SUB]], 7
1160; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds [[STRUCT_C:%.*]], ptr [[C2:%.*]], i64 [[SHR]]
1161; CHECK-NEXT:    ret ptr [[GEP]]
1162;
1163  %ptrtoint = ptrtoint ptr %c1 to i64
1164  %sub = sub i64 0, %ptrtoint
1165  %shr = sdiv i64 %sub, 7
1166  %gep = getelementptr inbounds %struct.C, ptr %c2, i64 %shr
1167  ret ptr %gep
1168
1169}
1170
1171define ptr @test45(ptr %c1, ptr %c2) {
1172; CHECK-LABEL: @test45(
1173; CHECK-NEXT:    [[PTRTOINT1:%.*]] = ptrtoint ptr [[C1:%.*]] to i64
1174; CHECK-NEXT:    [[PTRTOINT2:%.*]] = ptrtoint ptr [[C2:%.*]] to i64
1175; CHECK-NEXT:    [[SUB:%.*]] = sub i64 [[PTRTOINT2]], [[PTRTOINT1]]
1176; CHECK-NEXT:    [[SHR:%.*]] = sdiv i64 [[SUB]], 7
1177; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds [[STRUCT_C:%.*]], ptr [[C1]], i64 [[SHR]]
1178; CHECK-NEXT:    ret ptr [[GEP]]
1179;
1180  %ptrtoint1 = ptrtoint ptr %c1 to i64
1181  %ptrtoint2 = ptrtoint ptr %c2 to i64
1182  %sub = sub i64 %ptrtoint2, %ptrtoint1 ; C2 - C1
1183  %shr = sdiv i64 %sub, 7
1184  %gep = getelementptr inbounds %struct.C, ptr %c1, i64 %shr ; C1 + (C2 - C1)
1185  ret ptr %gep
1186}
1187
1188define ptr @test46(ptr %c1, ptr %c2, i64 %N) {
1189; CHECK-LABEL: @test46(
1190; CHECK-NEXT:    [[PTRTOINT:%.*]] = ptrtoint ptr [[C1:%.*]] to i64
1191; CHECK-NEXT:    [[SUB:%.*]] = sub i64 0, [[PTRTOINT]]
1192; CHECK-NEXT:    [[SDIV:%.*]] = sdiv i64 [[SUB]], [[N:%.*]]
1193; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds [[STRUCT_C:%.*]], ptr [[C2:%.*]], i64 [[SDIV]]
1194; CHECK-NEXT:    ret ptr [[GEP]]
1195;
1196  %ptrtoint = ptrtoint ptr %c1 to i64
1197  %sub = sub i64 0, %ptrtoint
1198  %sdiv = sdiv i64 %sub, %N
1199  %gep = getelementptr inbounds %struct.C, ptr %c2, i64 %sdiv
1200  ret ptr %gep
1201
1202}
1203
1204define ptr @test47(ptr %I, i64 %C, i64 %D) {
1205; CHECK-LABEL: @test47(
1206; CHECK-NEXT:    [[B:%.*]] = getelementptr i32, ptr [[I:%.*]], i64 [[D:%.*]]
1207; CHECK-NEXT:    ret ptr [[B]]
1208;
1209  %sub = sub i64 %D, %C
1210  %A = getelementptr i32, ptr %I, i64 %C
1211  %B = getelementptr i32, ptr %A, i64 %sub
1212  ret ptr %B
1213}
1214
1215define ptr @test48(ptr %I, i64 %C, i64 %D) {
1216; CHECK-LABEL: @test48(
1217; CHECK-NEXT:    [[B:%.*]] = getelementptr i32, ptr [[I:%.*]], i64 [[D:%.*]]
1218; CHECK-NEXT:    ret ptr [[B]]
1219;
1220  %sub = sub i64 %D, %C
1221  %A = getelementptr i32, ptr %I, i64 %sub
1222  %B = getelementptr i32, ptr %A, i64 %C
1223  ret ptr %B
1224}
1225
1226define ptr @test49(ptr %I, i64 %C) {
1227; CHECK-LABEL: @test49(
1228; CHECK-NEXT:    [[B:%.*]] = getelementptr i8, ptr [[I:%.*]], i64 -4
1229; CHECK-NEXT:    ret ptr [[B]]
1230;
1231  %notC = xor i64 -1, %C
1232  %A = getelementptr i32, ptr %I, i64 %C
1233  %B = getelementptr i32, ptr %A, i64 %notC
1234  ret ptr %B
1235}
1236
1237define ptr addrspace(1) @ascast_0_gep(ptr %p) nounwind {
1238; CHECK-LABEL: @ascast_0_gep(
1239; CHECK-NEXT:    [[X:%.*]] = addrspacecast ptr [[P:%.*]] to ptr addrspace(1)
1240; CHECK-NEXT:    ret ptr addrspace(1) [[X]]
1241;
1242  %x = addrspacecast ptr %p to ptr addrspace(1)
1243  ret ptr addrspace(1) %x
1244}
1245
1246; Do not merge the GEP and the addrspacecast, because it would undo the
1247; addrspacecast canonicalization.
1248define ptr addrspace(1) @ascast_0_0_gep(ptr %p) nounwind {
1249; CHECK-LABEL: @ascast_0_0_gep(
1250; CHECK-NEXT:    [[X:%.*]] = addrspacecast ptr [[P:%.*]] to ptr addrspace(1)
1251; CHECK-NEXT:    ret ptr addrspace(1) [[X]]
1252;
1253  %x = addrspacecast ptr %p to ptr addrspace(1)
1254  ret ptr addrspace(1) %x
1255}
1256
1257define <2 x ptr> @PR32414(ptr %ptr) {
1258; CHECK-LABEL: @PR32414(
1259; CHECK-NEXT:    [[T1:%.*]] = getelementptr inbounds i32, ptr [[PTR:%.*]], <2 x i64> <i64 0, i64 1>
1260; CHECK-NEXT:    ret <2 x ptr> [[T1]]
1261;
1262  %t1 = getelementptr inbounds i32, ptr %ptr, <2 x i64> <i64 0, i64 1>
1263  ret <2 x ptr> %t1
1264}
1265
1266define ptr @test_bitcast_nzgep(ptr %base, i64 %idx) {
1267; CHECK-LABEL: @test_bitcast_nzgep(
1268; CHECK-NEXT:    [[PTR:%.*]] = getelementptr inbounds i32, ptr [[BASE:%.*]], i64 [[IDX:%.*]]
1269; CHECK-NEXT:    ret ptr [[PTR]]
1270;
1271  %ptr = getelementptr inbounds i32, ptr %base, i64 %idx
1272  ret ptr %ptr
1273}
1274
1275define ptr @test_zgep_nzgep(ptr %base, i64 %idx) {
1276; CHECK-LABEL: @test_zgep_nzgep(
1277; CHECK-NEXT:    [[PTR:%.*]] = getelementptr inbounds i32, ptr [[BASE:%.*]], i64 [[IDX:%.*]]
1278; CHECK-NEXT:    ret ptr [[PTR]]
1279;
1280  %ptr = getelementptr inbounds i32, ptr %base, i64 %idx
1281  ret ptr %ptr
1282}
1283
1284define ptr @test_nzgep_zgep(ptr %base, i64 %idx) {
1285; CHECK-LABEL: @test_nzgep_zgep(
1286; CHECK-NEXT:    [[BASE2:%.*]] = getelementptr inbounds [1 x i32], ptr [[BASE:%.*]], i64 [[IDX:%.*]]
1287; CHECK-NEXT:    ret ptr [[BASE2]]
1288;
1289  %base2 = getelementptr inbounds [1 x i32], ptr %base, i64 %idx
1290  ret ptr %base2
1291}
1292
1293define ptr @test_gep_inbounds_of_gep(ptr %base) {
1294; CHECK-LABEL: @test_gep_inbounds_of_gep(
1295; CHECK-NEXT:    [[PTR2:%.*]] = getelementptr i8, ptr [[BASE:%.*]], i64 32
1296; CHECK-NEXT:    ret ptr [[PTR2]]
1297;
1298  %ptr1 = getelementptr i32, ptr %base, i64 4
1299  %ptr2 = getelementptr inbounds i32, ptr %ptr1, i64 4
1300  ret ptr %ptr2
1301}
1302
1303%struct.f = type { i32 }
1304
1305@g0 = internal unnamed_addr constant %struct.f zeroinitializer, align 4
1306@g1 = internal unnamed_addr constant %struct.f { i32 -1 }, align 4
1307
1308define ptr @PR45084(i1 %cond) {
1309; CHECK-LABEL: @PR45084(
1310; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND:%.*]], ptr @g0, ptr @g1, !prof [[PROF0:![0-9]+]]
1311; CHECK-NEXT:    ret ptr [[SEL]]
1312;
1313  %sel = select i1 %cond, ptr @g0, ptr @g1, !prof !0
1314  ret ptr %sel
1315}
1316
1317define ptr @PR45084_extra_use(i1 %cond, ptr %p) {
1318; CHECK-LABEL: @PR45084_extra_use(
1319; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND:%.*]], ptr @g0, ptr @g1
1320; CHECK-NEXT:    store ptr [[SEL]], ptr [[P:%.*]], align 8
1321; CHECK-NEXT:    ret ptr [[SEL]]
1322;
1323  %sel = select i1 %cond, ptr @g0, ptr @g1
1324  store ptr %sel, ptr %p
1325  ret ptr %sel
1326}
1327
1328define ptr @gep_null_inbounds(i64 %idx) {
1329; CHECK-LABEL: @gep_null_inbounds(
1330; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds i8, ptr null, i64 [[IDX:%.*]]
1331; CHECK-NEXT:    ret ptr [[GEP]]
1332;
1333  %gep = getelementptr inbounds i8, ptr null, i64 %idx
1334  ret ptr %gep
1335}
1336
1337define ptr @gep_null_not_inbounds(i64 %idx) {
1338; CHECK-LABEL: @gep_null_not_inbounds(
1339; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i8, ptr null, i64 [[IDX:%.*]]
1340; CHECK-NEXT:    ret ptr [[GEP]]
1341;
1342  %gep = getelementptr i8, ptr null, i64 %idx
1343  ret ptr %gep
1344}
1345
1346define ptr @gep_null_defined(i64 %idx) null_pointer_is_valid {
1347; CHECK-LABEL: @gep_null_defined(
1348; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds i8, ptr null, i64 [[IDX:%.*]]
1349; CHECK-NEXT:    ret ptr [[GEP]]
1350;
1351  %gep = getelementptr inbounds i8, ptr null, i64 %idx
1352  ret ptr %gep
1353}
1354
1355define ptr @gep_null_inbounds_different_type(i64 %idx1, i64 %idx2) {
1356; CHECK-LABEL: @gep_null_inbounds_different_type(
1357; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds [0 x i8], ptr null, i64 0, i64 [[IDX2:%.*]]
1358; CHECK-NEXT:    ret ptr [[GEP]]
1359;
1360  %gep = getelementptr inbounds [0 x i8], ptr null, i64 %idx1, i64 %idx2
1361  ret ptr %gep
1362}
1363
1364define ptr @D98588(ptr %c1, i64 %offset) {
1365; CHECK-LABEL: @D98588(
1366; CHECK-NEXT:    [[C2_NEXT_IDX:%.*]] = shl nsw i64 [[OFFSET:%.*]], 3
1367; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds i8, ptr [[C1:%.*]], i64 [[C2_NEXT_IDX]]
1368; CHECK-NEXT:    ret ptr [[GEP]]
1369;
1370  %c2_next = getelementptr inbounds i64, ptr %c1, i64 %offset
1371  %ptrtoint1 = ptrtoint ptr %c1 to i64
1372  %ptrtoint2 = ptrtoint ptr %c2_next to i64
1373  %sub = sub i64 %ptrtoint2, %ptrtoint1 ; C2 - C1
1374  %gep = getelementptr inbounds i8, ptr %c1, i64 %sub ; C1 + (C2 - C1)
1375  ret ptr %gep
1376}
1377
1378declare noalias ptr @malloc(i64) nounwind allockind("alloc,uninitialized") allocsize(0)
1379
1380define i32 @test_gep_bitcast_malloc(ptr %a) {
1381; CHECK-LABEL: @test_gep_bitcast_malloc(
1382; CHECK-NEXT:  entry:
1383; CHECK-NEXT:    [[CALL:%.*]] = call noalias dereferenceable_or_null(16) ptr @malloc(i64 16)
1384; CHECK-NEXT:    [[G3:%.*]] = getelementptr i8, ptr [[CALL]], i64 12
1385; CHECK-NEXT:    [[A_C:%.*]] = load i32, ptr [[G3]], align 4
1386; CHECK-NEXT:    ret i32 [[A_C]]
1387;
1388entry:
1389  %call = call noalias ptr @malloc(i64 16) #2
1390  %g3 = getelementptr %struct.A, ptr %call, i32 0, i32 2
1391  %a_c = load i32, ptr %g3, align 4
1392  ret i32 %a_c
1393}
1394
1395define ptr @gep_of_gep_multiuse_const_and_const(ptr %p, i64 %idx) {
1396; CHECK-LABEL: @gep_of_gep_multiuse_const_and_const(
1397; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 8
1398; CHECK-NEXT:    call void @use(ptr [[GEP1]])
1399; CHECK-NEXT:    [[GEP2:%.*]] = getelementptr i8, ptr [[P]], i64 12
1400; CHECK-NEXT:    ret ptr [[GEP2]]
1401;
1402  %gep1 = getelementptr { i32, i32 }, ptr %p, i64 1
1403  call void @use(ptr %gep1)
1404  %gep2 = getelementptr { i32, i32 }, ptr %gep1, i64 0, i32 1
1405  ret ptr %gep2
1406}
1407
1408define ptr @gep_of_gep_multiuse_var_and_const(ptr %p, i64 %idx) {
1409; CHECK-LABEL: @gep_of_gep_multiuse_var_and_const(
1410; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr { i32, i32 }, ptr [[P:%.*]], i64 [[IDX:%.*]]
1411; CHECK-NEXT:    call void @use(ptr [[GEP1]])
1412; CHECK-NEXT:    [[GEP2:%.*]] = getelementptr i8, ptr [[GEP1]], i64 4
1413; CHECK-NEXT:    ret ptr [[GEP2]]
1414;
1415  %gep1 = getelementptr { i32, i32 }, ptr %p, i64 %idx
1416  call void @use(ptr %gep1)
1417  %gep2 = getelementptr { i32, i32 }, ptr %gep1, i64 0, i32 1
1418  ret ptr %gep2
1419}
1420
1421define ptr @gep_of_gep_multiuse_var_and_var(ptr %p, i64 %idx, i64 %idx2) {
1422; CHECK-LABEL: @gep_of_gep_multiuse_var_and_var(
1423; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr [4 x i32], ptr [[P:%.*]], i64 [[IDX:%.*]]
1424; CHECK-NEXT:    call void @use(ptr [[GEP1]])
1425; CHECK-NEXT:    [[GEP2:%.*]] = getelementptr [4 x i32], ptr [[P]], i64 [[IDX]], i64 [[IDX2:%.*]]
1426; CHECK-NEXT:    ret ptr [[GEP2]]
1427;
1428  %gep1 = getelementptr [4 x i32], ptr %p, i64 %idx
1429  call void @use(ptr %gep1)
1430  %gep2 = getelementptr [4 x i32], ptr %gep1, i64 0, i64 %idx2
1431  ret ptr %gep2
1432}
1433
1434@g_i32_di = global i32 0
1435@g_i32_e = external global i32
1436@g_i32_ew = extern_weak global i32
1437@g_0xi8_e = external global [0 x i8]
1438
1439define ptr @const_gep_global_di_i8_smaller() {
1440; CHECK-LABEL: @const_gep_global_di_i8_smaller(
1441; CHECK-NEXT:    ret ptr getelementptr inbounds (i8, ptr @g_i32_di, i64 3)
1442;
1443  ret ptr getelementptr (i8, ptr @g_i32_di, i64 3)
1444}
1445
1446define ptr @const_gep_global_di_i8_exact() {
1447; CHECK-LABEL: @const_gep_global_di_i8_exact(
1448; CHECK-NEXT:    ret ptr getelementptr inbounds (i8, ptr @g_i32_di, i64 4)
1449;
1450  ret ptr getelementptr (i8, ptr @g_i32_di, i64 4)
1451}
1452
1453define ptr @const_gep_global_di_i8_larger() {
1454; CHECK-LABEL: @const_gep_global_di_i8_larger(
1455; CHECK-NEXT:    ret ptr getelementptr (i8, ptr @g_i32_di, i64 5)
1456;
1457  ret ptr getelementptr (i8, ptr @g_i32_di, i64 5)
1458}
1459
1460define ptr @const_gep_global_di_i64_larger() {
1461; CHECK-LABEL: @const_gep_global_di_i64_larger(
1462; CHECK-NEXT:    ret ptr getelementptr (i8, ptr @g_i32_di, i64 8)
1463;
1464  ret ptr getelementptr (i64, ptr @g_i32_di, i64 1)
1465}
1466
1467define ptr @const_gep_global_e_smaller() {
1468; CHECK-LABEL: @const_gep_global_e_smaller(
1469; CHECK-NEXT:    ret ptr getelementptr inbounds (i8, ptr @g_i32_e, i64 3)
1470;
1471  ret ptr getelementptr (i8, ptr @g_i32_e, i64 3)
1472}
1473
1474define ptr @const_gep_global_e_exact() {
1475; CHECK-LABEL: @const_gep_global_e_exact(
1476; CHECK-NEXT:    ret ptr getelementptr inbounds (i8, ptr @g_i32_e, i64 4)
1477;
1478  ret ptr getelementptr (i8, ptr @g_i32_e, i64 4)
1479}
1480
1481define ptr @const_gep_global_e_larger() {
1482; CHECK-LABEL: @const_gep_global_e_larger(
1483; CHECK-NEXT:    ret ptr getelementptr (i8, ptr @g_i32_e, i64 5)
1484;
1485  ret ptr getelementptr (i8, ptr @g_i32_e, i64 5)
1486}
1487
1488define ptr @const_gep_global_ew_smaller() {
1489; CHECK-LABEL: @const_gep_global_ew_smaller(
1490; CHECK-NEXT:    ret ptr getelementptr (i8, ptr @g_i32_ew, i64 3)
1491;
1492  ret ptr getelementptr (i8, ptr @g_i32_ew, i64 3)
1493}
1494
1495define ptr @const_gep_global_ew_exact() {
1496; CHECK-LABEL: @const_gep_global_ew_exact(
1497; CHECK-NEXT:    ret ptr getelementptr (i8, ptr @g_i32_ew, i64 4)
1498;
1499  ret ptr getelementptr (i8, ptr @g_i32_ew, i64 4)
1500}
1501
1502define ptr @const_gep_global_ew_larger() {
1503; CHECK-LABEL: @const_gep_global_ew_larger(
1504; CHECK-NEXT:    ret ptr getelementptr (i8, ptr @g_i32_ew, i64 5)
1505;
1506  ret ptr getelementptr (i8, ptr @g_i32_ew, i64 5)
1507}
1508
1509define ptr @const_gep_0xi8_global() {
1510; CHECK-LABEL: @const_gep_0xi8_global(
1511; CHECK-NEXT:    ret ptr getelementptr (i8, ptr @g_0xi8_e, i64 10)
1512;
1513  ret ptr getelementptr ([0 x i8], ptr @g_0xi8_e, i64 0, i64 10)
1514}
1515
1516define ptr @const_gep_chain(ptr %p, i64 %a) {
1517; CHECK-LABEL: @const_gep_chain(
1518; CHECK-NEXT:    [[P1:%.*]] = getelementptr inbounds i8, ptr [[P:%.*]], i64 [[A:%.*]]
1519; CHECK-NEXT:    [[P4:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 6
1520; CHECK-NEXT:    ret ptr [[P4]]
1521;
1522  %p1 = getelementptr inbounds i8, ptr %p, i64 %a
1523  %p2 = getelementptr inbounds i8, ptr %p1, i64 1
1524  %p3 = getelementptr inbounds i8, ptr %p2, i64 2
1525  %p4 = getelementptr inbounds i8, ptr %p3, i64 3
1526  ret ptr %p4
1527}
1528
1529define ptr @gep_sdiv(ptr %p, i64 %off) {
1530; CHECK-LABEL: @gep_sdiv(
1531; CHECK-NEXT:    [[PTR:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[OFF:%.*]]
1532; CHECK-NEXT:    ret ptr [[PTR]]
1533;
1534  %index = sdiv exact i64 %off, 7
1535  %ptr = getelementptr %struct.C, ptr %p, i64 %index
1536  ret ptr %ptr
1537}
1538
1539define ptr @gep_udiv(ptr %p, i64 %off) {
1540; CHECK-LABEL: @gep_udiv(
1541; CHECK-NEXT:    [[PTR:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[OFF:%.*]]
1542; CHECK-NEXT:    ret ptr [[PTR]]
1543;
1544  %index = udiv exact i64 %off, 7
1545  %ptr = getelementptr %struct.C, ptr %p, i64 %index
1546  ret ptr %ptr
1547}
1548
1549define <2 x ptr> @gep_sdiv_vec(<2 x ptr> %p, <2 x i64> %off) {
1550; CHECK-LABEL: @gep_sdiv_vec(
1551; CHECK-NEXT:    [[PTR:%.*]] = getelementptr i8, <2 x ptr> [[P:%.*]], <2 x i64> [[OFF:%.*]]
1552; CHECK-NEXT:    ret <2 x ptr> [[PTR]]
1553;
1554  %index = sdiv exact <2 x i64> %off, <i64 7, i64 7>
1555  %ptr = getelementptr %struct.C, <2 x ptr> %p, <2 x i64> %index
1556  ret <2 x ptr> %ptr
1557}
1558
1559define ptr @gep_sdiv_inbounds(ptr %p, i64 %off) {
1560; CHECK-LABEL: @gep_sdiv_inbounds(
1561; CHECK-NEXT:    [[PTR:%.*]] = getelementptr inbounds i8, ptr [[P:%.*]], i64 [[OFF:%.*]]
1562; CHECK-NEXT:    ret ptr [[PTR]]
1563;
1564  %index = sdiv exact i64 %off, 7
1565  %ptr = getelementptr inbounds %struct.C, ptr %p, i64 %index
1566  ret ptr %ptr
1567}
1568
1569define ptr @gep_ashr(ptr %p, i64 %off) {
1570; CHECK-LABEL: @gep_ashr(
1571; CHECK-NEXT:    [[PTR:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[OFF:%.*]]
1572; CHECK-NEXT:    ret ptr [[PTR]]
1573;
1574  %index = ashr exact i64 %off, 2
1575  %ptr = getelementptr i32, ptr %p, i64 %index
1576  ret ptr %ptr
1577}
1578
1579define ptr @gep_lshr(ptr %p, i64 %off) {
1580; CHECK-LABEL: @gep_lshr(
1581; CHECK-NEXT:    [[PTR:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[OFF:%.*]]
1582; CHECK-NEXT:    ret ptr [[PTR]]
1583;
1584  %index = lshr exact i64 %off, 2
1585  %ptr = getelementptr i32, ptr %p, i64 %index
1586  ret ptr %ptr
1587}
1588
1589; Negative tests
1590
1591define ptr @gep_i8(ptr %p, i64 %off) {
1592; CHECK-LABEL: @gep_i8(
1593; CHECK-NEXT:    [[PTR:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[OFF:%.*]]
1594; CHECK-NEXT:    ret ptr [[PTR]]
1595;
1596  %ptr = getelementptr i8, ptr %p, i64 %off
1597  ret ptr %ptr
1598}
1599
1600define ptr @gep_sdiv_mismatched_size(ptr %p, i64 %off) {
1601; CHECK-LABEL: @gep_sdiv_mismatched_size(
1602; CHECK-NEXT:    [[INDEX:%.*]] = sdiv exact i64 [[OFF:%.*]], 20
1603; CHECK-NEXT:    [[PTR:%.*]] = getelementptr [[STRUCT_C:%.*]], ptr [[P:%.*]], i64 [[INDEX]]
1604; CHECK-NEXT:    ret ptr [[PTR]]
1605;
1606  %index = sdiv exact i64 %off, 20
1607  %ptr = getelementptr %struct.C, ptr %p, i64 %index
1608  ret ptr %ptr
1609}
1610
1611define ptr @gep_udiv_mismatched_size(ptr %p, i64 %off) {
1612; CHECK-LABEL: @gep_udiv_mismatched_size(
1613; CHECK-NEXT:    [[INDEX:%.*]] = udiv exact i64 [[OFF:%.*]], 20
1614; CHECK-NEXT:    [[PTR:%.*]] = getelementptr [[STRUCT_C:%.*]], ptr [[P:%.*]], i64 [[INDEX]]
1615; CHECK-NEXT:    ret ptr [[PTR]]
1616;
1617  %index = udiv exact i64 %off, 20
1618  %ptr = getelementptr %struct.C, ptr %p, i64 %index
1619  ret ptr %ptr
1620}
1621
1622define ptr @gep_sdiv_without_exact(ptr %p, i64 %off) {
1623; CHECK-LABEL: @gep_sdiv_without_exact(
1624; CHECK-NEXT:    [[INDEX:%.*]] = sdiv i64 [[OFF:%.*]], 7
1625; CHECK-NEXT:    [[PTR:%.*]] = getelementptr [[STRUCT_C:%.*]], ptr [[P:%.*]], i64 [[INDEX]]
1626; CHECK-NEXT:    ret ptr [[PTR]]
1627;
1628  %index = sdiv i64 %off, 7
1629  %ptr = getelementptr %struct.C, ptr %p, i64 %index
1630  ret ptr %ptr
1631}
1632
1633define ptr @gep_udiv_without_exact(ptr %p, i64 %off) {
1634; CHECK-LABEL: @gep_udiv_without_exact(
1635; CHECK-NEXT:    [[INDEX:%.*]] = udiv i64 [[OFF:%.*]], 7
1636; CHECK-NEXT:    [[PTR:%.*]] = getelementptr [[STRUCT_C:%.*]], ptr [[P:%.*]], i64 [[INDEX]]
1637; CHECK-NEXT:    ret ptr [[PTR]]
1638;
1639  %index = udiv i64 %off, 7
1640  %ptr = getelementptr %struct.C, ptr %p, i64 %index
1641  ret ptr %ptr
1642}
1643
1644define ptr @gep_ashr_without_exact(ptr %p, i64 %off) {
1645; CHECK-LABEL: @gep_ashr_without_exact(
1646; CHECK-NEXT:    [[INDEX:%.*]] = ashr i64 [[OFF:%.*]], 2
1647; CHECK-NEXT:    [[PTR:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[INDEX]]
1648; CHECK-NEXT:    ret ptr [[PTR]]
1649;
1650  %index = ashr i64 %off, 2
1651  %ptr = getelementptr i32, ptr %p, i64 %index
1652  ret ptr %ptr
1653}
1654
1655define ptr @gep_lshr_without_exact(ptr %p, i64 %off) {
1656; CHECK-LABEL: @gep_lshr_without_exact(
1657; CHECK-NEXT:    [[INDEX:%.*]] = lshr i64 [[OFF:%.*]], 2
1658; CHECK-NEXT:    [[PTR:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[INDEX]]
1659; CHECK-NEXT:    ret ptr [[PTR]]
1660;
1661  %index = lshr i64 %off, 2
1662  %ptr = getelementptr i32, ptr %p, i64 %index
1663  ret ptr %ptr
1664}
1665
1666define i1 @test_only_used_by_icmp(ptr %a, ptr %b, ptr %c) {
1667; CHECK-LABEL: @test_only_used_by_icmp(
1668; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[B:%.*]], [[C:%.*]]
1669; CHECK-NEXT:    ret i1 [[CMP]]
1670;
1671  %pa = ptrtoint ptr %a to i64
1672  %pb = ptrtoint ptr %b to i64
1673  %sub = sub i64 %pb, %pa
1674  %gep = getelementptr i8, ptr %a, i64 %sub
1675  %cmp = icmp eq ptr %gep, %c
1676  ret i1 %cmp
1677}
1678
1679define i64 @test_only_used_by_ptrtoint(ptr %a, ptr %b) {
1680; CHECK-LABEL: @test_only_used_by_ptrtoint(
1681; CHECK-NEXT:    [[VAL:%.*]] = ptrtoint ptr [[B:%.*]] to i64
1682; CHECK-NEXT:    ret i64 [[VAL]]
1683;
1684  %pa = ptrtoint ptr %a to i64
1685  %pb = ptrtoint ptr %b to i64
1686  %sub = sub i64 %pb, %pa
1687  %gep = getelementptr i8, ptr %a, i64 %sub
1688  %val = ptrtoint ptr %gep to i64
1689  ret i64 %val
1690}
1691
1692define i64 @test_used_by_both(ptr %a, ptr %b, ptr %c) {
1693; CHECK-LABEL: @test_used_by_both(
1694; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[B:%.*]], [[C:%.*]]
1695; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
1696; CHECK:       if.then:
1697; CHECK-NEXT:    [[VAL:%.*]] = ptrtoint ptr [[B]] to i64
1698; CHECK-NEXT:    ret i64 [[VAL]]
1699; CHECK:       if.else:
1700; CHECK-NEXT:    ret i64 0
1701;
1702  %pa = ptrtoint ptr %a to i64
1703  %pb = ptrtoint ptr %b to i64
1704  %sub = sub i64 %pb, %pa
1705  %gep = getelementptr i8, ptr %a, i64 %sub
1706  %cmp = icmp eq ptr %gep, %c
1707  br i1 %cmp, label %if.then, label %if.else
1708if.then:
1709  %val = ptrtoint ptr %gep to i64
1710  ret i64 %val
1711if.else:
1712  ret i64 0
1713}
1714
1715; Negative tests
1716
1717define i64 @test_used_by_both_invalid(ptr %a, ptr %b, ptr %c) {
1718; CHECK-LABEL: @test_used_by_both_invalid(
1719; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[B:%.*]], [[C:%.*]]
1720; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
1721; CHECK:       if.then:
1722; CHECK-NEXT:    [[PB:%.*]] = ptrtoint ptr [[B]] to i64
1723; CHECK-NEXT:    [[PA:%.*]] = ptrtoint ptr [[A:%.*]] to i64
1724; CHECK-NEXT:    [[SUB:%.*]] = sub i64 [[PB]], [[PA]]
1725; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i8, ptr [[A]], i64 [[SUB]]
1726; CHECK-NEXT:    [[VAL:%.*]] = load i64, ptr [[GEP]], align 8
1727; CHECK-NEXT:    ret i64 [[VAL]]
1728; CHECK:       if.else:
1729; CHECK-NEXT:    ret i64 0
1730;
1731  %pa = ptrtoint ptr %a to i64
1732  %pb = ptrtoint ptr %b to i64
1733  %sub = sub i64 %pb, %pa
1734  %gep = getelementptr i8, ptr %a, i64 %sub
1735  %cmp = icmp eq ptr %gep, %c
1736  br i1 %cmp, label %if.then, label %if.else
1737if.then:
1738  %val = load i64, ptr %gep, align 8
1739  ret i64 %val
1740if.else:
1741  ret i64 0
1742}
1743
1744
1745@g = external global i8
1746
1747define ptr @constexpr_gep_of_gep_with_narrow_type() {
1748; CHECK-LABEL: @constexpr_gep_of_gep_with_narrow_type(
1749; CHECK-NEXT:    ret ptr getelementptr (i8, ptr @g, i64 254)
1750;
1751  ret ptr getelementptr (i8, ptr getelementptr (i8, ptr @g, i8 127), i8 127)
1752}
1753
1754define ptr @gep_to_i8_nusw_nuw(ptr %p) {
1755; CHECK-LABEL: @gep_to_i8_nusw_nuw(
1756; CHECK-NEXT:    [[GEP:%.*]] = getelementptr nusw nuw i8, ptr [[P:%.*]], i64 4
1757; CHECK-NEXT:    ret ptr [[GEP]]
1758;
1759  %gep = getelementptr nusw nuw i32, ptr %p, i64 1
1760  ret ptr %gep
1761}
1762
1763!0 = !{!"branch_weights", i32 2, i32 10}
1764