[libc++] Fix malformed CSV entry for C++26 LWG issue
[llvm-project.git] / llvm / test / Transforms / InstCombine / ptrtoint-nullgep.ll
blob9d6f0abce84c7c5aed4b43d74f92a859b7f67a42
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
2 ; Check that we can fold operations with (gep null) inputs.
3 ; Note: the LLParser already does some constant folding, check that output first:
4 ; RUN: opt -passes=verify -S < %s | FileCheck %s --check-prefixes=ALL,LLPARSER
5 ; We should be able to fold almost everything in InstSimplify other than the final test which requries InstCombine
6 ; RUN: opt -S -passes=instsimplify < %s | FileCheck %s --allow-unused-prefixes --check-prefixes=ALL,CHECK,INTEGRAL,INSTSIMPLIFY,INTEGRAL-INSTSIMPLIFY
7 ; RUN: opt -S -passes=instcombine < %s | FileCheck %s --allow-unused-prefixes --check-prefixes=ALL,CHECK,INTEGRAL,INSTCOMBINE,INTEGRAL-INSTCOMBINE
8 ; Non-integral pointers limit certain transformations on pointers:
9 ; RUN: sed -e 's/p:64:64:64:64/p:64:64:64:64-ni:1/g' %s | opt -S -passes=instsimplify | \
10 ; RUN:   FileCheck %s --allow-unused-prefixes --check-prefixes=ALL,CHECK,NONINTEGRAL,INSTSIMPLIFY,NONINTEGRAL-INSTSIMPLIFY
11 ; RUN: sed -e 's/p:64:64:64:64/p:64:64:64:64-ni:1/g' %s | opt -S -passes=instcombine | \
12 ; RUN:   FileCheck %s --allow-unused-prefixes --check-prefixes=ALL,CHECK,NONINTEGRAL,INSTCOMBINE,NONINTEGRAL-INSTCOMBINE
13 target datalayout = "p:64:64:64:64"
15 declare void @use_i64(i64)
16 declare void @use_ptr(ptr addrspace(1))
18 define i64 @constant_fold_ptrtoint_gep_zero() {
19 ; ALL-LABEL: define {{[^@]+}}@constant_fold_ptrtoint_gep_zero() {
20 ; ALL-NEXT:    ret i64 0
22   ret i64 ptrtoint (ptr addrspace(1) null to i64)
24 define i64 @constant_fold_ptrtoint_gep_nonzero() {
25 ; LLPARSER-LABEL: define {{[^@]+}}@constant_fold_ptrtoint_gep_nonzero() {
26 ; LLPARSER-NEXT:    ret i64 ptrtoint (ptr addrspace(1) getelementptr (i32, ptr addrspace(1) null, i64 1234) to i64)
28 ; INSTSIMPLIFY-LABEL: define {{[^@]+}}@constant_fold_ptrtoint_gep_nonzero() {
29 ; INSTSIMPLIFY-NEXT:    ret i64 ptrtoint (ptr addrspace(1) getelementptr (i32, ptr addrspace(1) null, i64 1234) to i64)
31 ; INSTCOMBINE-LABEL: define {{[^@]+}}@constant_fold_ptrtoint_gep_nonzero() {
32 ; INSTCOMBINE-NEXT:    ret i64 4936
34   ret i64 ptrtoint (ptr addrspace(1) getelementptr (i32, ptr addrspace(1) null, i64 1234) to i64)
37 define i64 @constant_fold_ptrtoint_gep_zero_inbounds() {
38 ; ALL-LABEL: define {{[^@]+}}@constant_fold_ptrtoint_gep_zero_inbounds() {
39 ; ALL-NEXT:    ret i64 0
41   ret i64 ptrtoint (ptr addrspace(1) null to i64)
44 ; In theory we could fold this to poison/null, but that would break offsetof
45 ; implementations that don't use __builtin_offsetof.
46 ; TODO: should Clang special case ((INTEGER)&((TYPE *)0)->MEMBER) to emit a non-inbounds GEP?
47 define i64 @constant_fold_ptrtoint_gep_nonzero_inbounds() {
48 ; LLPARSER-LABEL: define {{[^@]+}}@constant_fold_ptrtoint_gep_nonzero_inbounds() {
49 ; LLPARSER-NEXT:    ret i64 ptrtoint (ptr addrspace(1) getelementptr inbounds (i32, ptr addrspace(1) null, i64 1234) to i64)
51 ; INSTSIMPLIFY-LABEL: define {{[^@]+}}@constant_fold_ptrtoint_gep_nonzero_inbounds() {
52 ; INSTSIMPLIFY-NEXT:    ret i64 ptrtoint (ptr addrspace(1) getelementptr inbounds (i32, ptr addrspace(1) null, i64 1234) to i64)
54 ; INSTCOMBINE-LABEL: define {{[^@]+}}@constant_fold_ptrtoint_gep_nonzero_inbounds() {
55 ; INSTCOMBINE-NEXT:    ret i64 4936
57   ret i64 ptrtoint (ptr addrspace(1) getelementptr inbounds (i32, ptr addrspace(1) null, i64 1234) to i64)
60 ; Check all combinations of inbounds+non-inbounds GEP with the outer GEP having a non-zero offset
61 define void @constant_fold_ptrtoint_of_gep_of_nullgep() {
62 ; LLPARSER-LABEL: define {{[^@]+}}@constant_fold_ptrtoint_of_gep_of_nullgep() {
63 ; LLPARSER-NEXT:    call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) null, i64 1234) to i64))
64 ; LLPARSER-NEXT:    call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) null, i64 1234) to i64))
65 ; LLPARSER-NEXT:    call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) null, i64 1234) to i64))
66 ; LLPARSER-NEXT:    call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) null, i64 1234) to i64))
67 ; LLPARSER-NEXT:    call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) null, i64 1234) to i64))
68 ; LLPARSER-NEXT:    call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) null, i64 1234) to i64))
69 ; LLPARSER-NEXT:    call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) null, i64 1234) to i64))
70 ; LLPARSER-NEXT:    call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) null, i64 1234) to i64))
71 ; LLPARSER-NEXT:    call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) null, i64 -1), i64 1) to i64))
72 ; LLPARSER-NEXT:    call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) null, i64 -1), i64 1) to i64))
73 ; LLPARSER-NEXT:    call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) getelementptr (i8, ptr addrspace(1) null, i64 -1), i64 1) to i64))
74 ; LLPARSER-NEXT:    call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) getelementptr (i8, ptr addrspace(1) null, i64 -1), i64 1) to i64))
75 ; LLPARSER-NEXT:    ret void
77 ; INSTSIMPLIFY-LABEL: define {{[^@]+}}@constant_fold_ptrtoint_of_gep_of_nullgep() {
78 ; INSTSIMPLIFY-NEXT:    call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) null, i64 1234) to i64))
79 ; INSTSIMPLIFY-NEXT:    call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) null, i64 1234) to i64))
80 ; INSTSIMPLIFY-NEXT:    call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) null, i64 1234) to i64))
81 ; INSTSIMPLIFY-NEXT:    call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) null, i64 1234) to i64))
82 ; INSTSIMPLIFY-NEXT:    call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) null, i64 1234) to i64))
83 ; INSTSIMPLIFY-NEXT:    call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) null, i64 1234) to i64))
84 ; INSTSIMPLIFY-NEXT:    call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) null, i64 1234) to i64))
85 ; INSTSIMPLIFY-NEXT:    call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) null, i64 1234) to i64))
86 ; INSTSIMPLIFY-NEXT:    call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) null, i64 -1), i64 1) to i64))
87 ; INSTSIMPLIFY-NEXT:    call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) null, i64 -1), i64 1) to i64))
88 ; INSTSIMPLIFY-NEXT:    call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) getelementptr (i8, ptr addrspace(1) null, i64 -1), i64 1) to i64))
89 ; INSTSIMPLIFY-NEXT:    call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) getelementptr (i8, ptr addrspace(1) null, i64 -1), i64 1) to i64))
90 ; INSTSIMPLIFY-NEXT:    ret void
92 ; INSTCOMBINE-LABEL: define {{[^@]+}}@constant_fold_ptrtoint_of_gep_of_nullgep() {
93 ; INSTCOMBINE-NEXT:    call void @use_i64(i64 1234)
94 ; INSTCOMBINE-NEXT:    call void @use_i64(i64 1234)
95 ; INSTCOMBINE-NEXT:    call void @use_i64(i64 1234)
96 ; INSTCOMBINE-NEXT:    call void @use_i64(i64 1234)
97 ; INSTCOMBINE-NEXT:    call void @use_i64(i64 1234)
98 ; INSTCOMBINE-NEXT:    call void @use_i64(i64 1234)
99 ; INSTCOMBINE-NEXT:    call void @use_i64(i64 1234)
100 ; INSTCOMBINE-NEXT:    call void @use_i64(i64 1234)
101 ; INSTCOMBINE-NEXT:    call void @use_i64(i64 0)
102 ; INSTCOMBINE-NEXT:    call void @use_i64(i64 0)
103 ; INSTCOMBINE-NEXT:    call void @use_i64(i64 0)
104 ; INSTCOMBINE-NEXT:    call void @use_i64(i64 0)
105 ; INSTCOMBINE-NEXT:    ret void
107   call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) null, i64 1234) to i64))
108   call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) null, i64 1234) to i64))
109   call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) null, i64 1234) to i64))
110   call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) null, i64 1234) to i64))
111   ; Same again but this time with the inner GEP using the non-zero offset
112   call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) null, i64 1234), i64 0) to i64))
113   call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) null, i64 1234), i64 0) to i64))
114   call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) getelementptr (i8, ptr addrspace(1) null, i64 1234), i64 0) to i64))
115   call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) getelementptr (i8, ptr addrspace(1) null, i64 1234), i64 0) to i64))
116   ; And finally with two constants that sum to zero
117   call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) null, i64 -1), i64 1) to i64))
118   call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) null, i64 -1), i64 1) to i64))
119   call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) getelementptr (i8, ptr addrspace(1) null, i64 -1), i64 1) to i64))
120   call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) getelementptr (i8, ptr addrspace(1) null, i64 -1), i64 1) to i64))
121   ret void
124 ; Another set of tests for instructions instead of constants
125 define i64 @fold_ptrtoint_nullgep_zero() {
126 ; LLPARSER-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_zero() {
127 ; LLPARSER-NEXT:    [[OFFSET:%.*]] = add i64 0, 0
128 ; LLPARSER-NEXT:    [[PTR:%.*]] = getelementptr i8, ptr addrspace(1) null, i64 [[OFFSET]]
129 ; LLPARSER-NEXT:    [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64
130 ; LLPARSER-NEXT:    ret i64 [[RET]]
132 ; CHECK-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_zero() {
133 ; CHECK-NEXT:    ret i64 0
135   %offset = add i64 0, 0
136   %ptr = getelementptr i8, ptr addrspace(1) null, i64 %offset
137   %ret = ptrtoint ptr addrspace(1) %ptr to i64
138   ret i64 %ret
141 define i64 @fold_ptrtoint_nullgep_zero_inbounds() {
142 ; LLPARSER-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_zero_inbounds() {
143 ; LLPARSER-NEXT:    [[OFFSET:%.*]] = add i64 0, 0
144 ; LLPARSER-NEXT:    [[PTR:%.*]] = getelementptr inbounds i8, ptr addrspace(1) null, i64 [[OFFSET]]
145 ; LLPARSER-NEXT:    [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64
146 ; LLPARSER-NEXT:    ret i64 [[RET]]
148 ; CHECK-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_zero_inbounds() {
149 ; CHECK-NEXT:    ret i64 0
151   %offset = add i64 0, 0
152   %ptr = getelementptr inbounds i8, ptr addrspace(1) null, i64 %offset
153   %ret = ptrtoint ptr addrspace(1) %ptr to i64
154   ret i64 %ret
157 define i64 @fold_ptrtoint_nullgep_nonzero() {
158 ; LLPARSER-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_nonzero() {
159 ; LLPARSER-NEXT:    [[OFFSET:%.*]] = add i64 1234, 0
160 ; LLPARSER-NEXT:    [[PTR:%.*]] = getelementptr i8, ptr addrspace(1) null, i64 [[OFFSET]]
161 ; LLPARSER-NEXT:    [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64
162 ; LLPARSER-NEXT:    ret i64 [[RET]]
164 ; CHECK-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_nonzero() {
165 ; CHECK-NEXT:    ret i64 1234
167   %offset = add i64 1234, 0
168   %ptr = getelementptr i8, ptr addrspace(1) null, i64 %offset
169   %ret = ptrtoint ptr addrspace(1) %ptr to i64
170   ret i64 %ret
173 ; Inbounds constant null-GEP with non-zero could be constant-folded to null/poison,
174 ; but folding it to the value makes ((INTEGER)&((TYPE *)0)->MEMBER) work.
175 define i64 @fold_ptrtoint_nullgep_nonzero_inbounds() {
176 ; LLPARSER-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_nonzero_inbounds() {
177 ; LLPARSER-NEXT:    [[OFFSET:%.*]] = add i64 1234, 0
178 ; LLPARSER-NEXT:    [[PTR:%.*]] = getelementptr inbounds i8, ptr addrspace(1) null, i64 [[OFFSET]]
179 ; LLPARSER-NEXT:    [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64
180 ; LLPARSER-NEXT:    ret i64 [[RET]]
182 ; CHECK-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_nonzero_inbounds() {
183 ; CHECK-NEXT:    ret i64 1234
185   %offset = add i64 1234, 0
186   %ptr = getelementptr inbounds i8, ptr addrspace(1) null, i64 %offset
187   %ret = ptrtoint ptr addrspace(1) %ptr to i64
188   ret i64 %ret
191 ; We should be able to fold ptrtoint(gep null, x) to x
192 define i64 @fold_ptrtoint_nullgep_variable(i64 %val) {
193 ; LLPARSER-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_variable
194 ; LLPARSER-SAME: (i64 [[VAL:%.*]]) {
195 ; LLPARSER-NEXT:    [[PTR:%.*]] = getelementptr i8, ptr addrspace(1) null, i64 [[VAL]]
196 ; LLPARSER-NEXT:    [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64
197 ; LLPARSER-NEXT:    ret i64 [[RET]]
199 ; INSTSIMPLIFY-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_variable
200 ; INSTSIMPLIFY-SAME: (i64 [[VAL:%.*]]) {
201 ; INSTSIMPLIFY-NEXT:    [[PTR:%.*]] = getelementptr i8, ptr addrspace(1) null, i64 [[VAL]]
202 ; INSTSIMPLIFY-NEXT:    [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64
203 ; INSTSIMPLIFY-NEXT:    ret i64 [[RET]]
205 ; INSTCOMBINE-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_variable
206 ; INSTCOMBINE-SAME: (i64 [[VAL:%.*]]) {
207 ; INSTCOMBINE-NEXT:    ret i64 [[VAL]]
209   %ptr = getelementptr i8, ptr addrspace(1) null, i64 %val
210   %ret = ptrtoint ptr addrspace(1) %ptr to i64
211   ret i64 %ret
214 ; Inbounds null-GEP with non-zero offset could be folded to poison/null.
215 define i64 @fold_ptrtoint_nullgep_variable_known_nonzero(i64 %val) {
216 ; LLPARSER-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_variable_known_nonzero
217 ; LLPARSER-SAME: (i64 [[VAL:%.*]]) {
218 ; LLPARSER-NEXT:    [[NON_ZERO_OFFSET:%.*]] = or i64 [[VAL]], 1
219 ; LLPARSER-NEXT:    [[PTR:%.*]] = getelementptr i8, ptr addrspace(1) null, i64 [[NON_ZERO_OFFSET]]
220 ; LLPARSER-NEXT:    [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64
221 ; LLPARSER-NEXT:    ret i64 [[RET]]
223 ; INSTSIMPLIFY-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_variable_known_nonzero
224 ; INSTSIMPLIFY-SAME: (i64 [[VAL:%.*]]) {
225 ; INSTSIMPLIFY-NEXT:    [[NON_ZERO_OFFSET:%.*]] = or i64 [[VAL]], 1
226 ; INSTSIMPLIFY-NEXT:    [[PTR:%.*]] = getelementptr i8, ptr addrspace(1) null, i64 [[NON_ZERO_OFFSET]]
227 ; INSTSIMPLIFY-NEXT:    [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64
228 ; INSTSIMPLIFY-NEXT:    ret i64 [[RET]]
230 ; INSTCOMBINE-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_variable_known_nonzero
231 ; INSTCOMBINE-SAME: (i64 [[VAL:%.*]]) {
232 ; INSTCOMBINE-NEXT:    [[NON_ZERO_OFFSET:%.*]] = or i64 [[VAL]], 1
233 ; INSTCOMBINE-NEXT:    ret i64 [[NON_ZERO_OFFSET]]
235   %non_zero_offset = or i64 %val, 1
236   %ptr = getelementptr i8, ptr addrspace(1) null, i64 %non_zero_offset
237   %ret = ptrtoint ptr addrspace(1) %ptr to i64
238   ret i64 %ret
241 ; This is only valid if %val is zero so we could fold the result to 0.
242 define i64 @fold_ptrtoint_nullgep_variable_inbounds(i64 %val) {
243 ; LLPARSER-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_variable_inbounds
244 ; LLPARSER-SAME: (i64 [[VAL:%.*]]) {
245 ; LLPARSER-NEXT:    [[PTR:%.*]] = getelementptr inbounds i8, ptr addrspace(1) null, i64 [[VAL]]
246 ; LLPARSER-NEXT:    [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64
247 ; LLPARSER-NEXT:    ret i64 [[RET]]
249 ; INSTSIMPLIFY-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_variable_inbounds
250 ; INSTSIMPLIFY-SAME: (i64 [[VAL:%.*]]) {
251 ; INSTSIMPLIFY-NEXT:    [[PTR:%.*]] = getelementptr inbounds i8, ptr addrspace(1) null, i64 [[VAL]]
252 ; INSTSIMPLIFY-NEXT:    [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64
253 ; INSTSIMPLIFY-NEXT:    ret i64 [[RET]]
255 ; INSTCOMBINE-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_variable_inbounds
256 ; INSTCOMBINE-SAME: (i64 [[VAL:%.*]]) {
257 ; INSTCOMBINE-NEXT:    ret i64 [[VAL]]
259   %ptr = getelementptr inbounds i8, ptr addrspace(1) null, i64 %val
260   %ret = ptrtoint ptr addrspace(1) %ptr to i64
261   ret i64 %ret
264 ; A non-constant but known-non-zero GEP could be folded to poison/null
265 define i64 @fold_ptrtoint_nullgep_variable_known_nonzero_inbounds(i64 %val) {
266 ; LLPARSER-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_variable_known_nonzero_inbounds
267 ; LLPARSER-SAME: (i64 [[VAL:%.*]]) {
268 ; LLPARSER-NEXT:    [[NON_ZERO_OFFSET:%.*]] = or i64 [[VAL]], 1
269 ; LLPARSER-NEXT:    [[PTR:%.*]] = getelementptr inbounds i8, ptr addrspace(1) null, i64 [[NON_ZERO_OFFSET]]
270 ; LLPARSER-NEXT:    [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64
271 ; LLPARSER-NEXT:    ret i64 [[RET]]
273 ; INSTSIMPLIFY-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_variable_known_nonzero_inbounds
274 ; INSTSIMPLIFY-SAME: (i64 [[VAL:%.*]]) {
275 ; INSTSIMPLIFY-NEXT:    [[NON_ZERO_OFFSET:%.*]] = or i64 [[VAL]], 1
276 ; INSTSIMPLIFY-NEXT:    [[PTR:%.*]] = getelementptr inbounds i8, ptr addrspace(1) null, i64 [[NON_ZERO_OFFSET]]
277 ; INSTSIMPLIFY-NEXT:    [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64
278 ; INSTSIMPLIFY-NEXT:    ret i64 [[RET]]
280 ; INSTCOMBINE-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_variable_known_nonzero_inbounds
281 ; INSTCOMBINE-SAME: (i64 [[VAL:%.*]]) {
282 ; INSTCOMBINE-NEXT:    [[NON_ZERO_OFFSET:%.*]] = or i64 [[VAL]], 1
283 ; INSTCOMBINE-NEXT:    ret i64 [[NON_ZERO_OFFSET]]
285   %non_zero_offset = or i64 %val, 1
286   %ptr = getelementptr inbounds i8, ptr addrspace(1) null, i64 %non_zero_offset
287   %ret = ptrtoint ptr addrspace(1) %ptr to i64
288   ret i64 %ret
291 ; A non-constant but known-non-zero GEP could be folded to poison/null
292 define i64 @fold_ptrtoint_nullgep_variable_known_nonzero_inbounds_multiple_indices(i64 %val) {
293 ; LLPARSER-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_variable_known_nonzero_inbounds_multiple_indices
294 ; LLPARSER-SAME: (i64 [[VAL:%.*]]) {
295 ; LLPARSER-NEXT:    [[NON_ZERO_OFFSET:%.*]] = or i64 [[VAL]], 1
296 ; LLPARSER-NEXT:    [[PTR:%.*]] = getelementptr inbounds [2 x i8], ptr addrspace(1) null, i64 [[NON_ZERO_OFFSET]], i32 1
297 ; LLPARSER-NEXT:    [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64
298 ; LLPARSER-NEXT:    ret i64 [[RET]]
300 ; INSTSIMPLIFY-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_variable_known_nonzero_inbounds_multiple_indices
301 ; INSTSIMPLIFY-SAME: (i64 [[VAL:%.*]]) {
302 ; INSTSIMPLIFY-NEXT:    [[NON_ZERO_OFFSET:%.*]] = or i64 [[VAL]], 1
303 ; INSTSIMPLIFY-NEXT:    [[PTR:%.*]] = getelementptr inbounds [2 x i8], ptr addrspace(1) null, i64 [[NON_ZERO_OFFSET]], i32 1
304 ; INSTSIMPLIFY-NEXT:    [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64
305 ; INSTSIMPLIFY-NEXT:    ret i64 [[RET]]
307 ; INSTCOMBINE-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_variable_known_nonzero_inbounds_multiple_indices
308 ; INSTCOMBINE-SAME: (i64 [[VAL:%.*]]) {
309 ; INSTCOMBINE-NEXT:    [[NON_ZERO_OFFSET:%.*]] = shl i64 [[VAL]], 1
310 ; INSTCOMBINE-NEXT:    [[PTR_OFFS:%.*]] = or i64 [[NON_ZERO_OFFSET]], 3
311 ; INSTCOMBINE-NEXT:    ret i64 [[PTR_OFFS]]
313   %non_zero_offset = or i64 %val, 1
314   %ptr = getelementptr inbounds [2 x i8], ptr addrspace(1) null, i64 %non_zero_offset, i32 1
315   %ret = ptrtoint ptr addrspace(1) %ptr to i64
316   ret i64 %ret
319 ; We can't fold non-i8 GEPs in InstSimplify since that would require adding new arithmetic.
320 ; However, InstCombine can decompose the null gep and convert it to a shift.
321 define i64 @fold_ptrtoint_nullgep_i32_variable(i64 %val) {
322 ; LLPARSER-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_i32_variable
323 ; LLPARSER-SAME: (i64 [[VAL:%.*]]) {
324 ; LLPARSER-NEXT:    [[PTR:%.*]] = getelementptr i32, ptr addrspace(1) null, i64 [[VAL]]
325 ; LLPARSER-NEXT:    [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64
326 ; LLPARSER-NEXT:    ret i64 [[RET]]
328 ; INSTSIMPLIFY-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_i32_variable
329 ; INSTSIMPLIFY-SAME: (i64 [[VAL:%.*]]) {
330 ; INSTSIMPLIFY-NEXT:    [[PTR:%.*]] = getelementptr i32, ptr addrspace(1) null, i64 [[VAL]]
331 ; INSTSIMPLIFY-NEXT:    [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64
332 ; INSTSIMPLIFY-NEXT:    ret i64 [[RET]]
334 ; INSTCOMBINE-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_i32_variable
335 ; INSTCOMBINE-SAME: (i64 [[VAL:%.*]]) {
336 ; INSTCOMBINE-NEXT:    [[PTR_IDX:%.*]] = shl i64 [[VAL]], 2
337 ; INSTCOMBINE-NEXT:    ret i64 [[PTR_IDX]]
339   %ptr = getelementptr i32, ptr addrspace(1) null, i64 %val
340   %ret = ptrtoint ptr addrspace(1) %ptr to i64
341   ret i64 %ret
344 ; ptrtoint type does not match index type so requires requite a new trunc instruction
345 define i32 @fold_ptrtoint_nullgep_variable_trunc(i64 %val) {
346 ; LLPARSER-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_variable_trunc
347 ; LLPARSER-SAME: (i64 [[VAL:%.*]]) {
348 ; LLPARSER-NEXT:    [[PTR:%.*]] = getelementptr i8, ptr addrspace(1) null, i64 [[VAL]]
349 ; LLPARSER-NEXT:    [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i32
350 ; LLPARSER-NEXT:    ret i32 [[RET]]
352 ; INSTSIMPLIFY-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_variable_trunc
353 ; INSTSIMPLIFY-SAME: (i64 [[VAL:%.*]]) {
354 ; INSTSIMPLIFY-NEXT:    [[PTR:%.*]] = getelementptr i8, ptr addrspace(1) null, i64 [[VAL]]
355 ; INSTSIMPLIFY-NEXT:    [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i32
356 ; INSTSIMPLIFY-NEXT:    ret i32 [[RET]]
358 ; INSTCOMBINE-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_variable_trunc
359 ; INSTCOMBINE-SAME: (i64 [[VAL:%.*]]) {
360 ; INSTCOMBINE-NEXT:    [[RET:%.*]] = trunc i64 [[VAL]] to i32
361 ; INSTCOMBINE-NEXT:    ret i32 [[RET]]
363   %ptr = getelementptr i8, ptr addrspace(1) null, i64 %val
364   %ret = ptrtoint ptr addrspace(1) %ptr to i32
365   ret i32 %ret
368 ; For the following three tests, we could fold the result to poison/null since there is at least
369 ; one inbounds GEP on null with a non-zero offset.
370 define i64 @fold_ptrtoint_zero_nullgep_of_nonzero_inbounds_nullgep() {
371 ; LLPARSER-LABEL: define {{[^@]+}}@fold_ptrtoint_zero_nullgep_of_nonzero_inbounds_nullgep() {
372 ; LLPARSER-NEXT:    [[NONZERO_OFFSET:%.*]] = add i64 1234, 0
373 ; LLPARSER-NEXT:    [[ZERO_OFFSET:%.*]] = sub i64 [[NONZERO_OFFSET]], 1234
374 ; LLPARSER-NEXT:    [[PTR:%.*]] = getelementptr inbounds i8, ptr addrspace(1) null, i64 [[NONZERO_OFFSET]]
375 ; LLPARSER-NEXT:    [[PTR2:%.*]] = getelementptr i8, ptr addrspace(1) [[PTR]], i64 [[ZERO_OFFSET]]
376 ; LLPARSER-NEXT:    [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR2]] to i64
377 ; LLPARSER-NEXT:    ret i64 [[RET]]
379 ; CHECK-LABEL: define {{[^@]+}}@fold_ptrtoint_zero_nullgep_of_nonzero_inbounds_nullgep() {
380 ; CHECK-NEXT:    ret i64 1234
382   %nonzero_offset = add i64 1234, 0
383   %zero_offset = sub i64 %nonzero_offset, 1234
384   %ptr = getelementptr inbounds i8, ptr addrspace(1) null, i64 %nonzero_offset
385   %ptr2 = getelementptr i8, ptr addrspace(1) %ptr, i64 %zero_offset
386   %ret = ptrtoint ptr addrspace(1) %ptr2 to i64
387   ret i64 %ret
390 define i64 @fold_ptrtoint_nonzero_inbounds_nullgep_of_zero_noninbounds_nullgep() {
391 ; LLPARSER-LABEL: define {{[^@]+}}@fold_ptrtoint_nonzero_inbounds_nullgep_of_zero_noninbounds_nullgep() {
392 ; LLPARSER-NEXT:    [[NONZERO_OFFSET:%.*]] = add i64 1234, 0
393 ; LLPARSER-NEXT:    [[ZERO_OFFSET:%.*]] = sub i64 [[NONZERO_OFFSET]], 1234
394 ; LLPARSER-NEXT:    [[PTR:%.*]] = getelementptr i8, ptr addrspace(1) null, i64 [[ZERO_OFFSET]]
395 ; LLPARSER-NEXT:    [[PTR2:%.*]] = getelementptr inbounds i8, ptr addrspace(1) [[PTR]], i64 [[NONZERO_OFFSET]]
396 ; LLPARSER-NEXT:    [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR2]] to i64
397 ; LLPARSER-NEXT:    ret i64 [[RET]]
399 ; CHECK-LABEL: define {{[^@]+}}@fold_ptrtoint_nonzero_inbounds_nullgep_of_zero_noninbounds_nullgep() {
400 ; CHECK-NEXT:    ret i64 1234
402   %nonzero_offset = add i64 1234, 0
403   %zero_offset = sub i64 %nonzero_offset, 1234
404   %ptr = getelementptr i8, ptr addrspace(1) null, i64 %zero_offset
405   %ptr2 = getelementptr inbounds i8, ptr addrspace(1) %ptr, i64 %nonzero_offset
406   %ret = ptrtoint ptr addrspace(1) %ptr2 to i64
407   ret i64 %ret
410 ; We should also be able to fold GEPs with multiple indices.
411 %struct.S = type { [2 x %struct.K] }
412 %struct.K = type { [32 x i8] }
414 define i64 @fold_complex_index_last_nonzero(i64 %x) local_unnamed_addr #0 {
415 ; LLPARSER-LABEL: define {{[^@]+}}@fold_complex_index_last_nonzero
416 ; LLPARSER-SAME: (i64 [[X:%.*]]) local_unnamed_addr {
417 ; LLPARSER-NEXT:  entry:
418 ; LLPARSER-NEXT:    [[PTR:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr addrspace(1) null, i64 0, i32 0, i64 0, i32 0, i64 [[X]]
419 ; LLPARSER-NEXT:    [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64
420 ; LLPARSER-NEXT:    ret i64 [[RET]]
422 ; INSTSIMPLIFY-LABEL: define {{[^@]+}}@fold_complex_index_last_nonzero
423 ; INSTSIMPLIFY-SAME: (i64 [[X:%.*]]) local_unnamed_addr {
424 ; INSTSIMPLIFY-NEXT:  entry:
425 ; INSTSIMPLIFY-NEXT:    [[PTR:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr addrspace(1) null, i64 0, i32 0, i64 0, i32 0, i64 [[X]]
426 ; INSTSIMPLIFY-NEXT:    [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64
427 ; INSTSIMPLIFY-NEXT:    ret i64 [[RET]]
429 ; INSTCOMBINE-LABEL: define {{[^@]+}}@fold_complex_index_last_nonzero
430 ; INSTCOMBINE-SAME: (i64 [[X:%.*]]) local_unnamed_addr {
431 ; INSTCOMBINE-NEXT:  entry:
432 ; INSTCOMBINE-NEXT:    ret i64 [[X]]
434 entry:
435   %ptr = getelementptr inbounds %struct.S, ptr addrspace(1) null, i64 0, i32 0, i64 0, i32 0, i64 %x
436   %ret = ptrtoint ptr addrspace(1) %ptr to i64
437   ret i64 %ret
440 define i64 @fold_complex_index_multiple_nonzero(i64 %x) local_unnamed_addr #0 {
441 ; LLPARSER-LABEL: define {{[^@]+}}@fold_complex_index_multiple_nonzero
442 ; LLPARSER-SAME: (i64 [[X:%.*]]) local_unnamed_addr {
443 ; LLPARSER-NEXT:  entry:
444 ; LLPARSER-NEXT:    [[PTR:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr addrspace(1) null, i64 1, i32 0, i64 1, i32 0, i64 [[X]]
445 ; LLPARSER-NEXT:    [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64
446 ; LLPARSER-NEXT:    ret i64 [[RET]]
448 ; INSTSIMPLIFY-LABEL: define {{[^@]+}}@fold_complex_index_multiple_nonzero
449 ; INSTSIMPLIFY-SAME: (i64 [[X:%.*]]) local_unnamed_addr {
450 ; INSTSIMPLIFY-NEXT:  entry:
451 ; INSTSIMPLIFY-NEXT:    [[PTR:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr addrspace(1) null, i64 1, i32 0, i64 1, i32 0, i64 [[X]]
452 ; INSTSIMPLIFY-NEXT:    [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64
453 ; INSTSIMPLIFY-NEXT:    ret i64 [[RET]]
455 ; INSTCOMBINE-LABEL: define {{[^@]+}}@fold_complex_index_multiple_nonzero
456 ; INSTCOMBINE-SAME: (i64 [[X:%.*]]) local_unnamed_addr {
457 ; INSTCOMBINE-NEXT:  entry:
458 ; INSTCOMBINE-NEXT:    [[PTR_OFFS:%.*]] = add nsw i64 [[X]], 96
459 ; INSTCOMBINE-NEXT:    ret i64 [[PTR_OFFS]]
461 entry:
462   %ptr = getelementptr inbounds %struct.S, ptr addrspace(1) null, i64 1, i32 0, i64 1, i32 0, i64 %x
463   %ret = ptrtoint ptr addrspace(1) %ptr to i64
464   ret i64 %ret
467 define i64 @fold_ptrtoint_inbounds_nullgep_of_nonzero_inbounds_nullgep() {
468 ; LLPARSER-LABEL: define {{[^@]+}}@fold_ptrtoint_inbounds_nullgep_of_nonzero_inbounds_nullgep() {
469 ; LLPARSER-NEXT:    [[NONZERO_OFFSET:%.*]] = add i64 1234, 0
470 ; LLPARSER-NEXT:    [[ZERO_OFFSET:%.*]] = sub i64 [[NONZERO_OFFSET]], 1234
471 ; LLPARSER-NEXT:    [[PTR:%.*]] = getelementptr inbounds i8, ptr addrspace(1) null, i64 [[NONZERO_OFFSET]]
472 ; LLPARSER-NEXT:    [[PTR2:%.*]] = getelementptr inbounds i8, ptr addrspace(1) [[PTR]], i64 [[ZERO_OFFSET]]
473 ; LLPARSER-NEXT:    [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR2]] to i64
474 ; LLPARSER-NEXT:    ret i64 [[RET]]
476 ; CHECK-LABEL: define {{[^@]+}}@fold_ptrtoint_inbounds_nullgep_of_nonzero_inbounds_nullgep() {
477 ; CHECK-NEXT:    ret i64 1234
479   %nonzero_offset = add i64 1234, 0
480   %zero_offset = sub i64 %nonzero_offset, 1234
481   %ptr = getelementptr inbounds i8, ptr addrspace(1) null, i64 %nonzero_offset
482   %ptr2 = getelementptr inbounds i8, ptr addrspace(1) %ptr, i64 %zero_offset
483   %ret = ptrtoint ptr addrspace(1) %ptr2 to i64
484   ret i64 %ret
487 ; Check that InstCombine can convert ptrtoint(gep null) with multiple indices
488 define i64 @fold_ptrtoint_nullgep_array_one_var_1(i64 %x) {
489 ; LLPARSER-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_array_one_var_1
490 ; LLPARSER-SAME: (i64 [[X:%.*]]) {
491 ; LLPARSER-NEXT:    [[PTR:%.*]] = getelementptr [2 x i16], ptr addrspace(1) null, i64 [[X]], i64 3
492 ; LLPARSER-NEXT:    [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64
493 ; LLPARSER-NEXT:    ret i64 [[RET]]
495 ; INSTSIMPLIFY-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_array_one_var_1
496 ; INSTSIMPLIFY-SAME: (i64 [[X:%.*]]) {
497 ; INSTSIMPLIFY-NEXT:    [[PTR:%.*]] = getelementptr [2 x i16], ptr addrspace(1) null, i64 [[X]], i64 3
498 ; INSTSIMPLIFY-NEXT:    [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64
499 ; INSTSIMPLIFY-NEXT:    ret i64 [[RET]]
501 ; INSTCOMBINE-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_array_one_var_1
502 ; INSTCOMBINE-SAME: (i64 [[X:%.*]]) {
503 ; INSTCOMBINE-NEXT:    [[PTR_IDX:%.*]] = shl i64 [[X]], 2
504 ; INSTCOMBINE-NEXT:    [[PTR_OFFS:%.*]] = add i64 [[PTR_IDX]], 6
505 ; INSTCOMBINE-NEXT:    ret i64 [[PTR_OFFS]]
507   %ptr = getelementptr [2 x i16], ptr addrspace(1) null, i64 %x, i64 3
508   %ret = ptrtoint ptr addrspace(1) %ptr to i64
509   ret i64 %ret
512 define i64 @fold_ptrtoint_nullgep_array_one_var_2(i64 %x) {
513 ; LLPARSER-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_array_one_var_2
514 ; LLPARSER-SAME: (i64 [[X:%.*]]) {
515 ; LLPARSER-NEXT:    [[PTR:%.*]] = getelementptr [2 x i16], ptr addrspace(1) null, i64 7, i64 [[X]]
516 ; LLPARSER-NEXT:    [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64
517 ; LLPARSER-NEXT:    ret i64 [[RET]]
519 ; INSTSIMPLIFY-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_array_one_var_2
520 ; INSTSIMPLIFY-SAME: (i64 [[X:%.*]]) {
521 ; INSTSIMPLIFY-NEXT:    [[PTR:%.*]] = getelementptr [2 x i16], ptr addrspace(1) null, i64 7, i64 [[X]]
522 ; INSTSIMPLIFY-NEXT:    [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64
523 ; INSTSIMPLIFY-NEXT:    ret i64 [[RET]]
525 ; INSTCOMBINE-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_array_one_var_2
526 ; INSTCOMBINE-SAME: (i64 [[X:%.*]]) {
527 ; INSTCOMBINE-NEXT:    [[PTR_IDX:%.*]] = shl i64 [[X]], 1
528 ; INSTCOMBINE-NEXT:    [[PTR_OFFS:%.*]] = add i64 [[PTR_IDX]], 28
529 ; INSTCOMBINE-NEXT:    ret i64 [[PTR_OFFS]]
531   %ptr = getelementptr [2 x i16], ptr addrspace(1) null, i64 7, i64 %x
532   %ret = ptrtoint ptr addrspace(1) %ptr to i64
533   ret i64 %ret
536 define i64 @fold_ptrtoint_nested_array_two_vars(i64 %x, i64 %y) {
537 ; LLPARSER-LABEL: define {{[^@]+}}@fold_ptrtoint_nested_array_two_vars
538 ; LLPARSER-SAME: (i64 [[X:%.*]], i64 [[Y:%.*]]) {
539 ; LLPARSER-NEXT:    [[PTR:%.*]] = getelementptr [2 x i16], ptr addrspace(1) null, i64 [[X]], i64 [[Y]]
540 ; LLPARSER-NEXT:    [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64
541 ; LLPARSER-NEXT:    ret i64 [[RET]]
543 ; INSTSIMPLIFY-LABEL: define {{[^@]+}}@fold_ptrtoint_nested_array_two_vars
544 ; INSTSIMPLIFY-SAME: (i64 [[X:%.*]], i64 [[Y:%.*]]) {
545 ; INSTSIMPLIFY-NEXT:    [[PTR:%.*]] = getelementptr [2 x i16], ptr addrspace(1) null, i64 [[X]], i64 [[Y]]
546 ; INSTSIMPLIFY-NEXT:    [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64
547 ; INSTSIMPLIFY-NEXT:    ret i64 [[RET]]
549 ; INSTCOMBINE-LABEL: define {{[^@]+}}@fold_ptrtoint_nested_array_two_vars
550 ; INSTCOMBINE-SAME: (i64 [[X:%.*]], i64 [[Y:%.*]]) {
551 ; INSTCOMBINE-NEXT:    [[PTR_IDX:%.*]] = shl i64 [[X]], 2
552 ; INSTCOMBINE-NEXT:    [[PTR_IDX1:%.*]] = shl i64 [[Y]], 1
553 ; INSTCOMBINE-NEXT:    [[PTR_OFFS:%.*]] = add i64 [[PTR_IDX]], [[PTR_IDX1]]
554 ; INSTCOMBINE-NEXT:    ret i64 [[PTR_OFFS]]
557   %ptr = getelementptr [2 x i16], ptr addrspace(1) null, i64 %x, i64 %y
558   %ret = ptrtoint ptr addrspace(1) %ptr to i64
559   ret i64 %ret
562 define i64 @fold_ptrtoint_nested_array_two_vars_plus_zero(i64 %x, i64 %y) {
563 ; LLPARSER-LABEL: define {{[^@]+}}@fold_ptrtoint_nested_array_two_vars_plus_zero
564 ; LLPARSER-SAME: (i64 [[X:%.*]], i64 [[Y:%.*]]) {
565 ; LLPARSER-NEXT:    [[PTR:%.*]] = getelementptr [2 x [2 x i16]], ptr addrspace(1) null, i64 [[X]], i64 [[Y]], i64 0
566 ; LLPARSER-NEXT:    [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64
567 ; LLPARSER-NEXT:    ret i64 [[RET]]
569 ; INSTSIMPLIFY-LABEL: define {{[^@]+}}@fold_ptrtoint_nested_array_two_vars_plus_zero
570 ; INSTSIMPLIFY-SAME: (i64 [[X:%.*]], i64 [[Y:%.*]]) {
571 ; INSTSIMPLIFY-NEXT:    [[PTR:%.*]] = getelementptr [2 x [2 x i16]], ptr addrspace(1) null, i64 [[X]], i64 [[Y]], i64 0
572 ; INSTSIMPLIFY-NEXT:    [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64
573 ; INSTSIMPLIFY-NEXT:    ret i64 [[RET]]
575 ; INSTCOMBINE-LABEL: define {{[^@]+}}@fold_ptrtoint_nested_array_two_vars_plus_zero
576 ; INSTCOMBINE-SAME: (i64 [[X:%.*]], i64 [[Y:%.*]]) {
577 ; INSTCOMBINE-NEXT:    [[PTR_IDX:%.*]] = shl i64 [[X]], 3
578 ; INSTCOMBINE-NEXT:    [[PTR_IDX1:%.*]] = shl i64 [[Y]], 2
579 ; INSTCOMBINE-NEXT:    [[PTR_OFFS:%.*]] = add i64 [[PTR_IDX]], [[PTR_IDX1]]
580 ; INSTCOMBINE-NEXT:    ret i64 [[PTR_OFFS]]
582   %ptr = getelementptr [2 x [2 x i16]], ptr addrspace(1) null, i64 %x, i64 %y, i64 0
583   %ret = ptrtoint ptr addrspace(1) %ptr to i64
584   ret i64 %ret
587 define i64 @fold_ptrtoint_nested_array_two_vars_plus_const(i64 %x, i64 %y) {
588 ; LLPARSER-LABEL: define {{[^@]+}}@fold_ptrtoint_nested_array_two_vars_plus_const
589 ; LLPARSER-SAME: (i64 [[X:%.*]], i64 [[Y:%.*]]) {
590 ; LLPARSER-NEXT:    [[PTR:%.*]] = getelementptr [2 x [2 x i16]], ptr addrspace(1) null, i64 [[X]], i64 [[Y]], i64 1
591 ; LLPARSER-NEXT:    [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64
592 ; LLPARSER-NEXT:    ret i64 [[RET]]
594 ; INSTSIMPLIFY-LABEL: define {{[^@]+}}@fold_ptrtoint_nested_array_two_vars_plus_const
595 ; INSTSIMPLIFY-SAME: (i64 [[X:%.*]], i64 [[Y:%.*]]) {
596 ; INSTSIMPLIFY-NEXT:    [[PTR:%.*]] = getelementptr [2 x [2 x i16]], ptr addrspace(1) null, i64 [[X]], i64 [[Y]], i64 1
597 ; INSTSIMPLIFY-NEXT:    [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64
598 ; INSTSIMPLIFY-NEXT:    ret i64 [[RET]]
600 ; INSTCOMBINE-LABEL: define {{[^@]+}}@fold_ptrtoint_nested_array_two_vars_plus_const
601 ; INSTCOMBINE-SAME: (i64 [[X:%.*]], i64 [[Y:%.*]]) {
602 ; INSTCOMBINE-NEXT:    [[PTR_IDX:%.*]] = shl i64 [[X]], 3
603 ; INSTCOMBINE-NEXT:    [[PTR_IDX1:%.*]] = shl i64 [[Y]], 2
604 ; INSTCOMBINE-NEXT:    [[PTR_OFFS:%.*]] = add i64 [[PTR_IDX]], [[PTR_IDX1]]
605 ; INSTCOMBINE-NEXT:    [[PTR_OFFS2:%.*]] = or disjoint i64 [[PTR_OFFS]], 2
606 ; INSTCOMBINE-NEXT:    ret i64 [[PTR_OFFS2]]
608   %ptr = getelementptr [2 x [2 x i16]], ptr addrspace(1) null, i64 %x, i64 %y, i64 1
609   %ret = ptrtoint ptr addrspace(1) %ptr to i64
610   ret i64 %ret
613 ; Negative test -- should not be folded since there are multiple GEP uses
614 define i64 @fold_ptrtoint_nested_nullgep_array_variable_multiple_uses(i64 %x, i64 %y) {
615 ; ALL-LABEL: define {{[^@]+}}@fold_ptrtoint_nested_nullgep_array_variable_multiple_uses
616 ; ALL-SAME: (i64 [[X:%.*]], i64 [[Y:%.*]]) {
617 ; ALL-NEXT:    [[PTR:%.*]] = getelementptr [2 x i16], ptr addrspace(1) null, i64 [[X]], i64 [[Y]]
618 ; ALL-NEXT:    call void @use_ptr(ptr addrspace(1) [[PTR]])
619 ; ALL-NEXT:    [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64
620 ; ALL-NEXT:    ret i64 [[RET]]
622   %ptr = getelementptr [2 x i16], ptr addrspace(1) null, i64 %x, i64 %y
623   call void @use_ptr(ptr addrspace(1) %ptr)
624   %ret = ptrtoint ptr addrspace(1) %ptr to i64
625   ret i64 %ret