1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
2 ; RUN: opt -S -passes=instcombine -o - %s | FileCheck %s
3 target datalayout = "e-p:32:32:32-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v24:32:32-v32:32:32-v64:64:64-v128:128:128-a0:0:64"
5 define internal <2 x i32> @func_v2i32(<2 x i32> %v) noinline nounwind {
6 ; CHECK-LABEL: define internal <2 x i32> @func_v2i32
7 ; CHECK-SAME: (<2 x i32> [[V:%.*]]) #[[ATTR0:[0-9]+]] {
9 ; CHECK-NEXT: ret <2 x i32> [[V]]
15 define internal <2 x float> @func_v2f32(<2 x float> %v) noinline nounwind {
16 ; CHECK-LABEL: define internal <2 x float> @func_v2f32
17 ; CHECK-SAME: (<2 x float> [[V:%.*]]) #[[ATTR0]] {
19 ; CHECK-NEXT: ret <2 x float> [[V]]
25 define internal <4 x float> @func_v4f32(<4 x float> %v) noinline nounwind {
26 ; CHECK-LABEL: define internal <4 x float> @func_v4f32
27 ; CHECK-SAME: (<4 x float> [[V:%.*]]) #[[ATTR0]] {
29 ; CHECK-NEXT: ret <4 x float> [[V]]
35 define internal i32 @func_i32(i32 %v) noinline nounwind {
36 ; CHECK-LABEL: define internal i32 @func_i32
37 ; CHECK-SAME: (i32 [[V:%.*]]) #[[ATTR0]] {
39 ; CHECK-NEXT: ret i32 [[V]]
45 define internal i64 @func_i64(i64 %v) noinline nounwind {
46 ; CHECK-LABEL: define internal i64 @func_i64
47 ; CHECK-SAME: (i64 [[V:%.*]]) #[[ATTR0]] {
49 ; CHECK-NEXT: ret i64 [[V]]
55 define internal <2 x i64> @func_v2i64(<2 x i64> %v) noinline nounwind {
56 ; CHECK-LABEL: define internal <2 x i64> @func_v2i64
57 ; CHECK-SAME: (<2 x i64> [[V:%.*]]) #[[ATTR0]] {
59 ; CHECK-NEXT: ret <2 x i64> [[V]]
65 define internal <2 x ptr> @func_v2i32p(<2 x ptr> %v) noinline nounwind {
66 ; CHECK-LABEL: define internal <2 x ptr> @func_v2i32p
67 ; CHECK-SAME: (<2 x ptr> [[V:%.*]]) #[[ATTR0]] {
69 ; CHECK-NEXT: ret <2 x ptr> [[V]]
75 ; Valid cases, only bitcast for argument / return type and call underlying function
77 ; Test cast between scalars with same bit sizes
78 ; Sizes match, should only bitcast
79 define void @bitcast_scalar(ptr noalias %source, ptr noalias %dest) nounwind {
80 ; CHECK-LABEL: define void @bitcast_scalar
81 ; CHECK-SAME: (ptr noalias [[SOURCE:%.*]], ptr noalias [[DEST:%.*]]) #[[ATTR1:[0-9]+]] {
83 ; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[SOURCE]], align 8
84 ; CHECK-NEXT: [[CALL:%.*]] = call i32 @func_i32(i32 [[TMP1]]) #[[ATTR1]]
85 ; CHECK-NEXT: store i32 [[CALL]], ptr [[DEST]], align 8
86 ; CHECK-NEXT: ret void
89 %tmp = load float, ptr %source, align 8
90 %call = call float @func_i32(float %tmp) nounwind
91 store float %call, ptr %dest, align 8
95 ; Test cast between vectors with same number of elements and bit sizes
96 ; Sizes match, should only bitcast
97 define void @bitcast_vector(ptr noalias %source, ptr noalias %dest) nounwind {
98 ; CHECK-LABEL: define void @bitcast_vector
99 ; CHECK-SAME: (ptr noalias [[SOURCE:%.*]], ptr noalias [[DEST:%.*]]) #[[ATTR1]] {
101 ; CHECK-NEXT: [[TMP1:%.*]] = load <2 x i32>, ptr [[SOURCE]], align 8
102 ; CHECK-NEXT: [[CALL:%.*]] = call <2 x i32> @func_v2i32(<2 x i32> [[TMP1]]) #[[ATTR1]]
103 ; CHECK-NEXT: store <2 x i32> [[CALL]], ptr [[DEST]], align 8
104 ; CHECK-NEXT: ret void
107 %tmp = load <2 x float>, ptr %source, align 8
108 %call = call <2 x float> @func_v2i32(<2 x float> %tmp) nounwind
109 store <2 x float> %call, ptr %dest, align 8
113 ; Test cast from vector to scalar with same number of bits
114 ; Sizes match, should only bitcast
115 define void @bitcast_vector_scalar_same_size(ptr noalias %source, ptr noalias %dest) nounwind {
116 ; CHECK-LABEL: define void @bitcast_vector_scalar_same_size
117 ; CHECK-SAME: (ptr noalias [[SOURCE:%.*]], ptr noalias [[DEST:%.*]]) #[[ATTR1]] {
119 ; CHECK-NEXT: [[TMP1:%.*]] = load i64, ptr [[SOURCE]], align 8
120 ; CHECK-NEXT: [[CALL:%.*]] = call i64 @func_i64(i64 [[TMP1]]) #[[ATTR1]]
121 ; CHECK-NEXT: store i64 [[CALL]], ptr [[DEST]], align 8
122 ; CHECK-NEXT: ret void
125 %tmp = load <2 x float>, ptr %source, align 8
126 %call = call <2 x float> @func_i64(<2 x float> %tmp) nounwind
127 store <2 x float> %call, ptr %dest, align 8
131 ; Test cast from scalar to vector with same number of bits
132 define void @bitcast_scalar_vector_same_size(ptr noalias %source, ptr noalias %dest) nounwind {
133 ; CHECK-LABEL: define void @bitcast_scalar_vector_same_size
134 ; CHECK-SAME: (ptr noalias [[SOURCE:%.*]], ptr noalias [[DEST:%.*]]) #[[ATTR1]] {
136 ; CHECK-NEXT: [[TMP1:%.*]] = load <2 x float>, ptr [[SOURCE]], align 8
137 ; CHECK-NEXT: [[CALL:%.*]] = call <2 x float> @func_v2f32(<2 x float> [[TMP1]]) #[[ATTR1]]
138 ; CHECK-NEXT: store <2 x float> [[CALL]], ptr [[DEST]], align 8
139 ; CHECK-NEXT: ret void
142 %tmp = load i64, ptr %source, align 8
143 %call = call i64 @func_v2f32(i64 %tmp) nounwind
144 store i64 %call, ptr %dest, align 8
148 ; Test cast between vectors of pointers
149 define void @bitcast_vector_ptrs_same_size(ptr noalias %source, ptr noalias %dest) nounwind {
150 ; CHECK-LABEL: define void @bitcast_vector_ptrs_same_size
151 ; CHECK-SAME: (ptr noalias [[SOURCE:%.*]], ptr noalias [[DEST:%.*]]) #[[ATTR1]] {
153 ; CHECK-NEXT: [[TMP:%.*]] = load <2 x ptr>, ptr [[SOURCE]], align 8
154 ; CHECK-NEXT: [[CALL:%.*]] = call <2 x ptr> @func_v2i32p(<2 x ptr> [[TMP]]) #[[ATTR1]]
155 ; CHECK-NEXT: store <2 x ptr> [[CALL]], ptr [[DEST]], align 8
156 ; CHECK-NEXT: ret void
159 %tmp = load <2 x ptr>, ptr %source, align 8
160 %call = call <2 x ptr> @func_v2i32p(<2 x ptr> %tmp) nounwind
161 store <2 x ptr> %call, ptr %dest, align 8
167 ; Test cast between scalars with different bit sizes
168 define void @bitcast_mismatch_scalar_size(ptr noalias %source, ptr noalias %dest) nounwind {
169 ; CHECK-LABEL: define void @bitcast_mismatch_scalar_size
170 ; CHECK-SAME: (ptr noalias [[SOURCE:%.*]], ptr noalias [[DEST:%.*]]) #[[ATTR1]] {
172 ; CHECK-NEXT: [[TMP:%.*]] = load float, ptr [[SOURCE]], align 8
173 ; CHECK-NEXT: [[CALL:%.*]] = call float @func_i64(float [[TMP]]) #[[ATTR1]]
174 ; CHECK-NEXT: store float [[CALL]], ptr [[DEST]], align 8
175 ; CHECK-NEXT: ret void
178 %tmp = load float, ptr %source, align 8
179 %call = call float @func_i64(float %tmp) nounwind
180 store float %call, ptr %dest, align 8
184 ; Test cast between vectors with different bit sizes but the
185 ; same number of elements
186 define void @bitcast_mismatch_vector_element_and_bit_size(ptr noalias %source, ptr noalias %dest) nounwind {
187 ; CHECK-LABEL: define void @bitcast_mismatch_vector_element_and_bit_size
188 ; CHECK-SAME: (ptr noalias [[SOURCE:%.*]], ptr noalias [[DEST:%.*]]) #[[ATTR1]] {
190 ; CHECK-NEXT: [[TMP:%.*]] = load <2 x float>, ptr [[SOURCE]], align 8
191 ; CHECK-NEXT: [[CALL:%.*]] = call <2 x float> @func_v2i64(<2 x float> [[TMP]]) #[[ATTR1]]
192 ; CHECK-NEXT: store <2 x float> [[CALL]], ptr [[DEST]], align 8
193 ; CHECK-NEXT: ret void
196 %tmp = load <2 x float>, ptr %source, align 8
197 %call = call <2 x float> @func_v2i64(<2 x float> %tmp) nounwind
198 store <2 x float> %call, ptr %dest, align 8
202 ; Test cast between vectors with same number of bits and different
203 ; numbers of elements
204 define void @bitcast_vector_mismatched_number_elements(ptr noalias %source, ptr noalias %dest) nounwind {
205 ; CHECK-LABEL: define void @bitcast_vector_mismatched_number_elements
206 ; CHECK-SAME: (ptr noalias [[SOURCE:%.*]], ptr noalias [[DEST:%.*]]) #[[ATTR1]] {
208 ; CHECK-NEXT: [[TMP:%.*]] = load <4 x float>, ptr [[SOURCE]], align 8
209 ; CHECK-NEXT: [[CALL:%.*]] = call <4 x float> @func_v2i32(<4 x float> [[TMP]]) #[[ATTR1]]
210 ; CHECK-NEXT: store <4 x float> [[CALL]], ptr [[DEST]], align 8
211 ; CHECK-NEXT: ret void
214 %tmp = load <4 x float>, ptr %source, align 8
215 %call = call <4 x float> @func_v2i32(<4 x float> %tmp) nounwind
216 store <4 x float> %call, ptr %dest, align 8
220 ; Test cast between vector and scalar with different number of bits
221 define void @bitcast_vector_scalar_mismatched_bit_size(ptr noalias %source, ptr noalias %dest) nounwind {
222 ; CHECK-LABEL: define void @bitcast_vector_scalar_mismatched_bit_size
223 ; CHECK-SAME: (ptr noalias [[SOURCE:%.*]], ptr noalias [[DEST:%.*]]) #[[ATTR1]] {
225 ; CHECK-NEXT: [[TMP:%.*]] = load <4 x float>, ptr [[SOURCE]], align 8
226 ; CHECK-NEXT: [[CALL:%.*]] = call <4 x float> @func_i64(<4 x float> [[TMP]]) #[[ATTR1]]
227 ; CHECK-NEXT: store <4 x float> [[CALL]], ptr [[DEST]], align 8
228 ; CHECK-NEXT: ret void
231 %tmp = load <4 x float>, ptr %source, align 8
232 %call = call <4 x float> @func_i64(<4 x float> %tmp) nounwind
233 store <4 x float> %call, ptr %dest, align 8
237 ; Test cast between vector of pointers and scalar with different number of bits
238 define void @bitcast_vector_ptrs_scalar_mismatched_bit_size(ptr noalias %source, ptr noalias %dest) nounwind {
239 ; CHECK-LABEL: define void @bitcast_vector_ptrs_scalar_mismatched_bit_size
240 ; CHECK-SAME: (ptr noalias [[SOURCE:%.*]], ptr noalias [[DEST:%.*]]) #[[ATTR1]] {
242 ; CHECK-NEXT: [[TMP:%.*]] = load <4 x ptr>, ptr [[SOURCE]], align 8
243 ; CHECK-NEXT: [[CALL:%.*]] = call <4 x ptr> @func_i64(<4 x ptr> [[TMP]]) #[[ATTR1]]
244 ; CHECK-NEXT: store <4 x ptr> [[CALL]], ptr [[DEST]], align 8
245 ; CHECK-NEXT: ret void
248 %tmp = load <4 x ptr>, ptr %source, align 8
249 %call = call <4 x ptr> @func_i64(<4 x ptr> %tmp) nounwind
250 store <4 x ptr> %call, ptr %dest, align 8
254 ; Test cast from scalar to vector of pointers with same number of bits
255 ; We don't know the pointer size at this point, so this can't be done
256 define void @bitcast_scalar_vector_ptrs_same_size(ptr noalias %source, ptr noalias %dest) nounwind {
257 ; CHECK-LABEL: define void @bitcast_scalar_vector_ptrs_same_size
258 ; CHECK-SAME: (ptr noalias [[SOURCE:%.*]], ptr noalias [[DEST:%.*]]) #[[ATTR1]] {
260 ; CHECK-NEXT: [[TMP:%.*]] = load i64, ptr [[SOURCE]], align 8
261 ; CHECK-NEXT: [[CALL:%.*]] = call i64 @func_v2i32p(i64 [[TMP]]) #[[ATTR1]]
262 ; CHECK-NEXT: store i64 [[CALL]], ptr [[DEST]], align 8
263 ; CHECK-NEXT: ret void
266 %tmp = load i64, ptr %source, align 8
267 %call = call i64 @func_v2i32p(i64 %tmp) nounwind
268 store i64 %call, ptr %dest, align 8
272 ; Test cast between scalar and vector with different number of bits
273 define void @bitcast_scalar_vector_mismatched_bit_size(ptr noalias %source, ptr noalias %dest) nounwind {
274 ; CHECK-LABEL: define void @bitcast_scalar_vector_mismatched_bit_size
275 ; CHECK-SAME: (ptr noalias [[SOURCE:%.*]], ptr noalias [[DEST:%.*]]) #[[ATTR1]] {
277 ; CHECK-NEXT: [[TMP:%.*]] = load i64, ptr [[SOURCE]], align 8
278 ; CHECK-NEXT: [[CALL:%.*]] = call i64 @func_v4f32(i64 [[TMP]]) #[[ATTR1]]
279 ; CHECK-NEXT: store i64 [[CALL]], ptr [[DEST]], align 8
280 ; CHECK-NEXT: ret void
283 %tmp = load i64, ptr %source, align 8
284 %call = call i64 @func_v4f32(i64 %tmp) nounwind
285 store i64 %call, ptr %dest, align 8