xref: /llvm-project/llvm/test/Transforms/InstCombine/constant-fold-address-space-pointer.ll (revision 10f315dc9c96ec2413881ab55a285e35d80def88)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -S -passes=instcombine %s -o - | FileCheck %s
3target datalayout = "e-p:32:32:32-p1:64:64:64-p2:8:8:8-p3:16:16:16-p4:16:16:16-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:32"
4
5@g = addrspace(3) global i32 89
6
7@const_zero_i8_as1 = addrspace(1) constant i8 0
8@const_zero_i32_as1 = addrspace(1) constant i32 0
9
10@const_zero_i8_as2 = addrspace(2) constant i8 0
11@const_zero_i32_as2 = addrspace(2) constant i32 0
12
13@const_zero_i8_as3 = addrspace(3) constant i8 0
14@const_zero_i32_as3 = addrspace(3) constant i32 0
15
16; Test constant folding of inttoptr (ptrtoint constantexpr)
17; The intermediate integer size is the same as the pointer size
18define ptr addrspace(3) @test_constant_fold_inttoptr_as_pointer_same_size() {
19; CHECK-LABEL: @test_constant_fold_inttoptr_as_pointer_same_size(
20; CHECK-NEXT:    ret ptr addrspace(3) @const_zero_i32_as3
21;
22  %x = ptrtoint ptr addrspace(3) @const_zero_i32_as3 to i32
23  %y = inttoptr i32 %x to ptr addrspace(3)
24  ret ptr addrspace(3) %y
25}
26
27; The intermediate integer size is larger than the pointer size
28define ptr addrspace(2) @test_constant_fold_inttoptr_as_pointer_smaller() {
29; CHECK-LABEL: @test_constant_fold_inttoptr_as_pointer_smaller(
30; CHECK-NEXT:    ret ptr addrspace(2) @const_zero_i32_as2
31;
32  %x = ptrtoint ptr addrspace(2) @const_zero_i32_as2 to i16
33  %y = inttoptr i16 %x to ptr addrspace(2)
34  ret ptr addrspace(2) %y
35}
36
37; Different address spaces that are the same size, but they are
38; different so nothing should happen
39define ptr addrspace(4) @test_constant_fold_inttoptr_as_pointer_smaller_different_as() {
40; CHECK-LABEL: @test_constant_fold_inttoptr_as_pointer_smaller_different_as(
41; CHECK-NEXT:    ret ptr addrspace(4) inttoptr (i16 ptrtoint (ptr addrspace(3) @const_zero_i32_as3 to i16) to ptr addrspace(4))
42;
43  %x = ptrtoint ptr addrspace(3) @const_zero_i32_as3 to i16
44  %y = inttoptr i16 %x to ptr addrspace(4)
45  ret ptr addrspace(4) %y
46}
47
48; Make sure we don't introduce a bitcast between different sized
49; address spaces when folding this
50define ptr addrspace(2) @test_constant_fold_inttoptr_as_pointer_smaller_different_size_as() {
51; CHECK-LABEL: @test_constant_fold_inttoptr_as_pointer_smaller_different_size_as(
52; CHECK-NEXT:    ret ptr addrspace(2) inttoptr (i32 ptrtoint (ptr addrspace(3) @const_zero_i32_as3 to i32) to ptr addrspace(2))
53;
54  %x = ptrtoint ptr addrspace(3) @const_zero_i32_as3 to i32
55  %y = inttoptr i32 %x to ptr addrspace(2)
56  ret ptr addrspace(2) %y
57}
58
59; The intermediate integer size is too small, nothing should happen
60define ptr addrspace(3) @test_constant_fold_inttoptr_as_pointer_larger() {
61; CHECK-LABEL: @test_constant_fold_inttoptr_as_pointer_larger(
62; CHECK-NEXT:    ret ptr addrspace(3) inttoptr (i8 ptrtoint (ptr addrspace(3) @const_zero_i32_as3 to i8) to ptr addrspace(3))
63;
64  %x = ptrtoint ptr addrspace(3) @const_zero_i32_as3 to i8
65  %y = inttoptr i8 %x to ptr addrspace(3)
66  ret ptr addrspace(3) %y
67}
68
69define i8 @const_fold_ptrtoint() {
70; CHECK-LABEL: @const_fold_ptrtoint(
71; CHECK-NEXT:    ret i8 4
72;
73  ret i8 ptrtoint (ptr addrspace(2) inttoptr (i4 4 to ptr addrspace(2)) to i8)
74}
75
76; Test that mask happens when the destination pointer is smaller than
77; the original
78define i8 @const_fold_ptrtoint_mask() {
79; CHECK-LABEL: @const_fold_ptrtoint_mask(
80; CHECK-NEXT:    ret i8 1
81;
82  ret i8 ptrtoint (ptr addrspace(3) inttoptr (i32 257 to ptr addrspace(3)) to i8)
83}
84
85; Address space 0 is too small for the correct mask, should mask with
86; 64-bits instead of 32
87define i64 @const_fold_ptrtoint_mask_small_as0() {
88; CHECK-LABEL: @const_fold_ptrtoint_mask_small_as0(
89; CHECK-NEXT:    ret i64 -1
90;
91  ret i64 ptrtoint (ptr addrspace(1) inttoptr (i128 -1 to ptr addrspace(1)) to i64)
92}
93
94define ptr addrspace(3) @const_inttoptr() {
95; CHECK-LABEL: @const_inttoptr(
96; CHECK-NEXT:    ret ptr addrspace(3) inttoptr (i16 4 to ptr addrspace(3))
97;
98  %p = inttoptr i16 4 to ptr addrspace(3)
99  ret ptr addrspace(3) %p
100}
101
102define i16 @const_ptrtoint() {
103; CHECK-LABEL: @const_ptrtoint(
104; CHECK-NEXT:    ret i16 ptrtoint (ptr addrspace(3) @g to i16)
105;
106  %i = ptrtoint ptr addrspace(3) @g to i16
107  ret i16 %i
108}
109
110define i16 @const_inttoptr_ptrtoint() {
111; CHECK-LABEL: @const_inttoptr_ptrtoint(
112; CHECK-NEXT:    ret i16 9
113;
114  ret i16 ptrtoint (ptr addrspace(3) inttoptr (i16 9 to ptr addrspace(3)) to i16)
115}
116
117define i1 @constant_fold_cmp_constantexpr_inttoptr() {
118; CHECK-LABEL: @constant_fold_cmp_constantexpr_inttoptr(
119; CHECK-NEXT:    ret i1 true
120;
121  %x = icmp eq ptr addrspace(3) inttoptr (i16 0 to ptr addrspace(3)), null
122  ret i1 %x
123}
124
125define i1 @constant_fold_inttoptr_null(i16 %i) {
126; CHECK-LABEL: @constant_fold_inttoptr_null(
127; CHECK-NEXT:    ret i1 false
128;
129  %x = icmp eq ptr addrspace(3) inttoptr (i16 99 to ptr addrspace(3)), inttoptr (i16 0 to ptr addrspace(3))
130  ret i1 %x
131}
132
133define i1 @constant_fold_ptrtoint_null() {
134; CHECK-LABEL: @constant_fold_ptrtoint_null(
135; CHECK-NEXT:    [[X:%.*]] = icmp eq i16 ptrtoint (ptr addrspace(3) @g to i16), 0
136; CHECK-NEXT:    ret i1 [[X]]
137;
138  %x = icmp eq i16 ptrtoint (ptr addrspace(3) @g to i16), ptrtoint (ptr addrspace(3) null to i16)
139  ret i1 %x
140}
141
142define i1 @constant_fold_ptrtoint_null_2() {
143; CHECK-LABEL: @constant_fold_ptrtoint_null_2(
144; CHECK-NEXT:    [[X:%.*]] = icmp eq i16 0, ptrtoint (ptr addrspace(3) @g to i16)
145; CHECK-NEXT:    ret i1 [[X]]
146;
147  %x = icmp eq i16 ptrtoint (ptr addrspace(3) null to i16), ptrtoint (ptr addrspace(3) @g to i16)
148  ret i1 %x
149}
150
151define i1 @constant_fold_ptrtoint() {
152; CHECK-LABEL: @constant_fold_ptrtoint(
153; CHECK-NEXT:    ret i1 true
154;
155  %x = icmp eq i16 ptrtoint (ptr addrspace(3) @g to i16), ptrtoint (ptr addrspace(3) @g to i16)
156  ret i1 %x
157}
158
159define i1 @constant_fold_inttoptr() {
160; CHECK-LABEL: @constant_fold_inttoptr(
161; CHECK-NEXT:    ret i1 false
162;
163  %x = icmp eq ptr addrspace(3) inttoptr (i16 99 to ptr addrspace(3)), inttoptr (i16 27 to ptr addrspace(3))
164  ret i1 %x
165}
166
167@g_float_as3 = addrspace(3) global float zeroinitializer
168@g_v4f_as3 = addrspace(3) global <4 x float> zeroinitializer
169
170define float @constant_fold_bitcast_ftoi_load() {
171; CHECK-LABEL: @constant_fold_bitcast_ftoi_load(
172; CHECK-NEXT:    [[A:%.*]] = load float, ptr addrspace(3) @g, align 4
173; CHECK-NEXT:    ret float [[A]]
174;
175  %a = load float, ptr addrspace(3) @g, align 4
176  ret float %a
177}
178
179define i32 @constant_fold_bitcast_itof_load() {
180; CHECK-LABEL: @constant_fold_bitcast_itof_load(
181; CHECK-NEXT:    [[A:%.*]] = load i32, ptr addrspace(3) @g_float_as3, align 4
182; CHECK-NEXT:    ret i32 [[A]]
183;
184  %a = load i32, ptr addrspace(3) @g_float_as3, align 4
185  ret i32 %a
186}
187
188define <4 x float> @constant_fold_bitcast_vector_as() {
189; CHECK-LABEL: @constant_fold_bitcast_vector_as(
190; CHECK-NEXT:    [[A:%.*]] = load <4 x float>, ptr addrspace(3) @g_v4f_as3, align 4
191; CHECK-NEXT:    ret <4 x float> [[A]]
192;
193  %a = load <4 x float>, ptr addrspace(3) @g_v4f_as3, align 4
194  ret <4 x float> %a
195}
196
197@i32_array_as3 = addrspace(3) global [10 x i32] zeroinitializer
198
199define i32 @test_cast_gep_small_indices_as() {
200; CHECK-LABEL: @test_cast_gep_small_indices_as(
201; CHECK-NEXT:    [[X:%.*]] = load i32, ptr addrspace(3) @i32_array_as3, align 4
202; CHECK-NEXT:    ret i32 [[X]]
203;
204  %x = load i32, ptr addrspace(3) @i32_array_as3, align 4
205  ret i32 %x
206}
207
208%struct.foo = type { float, float, [4 x i32], ptr addrspace(3) }
209
210@constant_fold_global_ptr = addrspace(3) global %struct.foo {
211  float 0.0,
212  float 0.0,
213  [4 x i32] zeroinitializer,
214  ptr addrspace(3) @i32_array_as3
215}
216
217define i32 @test_cast_gep_large_indices_as() {
218; CHECK-LABEL: @test_cast_gep_large_indices_as(
219; CHECK-NEXT:    [[X:%.*]] = load i32, ptr addrspace(3) @i32_array_as3, align 4
220; CHECK-NEXT:    ret i32 [[X]]
221;
222  %x = load i32, ptr addrspace(3) @i32_array_as3, align 4
223  ret i32 %x
224}
225
226define i32 @test_constant_cast_gep_struct_indices_as() {
227; CHECK-LABEL: @test_constant_cast_gep_struct_indices_as(
228; CHECK-NEXT:    [[Y:%.*]] = load i32, ptr addrspace(3) getelementptr inbounds nuw (i8, ptr addrspace(3) @constant_fold_global_ptr, i16 16), align 4
229; CHECK-NEXT:    ret i32 [[Y]]
230;
231  %x = getelementptr %struct.foo, ptr addrspace(3) @constant_fold_global_ptr, i18 0, i32 2, i12 2
232  %y = load i32, ptr addrspace(3) %x, align 4
233  ret i32 %y
234}
235
236@constant_data_as3 = addrspace(3) constant [5 x i32] [i32 1, i32 2, i32 3, i32 4, i32 5]
237
238define i32 @test_read_data_from_global_as3() {
239; CHECK-LABEL: @test_read_data_from_global_as3(
240; CHECK-NEXT:    ret i32 2
241;
242  %x = getelementptr [5 x i32], ptr addrspace(3) @constant_data_as3, i32 0, i32 1
243  %y = load i32, ptr addrspace(3) %x, align 4
244  ret i32 %y
245}
246
247@a = addrspace(1) constant i32 9
248@b = addrspace(1) constant i32 23
249@c = addrspace(1) constant i32 34
250@d = addrspace(1) constant i32 99
251
252@ptr_array = addrspace(2) constant [4 x ptr addrspace(1)] [ ptr addrspace(1) @a, ptr addrspace(1) @b, ptr addrspace(1) @c, ptr addrspace(1) @d]
253@indirect = addrspace(0) constant ptr addrspace(2) getelementptr inbounds ([4 x ptr addrspace(1)], ptr addrspace(2) @ptr_array, i1 0, i32 2)
254
255define i32 @constant_through_array_as_ptrs() {
256; CHECK-LABEL: @constant_through_array_as_ptrs(
257; CHECK-NEXT:    ret i32 34
258;
259  %p = load ptr addrspace(2), ptr addrspace(0) @indirect, align 4
260  %a = load ptr addrspace(1), ptr addrspace(2) %p, align 4
261  %b = load i32, ptr addrspace(1) %a, align 4
262  ret i32 %b
263}
264
265@shared_mem = external addrspace(3) global [0 x i8]
266
267define float @canonicalize_addrspacecast(i32 %i) {
268; CHECK-LABEL: @canonicalize_addrspacecast(
269; CHECK-NEXT:    [[P:%.*]] = getelementptr inbounds float, ptr addrspacecast (ptr addrspace(3) @shared_mem to ptr), i32 [[I:%.*]]
270; CHECK-NEXT:    [[V:%.*]] = load float, ptr [[P]], align 4
271; CHECK-NEXT:    ret float [[V]]
272;
273  %p = getelementptr inbounds float, ptr addrspacecast (ptr addrspace(3) @shared_mem to ptr), i32 %i
274  %v = load float, ptr %p
275  ret float %v
276}
277