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