Re-land [openmp] Fix warnings when building on Windows with latest MSVC or Clang...
[llvm-project.git] / llvm / test / Transforms / InstCombine / getelementptr.ll
blob642c3eb2a0e41b53e7e7bdc85c861a1f66c04dff
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=instcombine -S | FileCheck %s
4 target datalayout = "e-p:64:64-p1:16:16-p2:32:32:32-p3:64:64:64-f16:32"
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] }
13 @Global = external global [10 x i8]
14 @Global_as1 = external addrspace(1) global [10 x i8]
16 declare void @use(ptr)
18 ; Test noop elimination
19 define ptr @test1(ptr %I) {
20 ; CHECK-LABEL: @test1(
21 ; CHECK-NEXT:    ret ptr [[I:%.*]]
23   ret ptr %I
26 define ptr addrspace(1) @test1_as1(ptr addrspace(1) %I) {
27 ; CHECK-LABEL: @test1_as1(
28 ; CHECK-NEXT:    ret ptr addrspace(1) [[I:%.*]]
30   ret ptr addrspace(1) %I
33 ; Test noop elimination
34 define ptr @test2(ptr %I) {
35 ; CHECK-LABEL: @test2(
36 ; CHECK-NEXT:    ret ptr [[I:%.*]]
38   %A = getelementptr i32, ptr %I
39   ret ptr %A
42 ; Test that two array indexing geps fold
43 define ptr @test3(ptr %I) {
44 ; CHECK-LABEL: @test3(
45 ; CHECK-NEXT:    [[B:%.*]] = getelementptr i32, ptr [[I:%.*]], i64 21
46 ; CHECK-NEXT:    ret ptr [[B]]
48   %A = getelementptr i32, ptr %I, i64 17
49   %B = getelementptr i32, ptr %A, i64 4
50   ret ptr %B
53 ; Test that two getelementptr insts fold
54 define ptr @test4(ptr %I) {
55 ; CHECK-LABEL: @test4(
56 ; CHECK-NEXT:    [[A:%.*]] = getelementptr { i32 }, ptr [[I:%.*]], i64 1
57 ; CHECK-NEXT:    ret ptr [[A]]
59   %A = getelementptr { i32 }, ptr %I, i64 1
60   ret ptr %A
63 define 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 ([10 x i8], ptr @Global, i64 0, i64 4), align 1
67 ; CHECK-NEXT:    ret void
69   %A = getelementptr [10 x i8], ptr @Global, i64 0, i64 4
70   store i8 %B, ptr %A
71   ret void
74 define 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 ([10 x i8], ptr addrspace(1) @Global_as1, i16 0, i16 4), align 1
78 ; CHECK-NEXT:    ret void
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
85 %as1_ptr_struct = type { ptr addrspace(1) }
86 %as2_ptr_struct = type { ptr addrspace(2) }
88 @global_as2 = addrspace(2) global i32 zeroinitializer
89 @global_as1_as2_ptr = addrspace(1) global %as2_ptr_struct { ptr addrspace(2) @global_as2 }
91 ; This should be turned into a constexpr instead of being an instruction
92 define 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
97   store ptr addrspace(2) %B, ptr addrspace(1) @global_as1_as2_ptr
98   ret void
101 @arst = addrspace(1) global [4 x ptr addrspace(2)] zeroinitializer
103 define 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 ([4 x ptr addrspace(2)], ptr addrspace(1) @arst, i16 0, i16 2), align 4
106 ; CHECK-NEXT:    ret void
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
114 ; This should be turned into a constexpr instead of being an instruction
115 define void @test_overaligned_vec(i8 %B) {
116 ; CHECK-LABEL: @test_overaligned_vec(
117 ; CHECK-NEXT:    store i8 [[B:%.*]], ptr getelementptr inbounds ([10 x i8], ptr @Global, i64 0, i64 2), align 1
118 ; CHECK-NEXT:    ret void
119   %A = getelementptr <2 x half>, ptr @Global, i64 0, i64 1
120   store i8 %B, ptr %A
121   ret void
124 define ptr @test7(ptr %I, i64 %C, i64 %D) {
125 ; CHECK-LABEL: @test7(
126 ; CHECK-NEXT:    [[A:%.*]] = getelementptr i32, ptr [[I:%.*]], i64 [[C:%.*]]
127 ; CHECK-NEXT:    [[B:%.*]] = getelementptr i32, ptr [[A]], i64 [[D:%.*]]
128 ; CHECK-NEXT:    ret ptr [[B]]
130   %A = getelementptr i32, ptr %I, i64 %C
131   %B = getelementptr i32, ptr %A, i64 %D
132   ret ptr %B
135 define ptr @test8(ptr %X) {
136         ;; Fold into the cast.
137 ; CHECK-LABEL: @test8(
138 ; CHECK-NEXT:    ret ptr [[X:%.*]]
140   ret ptr %X
143 define i32 @test9() {
144 ; CHECK-LABEL: @test9(
145 ; CHECK-NEXT:    ret i32 8
147   %A = getelementptr { i32, double }, ptr null, i32 0, i32 1
148   %B = ptrtoint ptr %A to i32
149   ret i32 %B
152 define i1 @test10(ptr %x, ptr %y) {
153 ; CHECK-LABEL: @test10(
154 ; CHECK-NEXT:    [[T4:%.*]] = icmp eq ptr [[X:%.*]], [[Y:%.*]]
155 ; CHECK-NEXT:    ret i1 [[T4]]
157   %t1 = getelementptr { i32, i32 }, ptr %x, i32 0, i32 1
158   %t3 = getelementptr { i32, i32 }, ptr %y, i32 0, i32 1
159   %t4 = icmp eq ptr %t1, %t3
160   ret i1 %t4
163 define i1 @test10_addrspacecast(ptr %x, ptr addrspace(3) %y) {
164 ; CHECK-LABEL: @test10_addrspacecast(
165 ; CHECK-NEXT:    [[T1:%.*]] = getelementptr { i32, i32 }, ptr [[X:%.*]], i64 0, i32 1
166 ; CHECK-NEXT:    [[T3:%.*]] = getelementptr { i32, i32 }, ptr addrspace(3) [[Y:%.*]], i64 0, i32 1
167 ; CHECK-NEXT:    [[T3_C:%.*]] = addrspacecast ptr addrspace(3) [[T3]] to ptr
168 ; CHECK-NEXT:    [[T4:%.*]] = icmp eq ptr [[T1]], [[T3_C]]
169 ; CHECK-NEXT:    ret i1 [[T4]]
171   %t1 = getelementptr { i32, i32 }, ptr %x, i32 0, i32 1
172   %t3 = getelementptr { i32, i32 }, ptr addrspace(3) %y, i32 0, i32 1
173   %t3.c = addrspacecast ptr addrspace(3) %t3 to ptr
174   %t4 = icmp eq ptr %t1, %t3.c
175   ret i1 %t4
178 define i1 @test11(ptr %X) {
179 ; CHECK-LABEL: @test11(
180 ; CHECK-NEXT:    [[Q:%.*]] = icmp eq ptr [[X:%.*]], null
181 ; CHECK-NEXT:    ret i1 [[Q]]
183   %P = getelementptr { i32, i32 }, ptr %X, i32 0, i32 0
184   %Q = icmp eq ptr %P, null
185   ret i1 %Q
189 ; PR4748
190 define i32 @test12(ptr %a) {
191 ; CHECK-LABEL: @test12(
192 ; CHECK-NEXT:  entry:
193 ; CHECK-NEXT:    [[G3:%.*]] = getelementptr [[STRUCT_A:%.*]], ptr [[A:%.*]], i64 0, i32 1
194 ; CHECK-NEXT:    store i32 10, ptr [[G3]], align 4
195 ; CHECK-NEXT:    ret i32 10
197 entry:
198   %g3 = getelementptr %struct.A, ptr %a, i32 0, i32 1
199   store i32 10, ptr %g3, align 4
203   %g5 = getelementptr %struct.A, ptr %a, i32 0, i32 1
204   %a_a = load i32, ptr %g5, align 4
205   ret i32 %a_a
209 ; PR2235
210 %S = type { i32, [ 100 x i32] }
211 define i1 @test13(i64 %X, ptr %P) {
212 ; CHECK-LABEL: @test13(
213 ; CHECK-NEXT:    [[C:%.*]] = icmp eq i64 [[X:%.*]], -1
214 ; CHECK-NEXT:    ret i1 [[C]]
216   %A = getelementptr inbounds %S, ptr %P, i32 0, i32 1, i64 %X
217   %C = icmp eq ptr %A, %P
218   ret i1 %C
221 define <2 x i1> @test13_vector(<2 x i64> %X, <2 x ptr> %P) nounwind {
222 ; CHECK-LABEL: @test13_vector(
223 ; CHECK-NEXT:    [[C:%.*]] = icmp eq <2 x i64> [[X:%.*]], <i64 -1, i64 -1>
224 ; CHECK-NEXT:    ret <2 x i1> [[C]]
226   %A = getelementptr inbounds %S, <2 x ptr> %P, <2 x i64> zeroinitializer, <2 x i32> <i32 1, i32 1>, <2 x i64> %X
227   %B = getelementptr inbounds %S, <2 x ptr> %P, <2 x i64> <i64 0, i64 0>, <2 x i32> <i32 0, i32 0>
228   %C = icmp eq <2 x ptr> %A, %B
229   ret <2 x i1> %C
232 define <2 x i1> @test13_vector2(i64 %X, <2 x ptr> %P) nounwind {
233 ; CHECK-LABEL: @test13_vector2(
234 ; CHECK-NEXT:    [[DOTSPLATINSERT:%.*]] = insertelement <2 x i64> poison, i64 [[X:%.*]], i64 0
235 ; CHECK-NEXT:    [[TMP1:%.*]] = shl <2 x i64> [[DOTSPLATINSERT]], <i64 2, i64 0>
236 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq <2 x i64> [[TMP1]], <i64 -4, i64 poison>
237 ; CHECK-NEXT:    [[C:%.*]] = shufflevector <2 x i1> [[TMP2]], <2 x i1> poison, <2 x i32> zeroinitializer
238 ; CHECK-NEXT:    ret <2 x i1> [[C]]
240   %A = getelementptr inbounds %S, <2 x ptr> %P, <2 x i64> zeroinitializer, <2 x i32> <i32 1, i32 1>, i64 %X
241   %B = getelementptr inbounds %S, <2 x ptr> %P, <2 x i64> <i64 0, i64 0>, <2 x i32> <i32 0, i32 0>
242   %C = icmp eq <2 x ptr> %A, %B
243   ret <2 x i1> %C
246 define <2 x i1> @test13_fixed_fixed(i64 %X, ptr %P, <2 x i64> %y) nounwind {
247 ; CHECK-LABEL: @test13_fixed_fixed(
248 ; CHECK-NEXT:    [[DOTSPLATINSERT:%.*]] = insertelement <2 x i64> poison, i64 [[X:%.*]], i64 0
249 ; CHECK-NEXT:    [[TMP1:%.*]] = shl <2 x i64> [[DOTSPLATINSERT]], <i64 3, i64 0>
250 ; CHECK-NEXT:    [[A_IDX:%.*]] = shufflevector <2 x i64> [[TMP1]], <2 x i64> poison, <2 x i32> zeroinitializer
251 ; CHECK-NEXT:    [[B_IDX:%.*]] = shl nsw <2 x i64> [[Y:%.*]], <i64 4, i64 4>
252 ; CHECK-NEXT:    [[C:%.*]] = icmp eq <2 x i64> [[A_IDX]], [[B_IDX]]
253 ; CHECK-NEXT:    ret <2 x i1> [[C]]
255   %A = getelementptr inbounds <2 x i64>, ptr %P, <2 x i64> zeroinitializer, i64 %X
256   %B = getelementptr inbounds <2 x i64>, ptr %P, <2 x i64> %y
257   %C = icmp eq <2 x ptr> %A, %B
258   ret <2 x i1> %C
261 define <2 x i1> @test13_fixed_scalable(i64 %X, ptr %P, <2 x i64> %y) nounwind {
262 ; CHECK-LABEL: @test13_fixed_scalable(
263 ; CHECK-NEXT:    [[DOTSPLATINSERT:%.*]] = insertelement <2 x i64> poison, i64 [[X:%.*]], i64 0
264 ; CHECK-NEXT:    [[TMP1:%.*]] = shl <2 x i64> [[DOTSPLATINSERT]], <i64 3, i64 0>
265 ; CHECK-NEXT:    [[A_IDX:%.*]] = shufflevector <2 x i64> [[TMP1]], <2 x i64> poison, <2 x i32> zeroinitializer
266 ; CHECK-NEXT:    [[TMP2:%.*]] = call i64 @llvm.vscale.i64()
267 ; CHECK-NEXT:    [[TMP3:%.*]] = shl i64 [[TMP2]], 4
268 ; CHECK-NEXT:    [[DOTSPLATINSERT1:%.*]] = insertelement <2 x i64> poison, i64 [[TMP3]], i64 0
269 ; CHECK-NEXT:    [[DOTSPLAT2:%.*]] = shufflevector <2 x i64> [[DOTSPLATINSERT1]], <2 x i64> poison, <2 x i32> zeroinitializer
270 ; CHECK-NEXT:    [[B_IDX:%.*]] = mul nsw <2 x i64> [[DOTSPLAT2]], [[Y:%.*]]
271 ; CHECK-NEXT:    [[C:%.*]] = icmp eq <2 x i64> [[A_IDX]], [[B_IDX]]
272 ; CHECK-NEXT:    ret <2 x i1> [[C]]
274   %A = getelementptr inbounds <vscale x 2 x i64>, ptr %P, <2 x i64> zeroinitializer, i64 %X
275   %B = getelementptr inbounds <vscale x 2 x i64>, ptr %P, <2 x i64> %y
276   %C = icmp eq <2 x ptr> %A, %B
277   ret <2 x i1> %C
280 define <vscale x 2 x i1> @test13_scalable_scalable(i64 %X, ptr %P, <vscale x 2 x i64> %y) nounwind {
281 ; CHECK-LABEL: @test13_scalable_scalable(
282 ; CHECK-NEXT:    [[DOTSPLATINSERT:%.*]] = insertelement <vscale x 2 x i64> poison, i64 [[X:%.*]], i64 0
283 ; CHECK-NEXT:    [[DOTSPLAT:%.*]] = shufflevector <vscale x 2 x i64> [[DOTSPLATINSERT]], <vscale x 2 x i64> poison, <vscale x 2 x i32> zeroinitializer
284 ; 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)
285 ; CHECK-NEXT:    [[TMP1:%.*]] = call i64 @llvm.vscale.i64()
286 ; CHECK-NEXT:    [[TMP2:%.*]] = shl i64 [[TMP1]], 4
287 ; CHECK-NEXT:    [[DOTSPLATINSERT1:%.*]] = insertelement <vscale x 2 x i64> poison, i64 [[TMP2]], i64 0
288 ; CHECK-NEXT:    [[DOTSPLAT2:%.*]] = shufflevector <vscale x 2 x i64> [[DOTSPLATINSERT1]], <vscale x 2 x i64> poison, <vscale x 2 x i32> zeroinitializer
289 ; CHECK-NEXT:    [[B_IDX:%.*]] = mul nsw <vscale x 2 x i64> [[DOTSPLAT2]], [[Y:%.*]]
290 ; CHECK-NEXT:    [[C:%.*]] = icmp eq <vscale x 2 x i64> [[A_IDX]], [[B_IDX]]
291 ; CHECK-NEXT:    ret <vscale x 2 x i1> [[C]]
293   %A = getelementptr inbounds <vscale x 2 x i64>, ptr %P, <vscale x 2 x i64> zeroinitializer, i64 %X
294   %B = getelementptr inbounds <vscale x 2 x i64>, ptr %P, <vscale x 2 x i64> %y
295   %C = icmp eq <vscale x 2 x ptr> %A, %B
296   ret <vscale x 2 x i1> %C
299 ; This is a test of icmp + shl nuw in disguise - 4611... is 0x3fff...
300 define <2 x i1> @test13_vector3(i64 %X, <2 x ptr> %P) nounwind {
301 ; CHECK-LABEL: @test13_vector3(
302 ; CHECK-NEXT:    [[DOTSPLATINSERT:%.*]] = insertelement <2 x i64> poison, i64 [[X:%.*]], i64 0
303 ; CHECK-NEXT:    [[TMP1:%.*]] = shl <2 x i64> [[DOTSPLATINSERT]], <i64 2, i64 0>
304 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq <2 x i64> [[TMP1]], <i64 4, i64 poison>
305 ; CHECK-NEXT:    [[C:%.*]] = shufflevector <2 x i1> [[TMP2]], <2 x i1> poison, <2 x i32> zeroinitializer
306 ; CHECK-NEXT:    ret <2 x i1> [[C]]
308   %A = getelementptr inbounds %S, <2 x ptr> %P, <2 x i64> zeroinitializer, <2 x i32> <i32 1, i32 1>, i64 %X
309   %B = getelementptr inbounds %S, <2 x ptr> %P, <2 x i64> <i64 0, i64 0>, <2 x i32> <i32 1, i32 1>, i64 1
310   %C = icmp eq <2 x ptr> %A, %B
311   ret <2 x i1> %C
314 define i1 @test13_as1(i16 %X, ptr addrspace(1) %P) {
315 ; CHECK-LABEL: @test13_as1(
316 ; CHECK-NEXT:    [[C:%.*]] = icmp eq i16 [[X:%.*]], -1
317 ; CHECK-NEXT:    ret i1 [[C]]
319   %A = getelementptr inbounds %S, ptr addrspace(1) %P, i16 0, i32 1, i16 %X
320   %C = icmp eq ptr addrspace(1) %A, %P
321   ret i1 %C
324 define <2 x i1> @test13_vector_as1(<2 x i16> %X, <2 x ptr addrspace(1)> %P) {
325 ; CHECK-LABEL: @test13_vector_as1(
326 ; CHECK-NEXT:    [[C:%.*]] = icmp eq <2 x i16> [[X:%.*]], <i16 -1, i16 -1>
327 ; CHECK-NEXT:    ret <2 x i1> [[C]]
329   %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
330   %B = getelementptr inbounds %S, <2 x ptr addrspace(1)> %P, <2 x i16> <i16 0, i16 0>, <2 x i32> <i32 0, i32 0>
331   %C = icmp eq <2 x ptr addrspace(1)> %A, %B
332   ret <2 x i1> %C
335 define i1 @test13_i32(i32 %X, ptr %P) {
336 ; CHECK-LABEL: @test13_i32(
337 ; CHECK-NEXT:    [[C:%.*]] = icmp eq i32 [[X:%.*]], -1
338 ; CHECK-NEXT:    ret i1 [[C]]
340   %A = getelementptr inbounds %S, ptr %P, i32 0, i32 1, i32 %X
341   %C = icmp eq ptr %A, %P
342   ret i1 %C
345 define i1 @test13_i16(i16 %X, ptr %P) {
346 ; CHECK-LABEL: @test13_i16(
347 ; CHECK-NEXT:    [[C:%.*]] = icmp eq i16 [[X:%.*]], -1
348 ; CHECK-NEXT:    ret i1 [[C]]
350   %A = getelementptr inbounds %S, ptr %P, i16 0, i32 1, i16 %X
351   %C = icmp eq ptr %A, %P
352   ret i1 %C
355 define i1 @test13_i128(i128 %X, ptr %P) {
356 ; CHECK-LABEL: @test13_i128(
357 ; CHECK-NEXT:    [[TMP1:%.*]] = trunc i128 [[X:%.*]] to i64
358 ; CHECK-NEXT:    [[C:%.*]] = icmp eq i64 [[TMP1]], -1
359 ; CHECK-NEXT:    ret i1 [[C]]
361   %A = getelementptr inbounds %S, ptr %P, i128 0, i32 1, i128 %X
362   %C = icmp eq ptr %A, %P
363   ret i1 %C
367 @G = external global [3 x i8]
368 define ptr @test14(i32 %idx) {
369 ; CHECK-LABEL: @test14(
370 ; CHECK-NEXT:    [[ZEXT:%.*]] = zext i32 [[IDX:%.*]] to i64
371 ; CHECK-NEXT:    [[T:%.*]] = getelementptr i8, ptr @G, i64 [[ZEXT]]
372 ; CHECK-NEXT:    ret ptr [[T]]
374   %zext = zext i32 %idx to i64
375   %t = getelementptr i8, ptr @G, i64 %zext
376   ret ptr %t
380 ; Test folding of constantexpr geps into normal geps.
381 @Array = external global [40 x i32]
382 define ptr @test15(i64 %X) {
383 ; CHECK-LABEL: @test15(
384 ; CHECK-NEXT:    [[A:%.*]] = getelementptr i32, ptr @Array, i64 [[X:%.*]]
385 ; CHECK-NEXT:    ret ptr [[A]]
387   %A = getelementptr i32, ptr @Array, i64 %X
388   ret ptr %A
392 define ptr @test16(ptr %X, i32 %Idx) {
393 ; CHECK-LABEL: @test16(
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]]
398   %R = getelementptr i32, ptr %X, i32 %Idx
399   ret ptr %R
403 define i1 @test17(ptr %P, i32 %I, i32 %J) {
404 ; CHECK-LABEL: @test17(
405 ; CHECK-NEXT:    [[C:%.*]] = icmp slt i32 [[I:%.*]], [[J:%.*]]
406 ; CHECK-NEXT:    ret i1 [[C]]
408   %X = getelementptr inbounds i16, ptr %P, i32 %I
409   %Y = getelementptr inbounds i16, ptr %P, i32 %J
410   %C = icmp ult ptr %X, %Y
411   ret i1 %C
414 define i1 @test18(ptr %P, i32 %I) {
415 ; CHECK-LABEL: @test18(
416 ; CHECK-NEXT:    [[C:%.*]] = icmp slt i32 [[I:%.*]], 0
417 ; CHECK-NEXT:    ret i1 [[C]]
419   %X = getelementptr inbounds i16, ptr %P, i32 %I
420   %C = icmp ult ptr %X, %P
421   ret i1 %C
424 ; Larger than the pointer size for a non-zero address space
425 define i1 @test18_as1(ptr addrspace(1) %P, i32 %I) {
426 ; CHECK-LABEL: @test18_as1(
427 ; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[I:%.*]], 32768
428 ; CHECK-NEXT:    [[C:%.*]] = icmp ne i32 [[TMP1]], 0
429 ; CHECK-NEXT:    ret i1 [[C]]
431   %X = getelementptr inbounds i16, ptr addrspace(1) %P, i32 %I
432   %C = icmp ult ptr addrspace(1) %X, %P
433   ret i1 %C
436 ; Smaller than the pointer size for a non-zero address space
437 define i1 @test18_as1_i32(ptr addrspace(1) %P, i32 %I) {
438 ; CHECK-LABEL: @test18_as1_i32(
439 ; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[I:%.*]], 32768
440 ; CHECK-NEXT:    [[C:%.*]] = icmp ne i32 [[TMP1]], 0
441 ; CHECK-NEXT:    ret i1 [[C]]
443   %X = getelementptr inbounds i16, ptr addrspace(1) %P, i32 %I
444   %C = icmp ult ptr addrspace(1) %X, %P
445   ret i1 %C
448 ; Smaller than pointer size
449 define i1 @test18_i16(ptr %P, i16 %I) {
450 ; CHECK-LABEL: @test18_i16(
451 ; CHECK-NEXT:    [[C:%.*]] = icmp slt i16 [[I:%.*]], 0
452 ; CHECK-NEXT:    ret i1 [[C]]
454   %X = getelementptr inbounds i16, ptr %P, i16 %I
455   %C = icmp ult ptr %X, %P
456   ret i1 %C
459 ; Same as pointer size
460 define i1 @test18_i64(ptr %P, i64 %I) {
461 ; CHECK-LABEL: @test18_i64(
462 ; CHECK-NEXT:    [[C:%.*]] = icmp slt i64 [[I:%.*]], 0
463 ; CHECK-NEXT:    ret i1 [[C]]
465   %X = getelementptr inbounds i16, ptr %P, i64 %I
466   %C = icmp ult ptr %X, %P
467   ret i1 %C
470 ; Larger than the pointer size
471 define i1 @test18_i128(ptr %P, i128 %I) {
472 ; CHECK-LABEL: @test18_i128(
473 ; CHECK-NEXT:    [[TMP1:%.*]] = and i128 [[I:%.*]], 9223372036854775808
474 ; CHECK-NEXT:    [[C:%.*]] = icmp ne i128 [[TMP1]], 0
475 ; CHECK-NEXT:    ret i1 [[C]]
477   %X = getelementptr inbounds i16, ptr %P, i128 %I
478   %C = icmp ult ptr %X, %P
479   ret i1 %C
482 define i32 @test19(ptr %P, i32 %A, i32 %B) {
483 ; CHECK-LABEL: @test19(
484 ; CHECK-NEXT:    [[T10:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
485 ; CHECK-NEXT:    [[T11:%.*]] = zext i1 [[T10]] to i32
486 ; CHECK-NEXT:    ret i32 [[T11]]
488   %t4 = getelementptr inbounds i32, ptr %P, i32 %A
489   %t9 = getelementptr inbounds i32, ptr %P, i32 %B
490   %t10 = icmp eq ptr %t4, %t9
491   %t11 = zext i1 %t10 to i32
492   ret i32 %t11
495 define i32 @test20(ptr %P, i32 %A, i32 %B) {
496 ; CHECK-LABEL: @test20(
497 ; CHECK-NEXT:    [[T6:%.*]] = icmp eq i32 [[A:%.*]], 0
498 ; CHECK-NEXT:    [[T7:%.*]] = zext i1 [[T6]] to i32
499 ; CHECK-NEXT:    ret i32 [[T7]]
501   %t4 = getelementptr inbounds i32, ptr %P, i32 %A
502   %t6 = icmp eq ptr %t4, %P
503   %t7 = zext i1 %t6 to i32
504   ret i32 %t7
507 define i32 @test20_as1(ptr addrspace(1) %P, i32 %A, i32 %B) {
508 ; CHECK-LABEL: @test20_as1(
509 ; CHECK-NEXT:    [[TMP1:%.*]] = trunc i32 [[A:%.*]] to i16
510 ; CHECK-NEXT:    [[T6:%.*]] = icmp eq i16 [[TMP1]], 0
511 ; CHECK-NEXT:    [[T7:%.*]] = zext i1 [[T6]] to i32
512 ; CHECK-NEXT:    ret i32 [[T7]]
514   %t4 = getelementptr inbounds i32, ptr addrspace(1) %P, i32 %A
515   %t6 = icmp eq ptr addrspace(1) %t4, %P
516   %t7 = zext i1 %t6 to i32
517   ret i32 %t7
521 define i32 @test21() {
522 ; CHECK-LABEL: @test21(
523 ; CHECK-NEXT:    [[PBOB1:%.*]] = alloca [[INTSTRUCT:%.*]], align 8
524 ; CHECK-NEXT:    [[RVAL:%.*]] = load i32, ptr [[PBOB1]], align 4
525 ; CHECK-NEXT:    ret i32 [[RVAL]]
527   %pbob1 = alloca %intstruct
528   %pbob2 = getelementptr %intstruct, ptr %pbob1
529   %rval = load i32, ptr %pbob2
530   ret i32 %rval
534 @A = global i32 1               ; <ptr> [#uses=1]
535 @B = global i32 2               ; <ptr> [#uses=1]
537 define i1 @test22() {
538 ; CHECK-LABEL: @test22(
539 ; CHECK-NEXT:    ret i1 icmp ult (ptr getelementptr inbounds (i32, ptr @A, i64 1), ptr getelementptr (i32, ptr @B, i64 2))
541   %C = icmp ult ptr getelementptr (i32, ptr @A, i64 1),
542   getelementptr (i32, ptr @B, i64 2)
543   ret i1 %C
547 %X = type { [10 x i32], float }
549 define i1 @test23() {
550 ; CHECK-LABEL: @test23(
551 ; CHECK-NEXT:    ret i1 false
553   %A = getelementptr %X, ptr null, i64 0, i32 0, i64 0                ; <ptr> [#uses=1]
554   %B = icmp ne ptr %A, null              ; <i1> [#uses=1]
555   ret i1 %B
558 define void @test25() {
559 ; CHECK-LABEL: @test25(
560 ; CHECK-NEXT:  entry:
561 ; CHECK-NEXT:    unreachable
563 entry:
564   %t = getelementptr { i64, i64, i64, i64 }, ptr null, i32 0, i32 3
565   %t.upgrd.1 = load i64, ptr %t
566   %t8.ui = load i64, ptr null
567   %t8 = bitcast i64 %t8.ui to i64
568   %t9 = and i64 %t8, %t.upgrd.1
569   %sext = trunc i64 %t9 to i32
570   %t27.i = sext i32 %sext to i64
571   tail call void @foo25( i32 0, i64 %t27.i )
572   unreachable
575 declare void @foo25(i32, i64)
578 ; PR1637
579 define i1 @test26(ptr %arr) {
580 ; CHECK-LABEL: @test26(
581 ; CHECK-NEXT:    ret i1 true
583   %X = getelementptr i8, ptr %arr, i32 1
584   %Y = getelementptr i8, ptr %arr, i32 1
585   %test = icmp uge ptr %X, %Y
586   ret i1 %test
589   %struct.__large_struct = type { [100 x i64] }
590   %struct.compat_siginfo = type { i32, i32, i32, { [29 x i32] } }
591   %struct.siginfo_t = type { i32, i32, i32, { { i32, i32, [0 x i8], %struct.sigval_t, i32 }, [88 x i8] } }
592   %struct.sigval_t = type { ptr }
594 define i32 @test27(ptr %to, ptr %from) {
595 ; CHECK-LABEL: @test27(
596 ; CHECK-NEXT:  entry:
597 ; CHECK-NEXT:    [[FROM_ADDR:%.*]] = alloca ptr, align 8
598 ; CHECK-NEXT:    [[T344:%.*]] = load ptr, ptr [[FROM_ADDR]], align 8
599 ; CHECK-NEXT:    [[T348:%.*]] = getelementptr [[STRUCT_SIGINFO_T:%.*]], ptr [[T344]], i64 0, i32 3, i32 0, i32 3
600 ; CHECK-NEXT:    [[T351:%.*]] = load i32, ptr [[T348]], align 8
601 ; 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]+]]
602 ; CHECK-NEXT:    unreachable
604 entry:
605   %from_addr = alloca ptr
606   %t344 = load ptr, ptr %from_addr, align 8
607   %t345 = getelementptr %struct.siginfo_t, ptr %t344, i32 0, i32 3
608   %t346 = getelementptr { { i32, i32, [0 x i8], %struct.sigval_t, i32 }, [88 x i8] }, ptr %t345, i32 0, i32 0
609   %t348 = getelementptr { i32, i32, %struct.sigval_t }, ptr %t346, i32 0, i32 2
610   %t351 = load i32, ptr %t348, align 8
611   %t360 = call i32 asm sideeffect "...",
612   "=r,ir,*m,i,0,~{dirflag},~{fpsr},~{flags}"( i32 %t351, ptr elementtype(%struct.__large_struct) null, i32 -14, i32 0 )
613   unreachable
616 ; PR1978
617   %struct.x = type <{ i8 }>
618 @.str = internal constant [6 x i8] c"Main!\00"
619 @.str1 = internal constant [12 x i8] c"destroy %p\0A\00"
621 define i32 @test28() nounwind  {
622 ; CHECK-LABEL: @test28(
623 ; CHECK-NEXT:  entry:
624 ; CHECK-NEXT:    [[ORIENTATIONS:%.*]] = alloca [1 x [1 x %struct.x]], align 8
625 ; CHECK-NEXT:    [[T3:%.*]] = call i32 @puts(ptr noundef nonnull dereferenceable(1) @.str) #[[ATTR0]]
626 ; CHECK-NEXT:    br label [[BB10:%.*]]
627 ; CHECK:       bb10:
628 ; CHECK-NEXT:    [[INDVAR:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[BB10]] ]
629 ; CHECK-NEXT:    [[T12_REC:%.*]] = xor i32 [[INDVAR]], -1
630 ; CHECK-NEXT:    [[TMP0:%.*]] = sext i32 [[T12_REC]] to i64
631 ; CHECK-NEXT:    [[T12:%.*]] = getelementptr inbounds [1 x [1 x %struct.x]], ptr [[ORIENTATIONS]], i64 1, i64 0, i64 [[TMP0]]
632 ; CHECK-NEXT:    [[T16:%.*]] = call i32 (ptr, ...) @printf(ptr noundef nonnull dereferenceable(1) @.str1, ptr nonnull [[T12]]) #[[ATTR0]]
633 ; CHECK-NEXT:    [[T84:%.*]] = icmp eq i32 [[INDVAR]], 0
634 ; CHECK-NEXT:    [[INDVAR_NEXT]] = add i32 [[INDVAR]], 1
635 ; CHECK-NEXT:    br i1 [[T84]], label [[BB17:%.*]], label [[BB10]]
636 ; CHECK:       bb17:
637 ; CHECK-NEXT:    ret i32 0
639 entry:
640   %orientations = alloca [1 x [1 x %struct.x]]
641   %t3 = call i32 @puts( ptr @.str ) nounwind
642   %t45 = getelementptr inbounds [1 x [1 x %struct.x]], ptr %orientations, i32 1, i32 0, i32 0
643   br label %bb10
645 bb10:
646   %indvar = phi i32 [ 0, %entry ], [ %indvar.next, %bb10 ]
647   %t.0.reg2mem.0.rec = mul i32 %indvar, -1
648   %t12.rec = add i32 %t.0.reg2mem.0.rec, -1
649   %t12 = getelementptr inbounds %struct.x, ptr %t45, i32 %t12.rec
650   %t16 = call i32 (ptr, ...) @printf( ptr nonnull dereferenceable(1) @.str1, ptr %t12 ) nounwind
651   %t84 = icmp eq ptr %t12, %orientations
652   %indvar.next = add i32 %indvar, 1
653   br i1 %t84, label %bb17, label %bb10
655 bb17:
656   ret i32 0
659 declare i32 @puts(ptr)
661 declare i32 @printf(ptr, ...)
666 ; rdar://6762290
667   %T = type <{ i64, i64, i64 }>
668 define i32 @test29(ptr %start, i32 %X) nounwind {
669 ; CHECK-LABEL: @test29(
670 ; CHECK-NEXT:  entry:
671 ; CHECK-NEXT:    store i1 true, ptr poison, align 1
672 ; CHECK-NEXT:    br i1 poison, label [[IF_THEN216:%.*]], label [[IF_END363:%.*]]
673 ; CHECK:       if.then216:
674 ; CHECK-NEXT:    ret i32 1
675 ; CHECK:       if.end363:
676 ; CHECK-NEXT:    ret i32 0
678 entry:
679   %t3 = load i64, ptr null
680   %add.ptr = getelementptr i8, ptr %start, i64 %t3
681   %t158 = load i32, ptr null
682   %add.ptr159 = getelementptr %T, ptr null, i32 %t158
683   %add.ptr212 = getelementptr i8, ptr %start, i32 %X
684   %cmp214 = icmp ugt ptr %add.ptr212, %add.ptr
685   br i1 %cmp214, label %if.then216, label %if.end363
687 if.then216:
688   ret i32 1
690 if.end363:
691   ret i32 0
695 ; PR3694
696 define i32 @test30(i32 %m, i32 %n) nounwind {
697 ; CHECK-LABEL: @test30(
698 ; CHECK-NEXT:  entry:
699 ; CHECK-NEXT:    [[TMP0:%.*]] = zext i32 [[N:%.*]] to i64
700 ; CHECK-NEXT:    [[TMP1:%.*]] = alloca i32, i64 [[TMP0]], align 4
701 ; CHECK-NEXT:    call void @test30f(ptr nonnull [[TMP1]]) #[[ATTR0]]
702 ; CHECK-NEXT:    [[TMP2:%.*]] = sext i32 [[M:%.*]] to i64
703 ; CHECK-NEXT:    [[TMP3:%.*]] = getelementptr [0 x i32], ptr [[TMP1]], i64 0, i64 [[TMP2]]
704 ; CHECK-NEXT:    [[TMP4:%.*]] = load i32, ptr [[TMP3]], align 4
705 ; CHECK-NEXT:    ret i32 [[TMP4]]
707 entry:
708   %0 = alloca i32, i32 %n, align 4
709   call void @test30f(ptr %0) nounwind
710   %1 = getelementptr [0 x i32], ptr %0, i32 0, i32 %m
711   %2 = load i32, ptr %1, align 4
712   ret i32 %2
715 declare void @test30f(ptr)
719 define i1 @test31(ptr %A) {
720 ; CHECK-LABEL: @test31(
721 ; CHECK-NEXT:    ret i1 true
723   %B = getelementptr i32, ptr %A, i32 1
724   %C = getelementptr i32, ptr %A, i64 1
725   %V = icmp eq ptr %B, %C
726   ret i1 %V
730 ; PR1345
731 define ptr @test32(ptr %v) {
732 ; CHECK-LABEL: @test32(
733 ; CHECK-NEXT:    [[A:%.*]] = alloca [4 x ptr], align 16
734 ; CHECK-NEXT:    store ptr null, ptr [[A]], align 8
735 ; CHECK-NEXT:    [[D:%.*]] = getelementptr inbounds { [16 x i8] }, ptr [[A]], i64 0, i32 0, i64 8
736 ; CHECK-NEXT:    store ptr [[V:%.*]], ptr [[D]], align 8
737 ; CHECK-NEXT:    [[F:%.*]] = getelementptr inbounds [4 x ptr], ptr [[A]], i64 0, i64 2
738 ; CHECK-NEXT:    [[G:%.*]] = load ptr, ptr [[F]], align 8
739 ; CHECK-NEXT:    ret ptr [[G]]
741   %A = alloca [4 x ptr], align 16
742   store ptr null, ptr %A
743   %D = getelementptr { [16 x i8] }, ptr %A, i32 0, i32 0, i32 8
744   store ptr %v, ptr %D
745   %F = getelementptr [4 x ptr], ptr %A, i32 0, i32 2
746   %G = load ptr, ptr %F
747   ret ptr %G
750 ; PR3290
751 %struct.Key = type { { i32, i32 } }
752 %struct.anon = type <{ i8, [3 x i8], i32 }>
754 define ptr @test33(ptr %A) {
755 ; CHECK-LABEL: @test33(
756 ; CHECK-NEXT:    [[C:%.*]] = getelementptr [[STRUCT_ANON:%.*]], ptr [[A:%.*]], i64 0, i32 2
757 ; CHECK-NEXT:    ret ptr [[C]]
759   %C = getelementptr %struct.anon, ptr %A, i32 0, i32 2
760   ret ptr %C
763 define ptr addrspace(1) @test33_as1(ptr addrspace(1) %A) {
764 ; CHECK-LABEL: @test33_as1(
765 ; CHECK-NEXT:    [[C:%.*]] = getelementptr [[STRUCT_ANON:%.*]], ptr addrspace(1) [[A:%.*]], i16 0, i32 2
766 ; CHECK-NEXT:    ret ptr addrspace(1) [[C]]
768   %C = getelementptr %struct.anon, ptr addrspace(1) %A, i32 0, i32 2
769   ret ptr addrspace(1) %C
772 define ptr addrspace(1) @test33_array_as1(ptr addrspace(1) %A) {
773 ; CHECK-LABEL: @test33_array_as1(
774 ; CHECK-NEXT:    [[C:%.*]] = getelementptr [5 x i32], ptr addrspace(1) [[A:%.*]], i16 0, i16 2
775 ; CHECK-NEXT:    ret ptr addrspace(1) [[C]]
777   %C = getelementptr [5 x i32], ptr addrspace(1) %A, i32 0, i32 2
778   ret ptr addrspace(1) %C
781 ; Make sure the GEP indices use the right pointer sized integer
782 define ptr addrspace(1) @test33_array_struct_as1(ptr addrspace(1) %A) {
783 ; CHECK-LABEL: @test33_array_struct_as1(
784 ; CHECK-NEXT:    [[C:%.*]] = getelementptr [20 x i32], ptr addrspace(1) [[A:%.*]], i16 0, i16 2
785 ; CHECK-NEXT:    ret ptr addrspace(1) [[C]]
787   %C = getelementptr [20 x i32], ptr addrspace(1) %A, i32 0, i32 2
788   ret ptr addrspace(1) %C
791 define ptr addrspace(1) @test33_addrspacecast(ptr %A) {
792 ; CHECK-LABEL: @test33_addrspacecast(
793 ; CHECK-NEXT:    [[B:%.*]] = addrspacecast ptr [[A:%.*]] to ptr addrspace(1)
794 ; CHECK-NEXT:    [[C:%.*]] = getelementptr [[STRUCT_ANON:%.*]], ptr addrspace(1) [[B]], i16 0, i32 2
795 ; CHECK-NEXT:    ret ptr addrspace(1) [[C]]
797   %B = addrspacecast ptr %A to ptr addrspace(1)
798   %C = getelementptr %struct.anon, ptr addrspace(1) %B, i32 0, i32 2
799   ret ptr addrspace(1) %C
802   %T2 = type { ptr, i8 }
803 define ptr @test34(ptr %Val, i64 %V) nounwind {
804 ; CHECK-LABEL: @test34(
805 ; CHECK-NEXT:  entry:
806 ; CHECK-NEXT:    [[C_CAST:%.*]] = inttoptr i64 [[V:%.*]] to ptr
807 ; CHECK-NEXT:    ret ptr [[C_CAST]]
809 entry:
810   %A = alloca %T2, align 8
812   store i64 %V, ptr %A
813   %C = load ptr, ptr %A, align 8
814   ret ptr %C
817 %t0 = type { ptr, [19 x i8] }
818 %t1 = type { ptr, [0 x i8] }
820 @array = external global [11 x i8]
822 @s = external global %t0
823 @"\01LC8" = external constant [17 x i8]
825 ; Instcombine should be able to fold this getelementptr.
827 define i32 @test35() nounwind {
828 ; CHECK-LABEL: @test35(
829 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 (ptr, ...) @printf(ptr noundef nonnull dereferenceable(1) @"\01LC8", ptr nonnull getelementptr inbounds ([[T0:%.*]], ptr @s, i64 0, i32 1, i64 0)) #[[ATTR0]]
830 ; CHECK-NEXT:    ret i32 0
832   call i32 (ptr, ...) @printf(ptr @"\01LC8",
833   ptr getelementptr (%t1, ptr @s, i32 0, i32 1, i32 0)) nounwind
834   ret i32 0
837 ; Don't treat signed offsets as unsigned.
838 define ptr @test36() nounwind {
839 ; CHECK-LABEL: @test36(
840 ; CHECK-NEXT:    ret ptr getelementptr ([11 x i8], ptr @array, i64 -1, i64 10)
842   ret ptr getelementptr ([11 x i8], ptr @array, i32 0, i64 -1)
845 ; Instcombine shouldn't assume that gep(A,0,1) != gep(A,1,0).
846 @A37 = external constant [1 x i8]
847 define i1 @test37() nounwind {
848 ; CHECK-LABEL: @test37(
849 ; CHECK-NEXT:    ret i1 true
851   %t = icmp eq ptr getelementptr ([1 x i8], ptr @A37, i64 0, i64 1),
852   getelementptr ([1 x i8], ptr @A37, i64 1, i64 0)
853   ret i1 %t
856 ; Test index promotion
857 define ptr @test38(ptr %I, i32 %n) {
858 ; CHECK-LABEL: @test38(
859 ; CHECK-NEXT:    [[TMP1:%.*]] = sext i32 [[N:%.*]] to i64
860 ; CHECK-NEXT:    [[A:%.*]] = getelementptr i32, ptr [[I:%.*]], i64 [[TMP1]]
861 ; CHECK-NEXT:    ret ptr [[A]]
863   %A = getelementptr i32, ptr %I, i32 %n
864   ret ptr %A
867 ; Test that we don't duplicate work when the second gep is a "bitcast".
868 %pr10322_t = type { ptr }
869 declare void @pr10322_f2(ptr)
870 declare void @pr10322_f3(ptr)
871 define void @pr10322_f1(ptr %foo) {
872 ; CHECK-LABEL: @pr10322_f1(
873 ; CHECK-NEXT:  entry:
874 ; CHECK-NEXT:    [[ARRAYIDX8:%.*]] = getelementptr inbounds [[PR10322_T:%.*]], ptr [[FOO:%.*]], i64 2
875 ; CHECK-NEXT:    call void @pr10322_f2(ptr nonnull [[ARRAYIDX8]]) #[[ATTR0]]
876 ; CHECK-NEXT:    call void @pr10322_f3(ptr nonnull [[ARRAYIDX8]]) #[[ATTR0]]
877 ; CHECK-NEXT:    ret void
879 entry:
880   %arrayidx8 = getelementptr inbounds %pr10322_t, ptr %foo, i64 2
881   call void @pr10322_f2(ptr %arrayidx8) nounwind
882   call void @pr10322_f3(ptr %arrayidx8) nounwind
883   ret void
887 ; Test that we combine the last two geps in this sequence, before we
888 ; would wait for gep1 and gep2 to be combined and never combine 2 and 3.
889 %three_gep_t = type {i32}
890 %three_gep_t2 = type {%three_gep_t}
892 define void @three_gep_f(ptr %x) {
893 ; CHECK-LABEL: @three_gep_f(
894 ; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr [[THREE_GEP_T2:%.*]], ptr [[X:%.*]], i64 2
895 ; CHECK-NEXT:    call void @three_gep_h(ptr [[GEP1]])
896 ; CHECK-NEXT:    call void @three_gep_g(ptr [[GEP1]])
897 ; CHECK-NEXT:    ret void
899   %gep1 = getelementptr %three_gep_t2, ptr %x, i64 2
900   call void @three_gep_h(ptr %gep1)
901   call void @three_gep_g(ptr %gep1)
903   ret void
906 declare void @three_gep_g(ptr)
907 declare void @three_gep_h(ptr)
909 %struct.ham = type { i32, ptr, ptr, ptr }
910 %struct.zot = type { i64, i8 }
912 define void @test39(ptr %arg, i8 %arg1) nounwind {
913 ; CHECK-LABEL: @test39(
914 ; CHECK-NEXT:    [[T:%.*]] = getelementptr inbounds [[STRUCT_HAM:%.*]], ptr [[ARG:%.*]], i64 0, i32 2
915 ; CHECK-NEXT:    [[T2:%.*]] = load ptr, ptr [[T]], align 8
916 ; CHECK-NEXT:    [[T4:%.*]] = getelementptr inbounds i8, ptr [[T2]], i64 -8
917 ; CHECK-NEXT:    store i8 [[ARG1:%.*]], ptr [[T4]], align 8
918 ; CHECK-NEXT:    ret void
920   %t = getelementptr inbounds %struct.ham, ptr %arg, i64 0, i32 2
921   %t2 = load ptr, ptr %t, align 8
922   %t4 = getelementptr inbounds i8, ptr %t2, i64 -8
923   store i8 %arg1, ptr %t4, align 8
924   ret void
928 define i1 @pr16483(ptr %a, ptr %b) {
929 ; CHECK-LABEL: @pr16483(
930 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult ptr [[A:%.*]], [[B:%.*]]
931 ; CHECK-NEXT:    ret i1 [[CMP]]
933   %cmp = icmp ult ptr %a, %b
934   ret i1 %cmp
938 define i8 @test_gep_bitcast_as1(ptr addrspace(1) %arr, i16 %N) {
939 ; CHECK-LABEL: @test_gep_bitcast_as1(
940 ; CHECK-NEXT:    [[V:%.*]] = shl i16 [[N:%.*]], 2
941 ; CHECK-NEXT:    [[T:%.*]] = getelementptr i8, ptr addrspace(1) [[ARR:%.*]], i16 [[V]]
942 ; CHECK-NEXT:    [[X:%.*]] = load i8, ptr addrspace(1) [[T]], align 1
943 ; CHECK-NEXT:    ret i8 [[X]]
945   %V = mul i16 %N, 4
946   %t = getelementptr i8, ptr addrspace(1) %arr, i16 %V
947   %x = load i8, ptr addrspace(1) %t
948   ret i8 %x
951 ; The element size of the array matches the element size of the pointer
952 define i64 @test_gep_bitcast_array_same_size_element(ptr %arr, i64 %N) {
953 ; CHECK-LABEL: @test_gep_bitcast_array_same_size_element(
954 ; CHECK-NEXT:    [[V:%.*]] = shl i64 [[N:%.*]], 3
955 ; CHECK-NEXT:    [[T:%.*]] = getelementptr i64, ptr [[ARR:%.*]], i64 [[V]]
956 ; CHECK-NEXT:    [[X:%.*]] = load i64, ptr [[T]], align 4
957 ; CHECK-NEXT:    ret i64 [[X]]
959   %V = mul i64 %N, 8
960   %t = getelementptr i64, ptr %arr, i64 %V
961   %x = load i64, ptr %t
962   ret i64 %x
965 ; gep should be done in the original address space.
966 define i64 @test_gep_bitcast_array_same_size_element_addrspacecast(ptr %arr, i64 %N) {
967 ; CHECK-LABEL: @test_gep_bitcast_array_same_size_element_addrspacecast(
968 ; CHECK-NEXT:    [[CAST:%.*]] = addrspacecast ptr [[ARR:%.*]] to ptr addrspace(3)
969 ; CHECK-NEXT:    [[V:%.*]] = shl i64 [[N:%.*]], 3
970 ; CHECK-NEXT:    [[T:%.*]] = getelementptr i64, ptr addrspace(3) [[CAST]], i64 [[V]]
971 ; CHECK-NEXT:    [[X:%.*]] = load i64, ptr addrspace(3) [[T]], align 4
972 ; CHECK-NEXT:    ret i64 [[X]]
974   %cast = addrspacecast ptr %arr to ptr addrspace(3)
975   %V = mul i64 %N, 8
976   %t = getelementptr i64, ptr addrspace(3) %cast, i64 %V
977   %x = load i64, ptr addrspace(3) %t
978   ret i64 %x
981 ; The element size of the array is different the element size of the pointer
982 define i8 @test_gep_bitcast_array_different_size_element(ptr %arr, i64 %N) {
983 ; CHECK-LABEL: @test_gep_bitcast_array_different_size_element(
984 ; CHECK-NEXT:    [[V:%.*]] = shl i64 [[N:%.*]], 3
985 ; CHECK-NEXT:    [[T:%.*]] = getelementptr i8, ptr [[ARR:%.*]], i64 [[V]]
986 ; CHECK-NEXT:    [[X:%.*]] = load i8, ptr [[T]], align 1
987 ; CHECK-NEXT:    ret i8 [[X]]
989   %V = mul i64 %N, 8
990   %t = getelementptr i8, ptr %arr, i64 %V
991   %x = load i8, ptr %t
992   ret i8 %x
995 define i64 @test_gep_bitcast_array_same_size_element_as1(ptr addrspace(1) %arr, i16 %N) {
996 ; CHECK-LABEL: @test_gep_bitcast_array_same_size_element_as1(
997 ; CHECK-NEXT:    [[V:%.*]] = shl i16 [[N:%.*]], 3
998 ; CHECK-NEXT:    [[T:%.*]] = getelementptr i64, ptr addrspace(1) [[ARR:%.*]], i16 [[V]]
999 ; CHECK-NEXT:    [[X:%.*]] = load i64, ptr addrspace(1) [[T]], align 4
1000 ; CHECK-NEXT:    ret i64 [[X]]
1002   %V = mul i16 %N, 8
1003   %t = getelementptr i64, ptr addrspace(1) %arr, i16 %V
1004   %x = load i64, ptr addrspace(1) %t
1005   ret i64 %x
1008 define i8 @test_gep_bitcast_array_different_size_element_as1(ptr addrspace(1) %arr, i16 %N) {
1009 ; CHECK-LABEL: @test_gep_bitcast_array_different_size_element_as1(
1010 ; CHECK-NEXT:    [[V:%.*]] = shl i16 [[N:%.*]], 3
1011 ; CHECK-NEXT:    [[T:%.*]] = getelementptr i8, ptr addrspace(1) [[ARR:%.*]], i16 [[V]]
1012 ; CHECK-NEXT:    [[X:%.*]] = load i8, ptr addrspace(1) [[T]], align 1
1013 ; CHECK-NEXT:    ret i8 [[X]]
1015   %V = mul i16 %N, 8
1016   %t = getelementptr i8, ptr addrspace(1) %arr, i16 %V
1017   %x = load i8, ptr addrspace(1) %t
1018   ret i8 %x
1021 define i64 @test40() {
1022 ; CHECK-LABEL: @test40(
1023 ; CHECK-NEXT:    ret i64 8
1025   %array = alloca [3 x i32], align 4
1026   %gep = getelementptr inbounds [3 x i32], ptr %array, i64 0, i64 2
1027   %p = ptrtoint ptr %array to i64
1028   %np = sub i64 0, %p
1029   %gep2 = getelementptr i8, ptr %gep, i64 %np
1030   %ret = ptrtoint ptr %gep2 to i64
1031   ret i64 %ret
1035 define i16 @test41(ptr addrspace(1) %array) {
1036 ; CHECK-LABEL: @test41(
1037 ; CHECK-NEXT:    ret i16 8
1039   %gep = getelementptr inbounds [3 x i32], ptr addrspace(1) %array, i16 0, i16 2
1040   %p = ptrtoint ptr addrspace(1) %array to i16
1041   %np = sub i16 0, %p
1042   %gep2 = getelementptr i8, ptr addrspace(1) %gep, i16 %np
1043   %ret = ptrtoint ptr addrspace(1) %gep2 to i16
1044   ret i16 %ret
1048 define ptr @test42i(ptr %c1, ptr %c2) {
1049 ; CHECK-LABEL: @test42i(
1050 ; CHECK-NEXT:    [[PTRTOINT:%.*]] = ptrtoint ptr [[C1:%.*]] to i64
1051 ; CHECK-NEXT:    [[SUB:%.*]] = sub i64 0, [[PTRTOINT]]
1052 ; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds i8, ptr [[C2:%.*]], i64 [[SUB]]
1053 ; CHECK-NEXT:    ret ptr [[GEP]]
1055   %ptrtoint = ptrtoint ptr %c1 to i64
1056   %sub = sub i64 0, %ptrtoint
1057   %gep = getelementptr inbounds i8, ptr %c2, i64 %sub
1058   ret ptr %gep
1062 define ptr @test42(ptr %c1, ptr %c2) {
1063 ; CHECK-LABEL: @test42(
1064 ; CHECK-NEXT:    [[PTRTOINT:%.*]] = ptrtoint ptr [[C1:%.*]] to i64
1065 ; CHECK-NEXT:    [[SUB:%.*]] = sub i64 0, [[PTRTOINT]]
1066 ; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i8, ptr [[C2:%.*]], i64 [[SUB]]
1067 ; CHECK-NEXT:    ret ptr [[GEP]]
1069   %ptrtoint = ptrtoint ptr %c1 to i64
1070   %sub = sub i64 0, %ptrtoint
1071   %gep = getelementptr i8, ptr %c2, i64 %sub
1072   ret ptr %gep
1076 define ptr @test43i(ptr %c1, ptr %c2) {
1077 ; CHECK-LABEL: @test43i(
1078 ; CHECK-NEXT:    [[PTRTOINT:%.*]] = ptrtoint ptr [[C1:%.*]] to i64
1079 ; CHECK-NEXT:    [[SUB:%.*]] = sub i64 0, [[PTRTOINT]]
1080 ; CHECK-NEXT:    [[SHR:%.*]] = ashr i64 [[SUB]], 1
1081 ; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds i16, ptr [[C2:%.*]], i64 [[SHR]]
1082 ; CHECK-NEXT:    ret ptr [[GEP]]
1084   %ptrtoint = ptrtoint ptr %c1 to i64
1085   %sub = sub i64 0, %ptrtoint
1086   %shr = ashr i64 %sub, 1
1087   %gep = getelementptr inbounds i16, ptr %c2, i64 %shr
1088   ret ptr %gep
1092 define ptr @test44i(ptr %c1, ptr %c2) {
1093 ; CHECK-LABEL: @test44i(
1094 ; CHECK-NEXT:    [[PTRTOINT:%.*]] = ptrtoint ptr [[C1:%.*]] to i64
1095 ; CHECK-NEXT:    [[SUB:%.*]] = sub i64 0, [[PTRTOINT]]
1096 ; CHECK-NEXT:    [[SHR:%.*]] = sdiv i64 [[SUB]], 7
1097 ; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds [[STRUCT_C:%.*]], ptr [[C2:%.*]], i64 [[SHR]]
1098 ; CHECK-NEXT:    ret ptr [[GEP]]
1100   %ptrtoint = ptrtoint ptr %c1 to i64
1101   %sub = sub i64 0, %ptrtoint
1102   %shr = sdiv i64 %sub, 7
1103   %gep = getelementptr inbounds %struct.C, ptr %c2, i64 %shr
1104   ret ptr %gep
1108 define ptr @test45(ptr %c1, ptr %c2) {
1109 ; CHECK-LABEL: @test45(
1110 ; CHECK-NEXT:    [[PTRTOINT1:%.*]] = ptrtoint ptr [[C1:%.*]] to i64
1111 ; CHECK-NEXT:    [[PTRTOINT2:%.*]] = ptrtoint ptr [[C2:%.*]] to i64
1112 ; CHECK-NEXT:    [[SUB:%.*]] = sub i64 [[PTRTOINT2]], [[PTRTOINT1]]
1113 ; CHECK-NEXT:    [[SHR:%.*]] = sdiv i64 [[SUB]], 7
1114 ; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds [[STRUCT_C:%.*]], ptr [[C1]], i64 [[SHR]]
1115 ; CHECK-NEXT:    ret ptr [[GEP]]
1117   %ptrtoint1 = ptrtoint ptr %c1 to i64
1118   %ptrtoint2 = ptrtoint ptr %c2 to i64
1119   %sub = sub i64 %ptrtoint2, %ptrtoint1 ; C2 - C1
1120   %shr = sdiv i64 %sub, 7
1121   %gep = getelementptr inbounds %struct.C, ptr %c1, i64 %shr ; C1 + (C2 - C1)
1122   ret ptr %gep
1125 define ptr @test46(ptr %c1, ptr %c2, i64 %N) {
1126 ; CHECK-LABEL: @test46(
1127 ; CHECK-NEXT:    [[PTRTOINT:%.*]] = ptrtoint ptr [[C1:%.*]] to i64
1128 ; CHECK-NEXT:    [[SUB:%.*]] = sub i64 0, [[PTRTOINT]]
1129 ; CHECK-NEXT:    [[SDIV:%.*]] = sdiv i64 [[SUB]], [[N:%.*]]
1130 ; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds [[STRUCT_C:%.*]], ptr [[C2:%.*]], i64 [[SDIV]]
1131 ; CHECK-NEXT:    ret ptr [[GEP]]
1133   %ptrtoint = ptrtoint ptr %c1 to i64
1134   %sub = sub i64 0, %ptrtoint
1135   %sdiv = sdiv i64 %sub, %N
1136   %gep = getelementptr inbounds %struct.C, ptr %c2, i64 %sdiv
1137   ret ptr %gep
1141 define ptr @test47(ptr %I, i64 %C, i64 %D) {
1142 ; CHECK-LABEL: @test47(
1143 ; CHECK-NEXT:    [[B:%.*]] = getelementptr i32, ptr [[I:%.*]], i64 [[D:%.*]]
1144 ; CHECK-NEXT:    ret ptr [[B]]
1146   %sub = sub i64 %D, %C
1147   %A = getelementptr i32, ptr %I, i64 %C
1148   %B = getelementptr i32, ptr %A, i64 %sub
1149   ret ptr %B
1152 define ptr @test48(ptr %I, i64 %C, i64 %D) {
1153 ; CHECK-LABEL: @test48(
1154 ; CHECK-NEXT:    [[B:%.*]] = getelementptr i32, ptr [[I:%.*]], i64 [[D:%.*]]
1155 ; CHECK-NEXT:    ret ptr [[B]]
1157   %sub = sub i64 %D, %C
1158   %A = getelementptr i32, ptr %I, i64 %sub
1159   %B = getelementptr i32, ptr %A, i64 %C
1160   ret ptr %B
1163 define ptr @test49(ptr %I, i64 %C) {
1164 ; CHECK-LABEL: @test49(
1165 ; CHECK-NEXT:    [[B:%.*]] = getelementptr i32, ptr [[I:%.*]], i64 -1
1166 ; CHECK-NEXT:    ret ptr [[B]]
1168   %notC = xor i64 -1, %C
1169   %A = getelementptr i32, ptr %I, i64 %C
1170   %B = getelementptr i32, ptr %A, i64 %notC
1171   ret ptr %B
1174 define ptr addrspace(1) @ascast_0_gep(ptr %p) nounwind {
1175 ; CHECK-LABEL: @ascast_0_gep(
1176 ; CHECK-NEXT:    [[X:%.*]] = addrspacecast ptr [[P:%.*]] to ptr addrspace(1)
1177 ; CHECK-NEXT:    ret ptr addrspace(1) [[X]]
1179   %x = addrspacecast ptr %p to ptr addrspace(1)
1180   ret ptr addrspace(1) %x
1183 ; Do not merge the GEP and the addrspacecast, because it would undo the
1184 ; addrspacecast canonicalization.
1185 define ptr addrspace(1) @ascast_0_0_gep(ptr %p) nounwind {
1186 ; CHECK-LABEL: @ascast_0_0_gep(
1187 ; CHECK-NEXT:    [[X:%.*]] = addrspacecast ptr [[P:%.*]] to ptr addrspace(1)
1188 ; CHECK-NEXT:    ret ptr addrspace(1) [[X]]
1190   %x = addrspacecast ptr %p to ptr addrspace(1)
1191   ret ptr addrspace(1) %x
1194 define <2 x ptr> @PR32414(ptr %ptr) {
1195 ; CHECK-LABEL: @PR32414(
1196 ; CHECK-NEXT:    [[T1:%.*]] = getelementptr inbounds i32, ptr [[PTR:%.*]], <2 x i64> <i64 0, i64 1>
1197 ; CHECK-NEXT:    ret <2 x ptr> [[T1]]
1199   %t1 = getelementptr inbounds i32, ptr %ptr, <2 x i64> <i64 0, i64 1>
1200   ret <2 x ptr> %t1
1203 define ptr @test_bitcast_nzgep(ptr %base, i64 %idx) {
1204 ; CHECK-LABEL: @test_bitcast_nzgep(
1205 ; CHECK-NEXT:    [[PTR:%.*]] = getelementptr inbounds i32, ptr [[BASE:%.*]], i64 [[IDX:%.*]]
1206 ; CHECK-NEXT:    ret ptr [[PTR]]
1208   %ptr = getelementptr inbounds i32, ptr %base, i64 %idx
1209   ret ptr %ptr
1212 define ptr @test_zgep_nzgep(ptr %base, i64 %idx) {
1213 ; CHECK-LABEL: @test_zgep_nzgep(
1214 ; CHECK-NEXT:    [[PTR:%.*]] = getelementptr inbounds i32, ptr [[BASE:%.*]], i64 [[IDX:%.*]]
1215 ; CHECK-NEXT:    ret ptr [[PTR]]
1217   %ptr = getelementptr inbounds i32, ptr %base, i64 %idx
1218   ret ptr %ptr
1221 define ptr @test_nzgep_zgep(ptr %base, i64 %idx) {
1222 ; CHECK-LABEL: @test_nzgep_zgep(
1223 ; CHECK-NEXT:    [[BASE2:%.*]] = getelementptr inbounds [1 x i32], ptr [[BASE:%.*]], i64 [[IDX:%.*]]
1224 ; CHECK-NEXT:    ret ptr [[BASE2]]
1226   %base2 = getelementptr inbounds [1 x i32], ptr %base, i64 %idx
1227   ret ptr %base2
1230 define ptr @test_gep_inbounds_of_gep(ptr %base) {
1231 ; CHECK-LABEL: @test_gep_inbounds_of_gep(
1232 ; CHECK-NEXT:    [[PTR2:%.*]] = getelementptr i32, ptr [[BASE:%.*]], i64 8
1233 ; CHECK-NEXT:    ret ptr [[PTR2]]
1235   %ptr1 = getelementptr i32, ptr %base, i64 4
1236   %ptr2 = getelementptr inbounds i32, ptr %ptr1, i64 4
1237   ret ptr %ptr2
1240 %struct.f = type { i32 }
1242 @g0 = internal unnamed_addr constant %struct.f zeroinitializer, align 4
1243 @g1 = internal unnamed_addr constant %struct.f { i32 -1 }, align 4
1245 define ptr @PR45084(i1 %cond) {
1246 ; CHECK-LABEL: @PR45084(
1247 ; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND:%.*]], ptr @g0, ptr @g1, !prof [[PROF0:![0-9]+]]
1248 ; CHECK-NEXT:    ret ptr [[SEL]]
1250   %sel = select i1 %cond, ptr @g0, ptr @g1, !prof !0
1251   ret ptr %sel
1254 define ptr @PR45084_extra_use(i1 %cond, ptr %p) {
1255 ; CHECK-LABEL: @PR45084_extra_use(
1256 ; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND:%.*]], ptr @g0, ptr @g1
1257 ; CHECK-NEXT:    store ptr [[SEL]], ptr [[P:%.*]], align 8
1258 ; CHECK-NEXT:    ret ptr [[SEL]]
1260   %sel = select i1 %cond, ptr @g0, ptr @g1
1261   store ptr %sel, ptr %p
1262   ret ptr %sel
1265 define ptr @gep_null_inbounds(i64 %idx) {
1266 ; CHECK-LABEL: @gep_null_inbounds(
1267 ; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds i8, ptr null, i64 [[IDX:%.*]]
1268 ; CHECK-NEXT:    ret ptr [[GEP]]
1270   %gep = getelementptr inbounds i8, ptr null, i64 %idx
1271   ret ptr %gep
1274 define ptr @gep_null_not_inbounds(i64 %idx) {
1275 ; CHECK-LABEL: @gep_null_not_inbounds(
1276 ; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i8, ptr null, i64 [[IDX:%.*]]
1277 ; CHECK-NEXT:    ret ptr [[GEP]]
1279   %gep = getelementptr i8, ptr null, i64 %idx
1280   ret ptr %gep
1283 define ptr @gep_null_defined(i64 %idx) null_pointer_is_valid {
1284 ; CHECK-LABEL: @gep_null_defined(
1285 ; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds i8, ptr null, i64 [[IDX:%.*]]
1286 ; CHECK-NEXT:    ret ptr [[GEP]]
1288   %gep = getelementptr inbounds i8, ptr null, i64 %idx
1289   ret ptr %gep
1292 define ptr @gep_null_inbounds_different_type(i64 %idx1, i64 %idx2) {
1293 ; CHECK-LABEL: @gep_null_inbounds_different_type(
1294 ; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds [0 x i8], ptr null, i64 0, i64 [[IDX2:%.*]]
1295 ; CHECK-NEXT:    ret ptr [[GEP]]
1297   %gep = getelementptr inbounds [0 x i8], ptr null, i64 %idx1, i64 %idx2
1298   ret ptr %gep
1301 define ptr @D98588(ptr %c1, i64 %offset) {
1302 ; CHECK-LABEL: @D98588(
1303 ; CHECK-NEXT:    [[C2_NEXT_IDX:%.*]] = shl nsw i64 [[OFFSET:%.*]], 3
1304 ; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds i8, ptr [[C1:%.*]], i64 [[C2_NEXT_IDX]]
1305 ; CHECK-NEXT:    ret ptr [[GEP]]
1307   %c2_next = getelementptr inbounds i64, ptr %c1, i64 %offset
1308   %ptrtoint1 = ptrtoint ptr %c1 to i64
1309   %ptrtoint2 = ptrtoint ptr %c2_next to i64
1310   %sub = sub i64 %ptrtoint2, %ptrtoint1 ; C2 - C1
1311   %gep = getelementptr inbounds i8, ptr %c1, i64 %sub ; C1 + (C2 - C1)
1312   ret ptr %gep
1315 declare noalias ptr @malloc(i64) nounwind allockind("alloc,uninitialized") allocsize(0)
1317 define i32 @test_gep_bitcast_malloc(ptr %a) {
1318 ; CHECK-LABEL: @test_gep_bitcast_malloc(
1319 ; CHECK-NEXT:  entry:
1320 ; CHECK-NEXT:    [[CALL:%.*]] = call noalias dereferenceable_or_null(16) ptr @malloc(i64 16)
1321 ; CHECK-NEXT:    [[G3:%.*]] = getelementptr [[STRUCT_A:%.*]], ptr [[CALL]], i64 0, i32 2
1322 ; CHECK-NEXT:    [[A_C:%.*]] = load i32, ptr [[G3]], align 4
1323 ; CHECK-NEXT:    ret i32 [[A_C]]
1325 entry:
1326   %call = call noalias ptr @malloc(i64 16) #2
1327   %g3 = getelementptr %struct.A, ptr %call, i32 0, i32 2
1328   %a_c = load i32, ptr %g3, align 4
1329   ret i32 %a_c
1332 define ptr @gep_of_gep_multiuse_const_and_const(ptr %p, i64 %idx) {
1333 ; CHECK-LABEL: @gep_of_gep_multiuse_const_and_const(
1334 ; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr { i32, i32 }, ptr [[P:%.*]], i64 1
1335 ; CHECK-NEXT:    call void @use(ptr [[GEP1]])
1336 ; CHECK-NEXT:    [[GEP2:%.*]] = getelementptr { i32, i32 }, ptr [[P]], i64 1, i32 1
1337 ; CHECK-NEXT:    ret ptr [[GEP2]]
1339   %gep1 = getelementptr { i32, i32 }, ptr %p, i64 1
1340   call void @use(ptr %gep1)
1341   %gep2 = getelementptr { i32, i32 }, ptr %gep1, i64 0, i32 1
1342   ret ptr %gep2
1345 define ptr @gep_of_gep_multiuse_var_and_const(ptr %p, i64 %idx) {
1346 ; CHECK-LABEL: @gep_of_gep_multiuse_var_and_const(
1347 ; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr { i32, i32 }, ptr [[P:%.*]], i64 [[IDX:%.*]]
1348 ; CHECK-NEXT:    call void @use(ptr [[GEP1]])
1349 ; CHECK-NEXT:    [[GEP2:%.*]] = getelementptr { i32, i32 }, ptr [[P]], i64 [[IDX]], i32 1
1350 ; CHECK-NEXT:    ret ptr [[GEP2]]
1352   %gep1 = getelementptr { i32, i32 }, ptr %p, i64 %idx
1353   call void @use(ptr %gep1)
1354   %gep2 = getelementptr { i32, i32 }, ptr %gep1, i64 0, i32 1
1355   ret ptr %gep2
1358 define ptr @gep_of_gep_multiuse_var_and_var(ptr %p, i64 %idx, i64 %idx2) {
1359 ; CHECK-LABEL: @gep_of_gep_multiuse_var_and_var(
1360 ; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr [4 x i32], ptr [[P:%.*]], i64 [[IDX:%.*]]
1361 ; CHECK-NEXT:    call void @use(ptr [[GEP1]])
1362 ; CHECK-NEXT:    [[GEP2:%.*]] = getelementptr [4 x i32], ptr [[P]], i64 [[IDX]], i64 [[IDX2:%.*]]
1363 ; CHECK-NEXT:    ret ptr [[GEP2]]
1365   %gep1 = getelementptr [4 x i32], ptr %p, i64 %idx
1366   call void @use(ptr %gep1)
1367   %gep2 = getelementptr [4 x i32], ptr %gep1, i64 0, i64 %idx2
1368   ret ptr %gep2
1371 @g_i32_di = global i32 0
1372 @g_i32_e = external global i32
1373 @g_i32_ew = extern_weak global i32
1374 @g_0xi8_e = external global [0 x i8]
1376 define ptr @const_gep_global_di_i8_smaller() {
1377 ; CHECK-LABEL: @const_gep_global_di_i8_smaller(
1378 ; CHECK-NEXT:    ret ptr getelementptr (i8, ptr @g_i32_di, i64 3)
1380   ret ptr getelementptr (i8, ptr @g_i32_di, i64 3)
1383 define ptr @const_gep_global_di_i8_exact() {
1384 ; CHECK-LABEL: @const_gep_global_di_i8_exact(
1385 ; CHECK-NEXT:    ret ptr getelementptr inbounds (i32, ptr @g_i32_di, i64 1)
1387   ret ptr getelementptr (i8, ptr @g_i32_di, i64 4)
1390 define ptr @const_gep_global_di_i8_larger() {
1391 ; CHECK-LABEL: @const_gep_global_di_i8_larger(
1392 ; CHECK-NEXT:    ret ptr getelementptr (i8, ptr @g_i32_di, i64 5)
1394   ret ptr getelementptr (i8, ptr @g_i32_di, i64 5)
1397 define ptr @const_gep_global_di_i64_larger() {
1398 ; CHECK-LABEL: @const_gep_global_di_i64_larger(
1399 ; CHECK-NEXT:    ret ptr getelementptr (i32, ptr @g_i32_di, i64 2)
1401   ret ptr getelementptr (i64, ptr @g_i32_di, i64 1)
1404 define ptr @const_gep_global_e_smaller() {
1405 ; CHECK-LABEL: @const_gep_global_e_smaller(
1406 ; CHECK-NEXT:    ret ptr getelementptr (i8, ptr @g_i32_e, i64 3)
1408   ret ptr getelementptr (i8, ptr @g_i32_e, i64 3)
1411 define ptr @const_gep_global_e_exact() {
1412 ; CHECK-LABEL: @const_gep_global_e_exact(
1413 ; CHECK-NEXT:    ret ptr getelementptr inbounds (i32, ptr @g_i32_e, i64 1)
1415   ret ptr getelementptr (i8, ptr @g_i32_e, i64 4)
1418 define ptr @const_gep_global_e_larger() {
1419 ; CHECK-LABEL: @const_gep_global_e_larger(
1420 ; CHECK-NEXT:    ret ptr getelementptr (i8, ptr @g_i32_e, i64 5)
1422   ret ptr getelementptr (i8, ptr @g_i32_e, i64 5)
1425 define ptr @const_gep_global_ew_smaller() {
1426 ; CHECK-LABEL: @const_gep_global_ew_smaller(
1427 ; CHECK-NEXT:    ret ptr getelementptr (i8, ptr @g_i32_ew, i64 3)
1429   ret ptr getelementptr (i8, ptr @g_i32_ew, i64 3)
1432 define ptr @const_gep_global_ew_exact() {
1433 ; CHECK-LABEL: @const_gep_global_ew_exact(
1434 ; CHECK-NEXT:    ret ptr getelementptr (i32, ptr @g_i32_ew, i64 1)
1436   ret ptr getelementptr (i8, ptr @g_i32_ew, i64 4)
1439 define ptr @const_gep_global_ew_larger() {
1440 ; CHECK-LABEL: @const_gep_global_ew_larger(
1441 ; CHECK-NEXT:    ret ptr getelementptr (i8, ptr @g_i32_ew, i64 5)
1443   ret ptr getelementptr (i8, ptr @g_i32_ew, i64 5)
1446 define ptr @const_gep_0xi8_global() {
1447 ; CHECK-LABEL: @const_gep_0xi8_global(
1448 ; CHECK-NEXT:    ret ptr getelementptr ([0 x i8], ptr @g_0xi8_e, i64 0, i64 10)
1450   ret ptr getelementptr ([0 x i8], ptr @g_0xi8_e, i64 0, i64 10)
1453 define ptr @const_gep_chain(ptr %p, i64 %a) {
1454 ; CHECK-LABEL: @const_gep_chain(
1455 ; CHECK-NEXT:    [[P1:%.*]] = getelementptr inbounds i8, ptr [[P:%.*]], i64 [[A:%.*]]
1456 ; CHECK-NEXT:    [[P4:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 6
1457 ; CHECK-NEXT:    ret ptr [[P4]]
1459   %p1 = getelementptr inbounds i8, ptr %p, i64 %a
1460   %p2 = getelementptr inbounds i8, ptr %p1, i64 1
1461   %p3 = getelementptr inbounds i8, ptr %p2, i64 2
1462   %p4 = getelementptr inbounds i8, ptr %p3, i64 3
1463   ret ptr %p4
1466 define ptr @gep_sdiv(ptr %p, i64 %off) {
1467 ; CHECK-LABEL: @gep_sdiv(
1468 ; CHECK-NEXT:    [[PTR:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[OFF:%.*]]
1469 ; CHECK-NEXT:    ret ptr [[PTR]]
1471   %index = sdiv exact i64 %off, 7
1472   %ptr = getelementptr %struct.C, ptr %p, i64 %index
1473   ret ptr %ptr
1476 define <2 x ptr> @gep_sdiv_vec(<2 x ptr> %p, <2 x i64> %off) {
1477 ; CHECK-LABEL: @gep_sdiv_vec(
1478 ; CHECK-NEXT:    [[PTR:%.*]] = getelementptr i8, <2 x ptr> [[P:%.*]], <2 x i64> [[OFF:%.*]]
1479 ; CHECK-NEXT:    ret <2 x ptr> [[PTR]]
1481   %index = sdiv exact <2 x i64> %off, <i64 7, i64 7>
1482   %ptr = getelementptr %struct.C, <2 x ptr> %p, <2 x i64> %index
1483   ret <2 x ptr> %ptr
1486 define ptr @gep_sdiv_inbounds(ptr %p, i64 %off) {
1487 ; CHECK-LABEL: @gep_sdiv_inbounds(
1488 ; CHECK-NEXT:    [[PTR:%.*]] = getelementptr inbounds i8, ptr [[P:%.*]], i64 [[OFF:%.*]]
1489 ; CHECK-NEXT:    ret ptr [[PTR]]
1491   %index = sdiv exact i64 %off, 7
1492   %ptr = getelementptr inbounds %struct.C, ptr %p, i64 %index
1493   ret ptr %ptr
1496 define ptr @gep_ashr(ptr %p, i64 %off) {
1497 ; CHECK-LABEL: @gep_ashr(
1498 ; CHECK-NEXT:    [[PTR:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[OFF:%.*]]
1499 ; CHECK-NEXT:    ret ptr [[PTR]]
1501   %index = ashr exact i64 %off, 2
1502   %ptr = getelementptr i32, ptr %p, i64 %index
1503   ret ptr %ptr
1506 ; Negative tests
1508 define ptr @gep_i8(ptr %p, i64 %off) {
1509 ; CHECK-LABEL: @gep_i8(
1510 ; CHECK-NEXT:    [[PTR:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[OFF:%.*]]
1511 ; CHECK-NEXT:    ret ptr [[PTR]]
1513   %ptr = getelementptr i8, ptr %p, i64 %off
1514   ret ptr %ptr
1517 define ptr @gep_sdiv_mismatched_size(ptr %p, i64 %off) {
1518 ; CHECK-LABEL: @gep_sdiv_mismatched_size(
1519 ; CHECK-NEXT:    [[INDEX:%.*]] = sdiv exact i64 [[OFF:%.*]], 20
1520 ; CHECK-NEXT:    [[PTR:%.*]] = getelementptr [[STRUCT_C:%.*]], ptr [[P:%.*]], i64 [[INDEX]]
1521 ; CHECK-NEXT:    ret ptr [[PTR]]
1523   %index = sdiv exact i64 %off, 20
1524   %ptr = getelementptr %struct.C, ptr %p, i64 %index
1525   ret ptr %ptr
1528 define ptr @gep_sdiv_without_exact(ptr %p, i64 %off) {
1529 ; CHECK-LABEL: @gep_sdiv_without_exact(
1530 ; CHECK-NEXT:    [[INDEX:%.*]] = sdiv i64 [[OFF:%.*]], 7
1531 ; CHECK-NEXT:    [[PTR:%.*]] = getelementptr [[STRUCT_C:%.*]], ptr [[P:%.*]], i64 [[INDEX]]
1532 ; CHECK-NEXT:    ret ptr [[PTR]]
1534   %index = sdiv i64 %off, 7
1535   %ptr = getelementptr %struct.C, ptr %p, i64 %index
1536   ret ptr %ptr
1539 define ptr @gep_ashr_without_exact(ptr %p, i64 %off) {
1540 ; CHECK-LABEL: @gep_ashr_without_exact(
1541 ; CHECK-NEXT:    [[INDEX:%.*]] = ashr i64 [[OFF:%.*]], 2
1542 ; CHECK-NEXT:    [[PTR:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[INDEX]]
1543 ; CHECK-NEXT:    ret ptr [[PTR]]
1545   %index = ashr i64 %off, 2
1546   %ptr = getelementptr i32, ptr %p, i64 %index
1547   ret ptr %ptr
1550 define i1 @test_only_used_by_icmp(ptr %a, ptr %b, ptr %c) {
1551 ; CHECK-LABEL: @test_only_used_by_icmp(
1552 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[B:%.*]], [[C:%.*]]
1553 ; CHECK-NEXT:    ret i1 [[CMP]]
1555   %pa = ptrtoint ptr %a to i64
1556   %pb = ptrtoint ptr %b to i64
1557   %sub = sub i64 %pb, %pa
1558   %gep = getelementptr i8, ptr %a, i64 %sub
1559   %cmp = icmp eq ptr %gep, %c
1560   ret i1 %cmp
1563 define i64 @test_only_used_by_ptrtoint(ptr %a, ptr %b) {
1564 ; CHECK-LABEL: @test_only_used_by_ptrtoint(
1565 ; CHECK-NEXT:    [[VAL:%.*]] = ptrtoint ptr [[B:%.*]] to i64
1566 ; CHECK-NEXT:    ret i64 [[VAL]]
1568   %pa = ptrtoint ptr %a to i64
1569   %pb = ptrtoint ptr %b to i64
1570   %sub = sub i64 %pb, %pa
1571   %gep = getelementptr i8, ptr %a, i64 %sub
1572   %val = ptrtoint ptr %gep to i64
1573   ret i64 %val
1576 define i64 @test_used_by_both(ptr %a, ptr %b, ptr %c) {
1577 ; CHECK-LABEL: @test_used_by_both(
1578 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[B:%.*]], [[C:%.*]]
1579 ; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
1580 ; CHECK:       if.then:
1581 ; CHECK-NEXT:    [[VAL:%.*]] = ptrtoint ptr [[B]] to i64
1582 ; CHECK-NEXT:    ret i64 [[VAL]]
1583 ; CHECK:       if.else:
1584 ; CHECK-NEXT:    ret i64 0
1586   %pa = ptrtoint ptr %a to i64
1587   %pb = ptrtoint ptr %b to i64
1588   %sub = sub i64 %pb, %pa
1589   %gep = getelementptr i8, ptr %a, i64 %sub
1590   %cmp = icmp eq ptr %gep, %c
1591   br i1 %cmp, label %if.then, label %if.else
1592 if.then:
1593   %val = ptrtoint ptr %gep to i64
1594   ret i64 %val
1595 if.else:
1596   ret i64 0
1599 ; Negative tests
1601 define i64 @test_used_by_both_invalid(ptr %a, ptr %b, ptr %c) {
1602 ; CHECK-LABEL: @test_used_by_both_invalid(
1603 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[B:%.*]], [[C:%.*]]
1604 ; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
1605 ; CHECK:       if.then:
1606 ; CHECK-NEXT:    [[PB:%.*]] = ptrtoint ptr [[B]] to i64
1607 ; CHECK-NEXT:    [[PA:%.*]] = ptrtoint ptr [[A:%.*]] to i64
1608 ; CHECK-NEXT:    [[SUB:%.*]] = sub i64 [[PB]], [[PA]]
1609 ; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i8, ptr [[A]], i64 [[SUB]]
1610 ; CHECK-NEXT:    [[VAL:%.*]] = load i64, ptr [[GEP]], align 8
1611 ; CHECK-NEXT:    ret i64 [[VAL]]
1612 ; CHECK:       if.else:
1613 ; CHECK-NEXT:    ret i64 0
1615   %pa = ptrtoint ptr %a to i64
1616   %pb = ptrtoint ptr %b to i64
1617   %sub = sub i64 %pb, %pa
1618   %gep = getelementptr i8, ptr %a, i64 %sub
1619   %cmp = icmp eq ptr %gep, %c
1620   br i1 %cmp, label %if.then, label %if.else
1621 if.then:
1622   %val = load i64, ptr %gep, align 8
1623   ret i64 %val
1624 if.else:
1625   ret i64 0
1628 !0 = !{!"branch_weights", i32 2, i32 10}