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:%.*]]
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
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
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
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
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
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
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
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
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
135 define ptr @test8(ptr %X) {
136 ;; Fold into the cast.
137 ; CHECK-LABEL: @test8(
138 ; CHECK-NEXT: 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
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
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
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
190 define i32 @test12(ptr %a) {
191 ; CHECK-LABEL: @test12(
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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)
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]
558 define void @test25() {
559 ; CHECK-LABEL: @test25(
561 ; CHECK-NEXT: unreachable
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 )
575 declare void @foo25(i32, i64)
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
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(
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
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 )
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(
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:%.*]]
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]]
637 ; CHECK-NEXT: ret i32 0
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
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
659 declare i32 @puts(ptr)
661 declare i32 @printf(ptr, ...)
667 %T = type <{ i64, i64, i64 }>
668 define i32 @test29(ptr %start, i32 %X) nounwind {
669 ; CHECK-LABEL: @test29(
671 ; CHECK-NEXT: store i1 true, ptr poison, align 1
672 ; CHECK-NEXT: br i1 poison, label [[IF_THEN216:%.*]], label [[IF_END363:%.*]]
674 ; CHECK-NEXT: ret i32 1
676 ; CHECK-NEXT: ret i32 0
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
696 define i32 @test30(i32 %m, i32 %n) nounwind {
697 ; CHECK-LABEL: @test30(
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]]
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
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
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
745 %F = getelementptr [4 x ptr], ptr %A, i32 0, i32 2
746 %G = load ptr, ptr %F
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
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(
806 ; CHECK-NEXT: [[C_CAST:%.*]] = inttoptr i64 [[V:%.*]] to ptr
807 ; CHECK-NEXT: ret ptr [[C_CAST]]
810 %A = alloca %T2, align 8
813 %C = load ptr, ptr %A, align 8
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
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)
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
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(
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
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
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)
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
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
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]]
946 %t = getelementptr i8, ptr addrspace(1) %arr, i16 %V
947 %x = load i8, ptr addrspace(1) %t
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]]
960 %t = getelementptr i64, ptr %arr, i64 %V
961 %x = load i64, ptr %t
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)
976 %t = getelementptr i64, ptr addrspace(3) %cast, i64 %V
977 %x = load i64, ptr addrspace(3) %t
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]]
990 %t = getelementptr i8, ptr %arr, i64 %V
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]]
1003 %t = getelementptr i64, ptr addrspace(1) %arr, i16 %V
1004 %x = load i64, ptr addrspace(1) %t
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]]
1016 %t = getelementptr i8, ptr addrspace(1) %arr, i16 %V
1017 %x = load i8, ptr addrspace(1) %t
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
1029 %gep2 = getelementptr i8, ptr %gep, i64 %np
1030 %ret = ptrtoint ptr %gep2 to i64
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
1042 %gep2 = getelementptr i8, ptr addrspace(1) %gep, i16 %np
1043 %ret = ptrtoint ptr addrspace(1) %gep2 to i16
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
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
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
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
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)
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
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
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
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
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>
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
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
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
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
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
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
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
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
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
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
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)
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]]
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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:%.*]]
1581 ; CHECK-NEXT: [[VAL:%.*]] = ptrtoint ptr [[B]] to i64
1582 ; CHECK-NEXT: ret i64 [[VAL]]
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
1593 %val = ptrtoint ptr %gep to i64
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:%.*]]
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]]
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
1622 %val = load i64, ptr %gep, align 8
1628 !0 = !{!"branch_weights", i32 2, i32 10}