xref: /llvm-project/clang/test/CodeGen/AArch64/poly128.c (revision 207e5ccceec8d3cc3f32723e78f2a142bc61b07d)
1 // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --function-signature
2 // RUN: %clang_cc1 -triple arm64-none-linux-gnu -target-feature +neon \
3 // RUN: -disable-O0-optnone -ffp-contract=fast -emit-llvm -o - %s | opt -S -passes=mem2reg \
4 // RUN:  | FileCheck %s
5 
6 // REQUIRES: aarch64-registered-target
7 
8 // Test new aarch64 intrinsics with poly128
9 // FIXME: Currently, poly128_t equals to uint128, which will be spilt into
10 // two 64-bit GPR(eg X0, X1). Now moving data from X0, X1 to FPR128 will
11 // introduce 2 store and 1 load instructions(store X0, X1 to memory and
12 // then load back to Q0). If target has NEON, this is better replaced by
13 // FMOV or INS.
14 
15 #include <arm_neon.h>
16 
17 // CHECK-LABEL: define {{[^@]+}}@test_vstrq_p128
18 // CHECK-SAME: (ptr noundef [[PTR:%.*]], i128 noundef [[VAL:%.*]]) #[[ATTR0:[0-9]+]] {
19 // CHECK-NEXT:  entry:
20 // CHECK-NEXT:    store i128 [[VAL]], ptr [[PTR]], align 16
21 // CHECK-NEXT:    ret void
22 //
23 void test_vstrq_p128(poly128_t * ptr, poly128_t val) {
24   vstrq_p128(ptr, val);
25 
26 }
27 
28 // CHECK-LABEL: define {{[^@]+}}@test_vldrq_p128
29 // CHECK-SAME: (ptr noundef [[PTR:%.*]]) #[[ATTR0]] {
30 // CHECK-NEXT:  entry:
31 // CHECK-NEXT:    [[TMP0:%.*]] = load i128, ptr [[PTR]], align 16
32 // CHECK-NEXT:    ret i128 [[TMP0]]
33 //
34 poly128_t test_vldrq_p128(poly128_t * ptr) {
35   return vldrq_p128(ptr);
36 
37 }
38 
39 // CHECK-LABEL: define {{[^@]+}}@test_ld_st_p128
40 // CHECK-SAME: (ptr noundef [[PTR:%.*]]) #[[ATTR0]] {
41 // CHECK-NEXT:  entry:
42 // CHECK-NEXT:    [[TMP0:%.*]] = load i128, ptr [[PTR]], align 16
43 // CHECK-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i128, ptr [[PTR]], i64 1
44 // CHECK-NEXT:    store i128 [[TMP0]], ptr [[ADD_PTR]], align 16
45 // CHECK-NEXT:    ret void
46 //
47 void test_ld_st_p128(poly128_t * ptr) {
48    vstrq_p128(ptr+1, vldrq_p128(ptr));
49 
50 }
51 
52 // CHECK-LABEL: define {{[^@]+}}@test_vmull_p64
53 // CHECK-SAME: (i64 noundef [[A:%.*]], i64 noundef [[B:%.*]]) #[[ATTR1:[0-9]+]] {
54 // CHECK-NEXT:  entry:
55 // CHECK-NEXT:    [[VMULL_P64_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.pmull64(i64 [[A]], i64 [[B]])
56 // CHECK-NEXT:    [[VMULL_P641_I:%.*]] = bitcast <16 x i8> [[VMULL_P64_I]] to i128
57 // CHECK-NEXT:    ret i128 [[VMULL_P641_I]]
58 //
59 __attribute__((target("aes"))) poly128_t test_vmull_p64(poly64_t a, poly64_t b) {
60   return vmull_p64(a, b);
61 }
62 
63 // CHECK-LABEL: define {{[^@]+}}@test_vmull_high_p64
64 // CHECK-SAME: (<2 x i64> noundef [[A:%.*]], <2 x i64> noundef [[B:%.*]]) #[[ATTR2:[0-9]+]] {
65 // CHECK-NEXT:  entry:
66 // CHECK-NEXT:    [[SHUFFLE_I5:%.*]] = shufflevector <2 x i64> [[A]], <2 x i64> [[A]], <1 x i32> <i32 1>
67 // CHECK-NEXT:    [[TMP0:%.*]] = bitcast <1 x i64> [[SHUFFLE_I5]] to i64
68 // CHECK-NEXT:    [[SHUFFLE_I:%.*]] = shufflevector <2 x i64> [[B]], <2 x i64> [[B]], <1 x i32> <i32 1>
69 // CHECK-NEXT:    [[TMP1:%.*]] = bitcast <1 x i64> [[SHUFFLE_I]] to i64
70 // CHECK-NEXT:    [[VMULL_P64_I_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.pmull64(i64 [[TMP0]], i64 [[TMP1]])
71 // CHECK-NEXT:    [[VMULL_P641_I_I:%.*]] = bitcast <16 x i8> [[VMULL_P64_I_I]] to i128
72 // CHECK-NEXT:    ret i128 [[VMULL_P641_I_I]]
73 //
74 __attribute__((target("aes"))) poly128_t test_vmull_high_p64(poly64x2_t a, poly64x2_t b) {
75   return vmull_high_p64(a, b);
76 }
77 
78 // CHECK-LABEL: define {{[^@]+}}@test_vreinterpretq_p128_s8
79 // CHECK-SAME: (<16 x i8> noundef [[A:%.*]]) #[[ATTR3:[0-9]+]] {
80 // CHECK-NEXT:  entry:
81 // CHECK-NEXT:    [[TMP0:%.*]] = bitcast <16 x i8> [[A]] to i128
82 // CHECK-NEXT:    ret i128 [[TMP0]]
83 //
84 poly128_t test_vreinterpretq_p128_s8(int8x16_t a) {
85   return vreinterpretq_p128_s8(a);
86 }
87 
88 // CHECK-LABEL: define {{[^@]+}}@test_vreinterpretq_p128_s16
89 // CHECK-SAME: (<8 x i16> noundef [[A:%.*]]) #[[ATTR3]] {
90 // CHECK-NEXT:  entry:
91 // CHECK-NEXT:    [[TMP0:%.*]] = bitcast <8 x i16> [[A]] to i128
92 // CHECK-NEXT:    ret i128 [[TMP0]]
93 //
94 poly128_t test_vreinterpretq_p128_s16(int16x8_t a) {
95   return vreinterpretq_p128_s16(a);
96 }
97 
98 // CHECK-LABEL: define {{[^@]+}}@test_vreinterpretq_p128_s32
99 // CHECK-SAME: (<4 x i32> noundef [[A:%.*]]) #[[ATTR3]] {
100 // CHECK-NEXT:  entry:
101 // CHECK-NEXT:    [[TMP0:%.*]] = bitcast <4 x i32> [[A]] to i128
102 // CHECK-NEXT:    ret i128 [[TMP0]]
103 //
104 poly128_t test_vreinterpretq_p128_s32(int32x4_t a) {
105   return vreinterpretq_p128_s32(a);
106 }
107 
108 // CHECK-LABEL: define {{[^@]+}}@test_vreinterpretq_p128_s64
109 // CHECK-SAME: (<2 x i64> noundef [[A:%.*]]) #[[ATTR3]] {
110 // CHECK-NEXT:  entry:
111 // CHECK-NEXT:    [[TMP0:%.*]] = bitcast <2 x i64> [[A]] to i128
112 // CHECK-NEXT:    ret i128 [[TMP0]]
113 //
114 poly128_t test_vreinterpretq_p128_s64(int64x2_t a) {
115   return vreinterpretq_p128_s64(a);
116 }
117 
118 // CHECK-LABEL: define {{[^@]+}}@test_vreinterpretq_p128_u8
119 // CHECK-SAME: (<16 x i8> noundef [[A:%.*]]) #[[ATTR3]] {
120 // CHECK-NEXT:  entry:
121 // CHECK-NEXT:    [[TMP0:%.*]] = bitcast <16 x i8> [[A]] to i128
122 // CHECK-NEXT:    ret i128 [[TMP0]]
123 //
124 poly128_t test_vreinterpretq_p128_u8(uint8x16_t a) {
125   return vreinterpretq_p128_u8(a);
126 }
127 
128 // CHECK-LABEL: define {{[^@]+}}@test_vreinterpretq_p128_u16
129 // CHECK-SAME: (<8 x i16> noundef [[A:%.*]]) #[[ATTR3]] {
130 // CHECK-NEXT:  entry:
131 // CHECK-NEXT:    [[TMP0:%.*]] = bitcast <8 x i16> [[A]] to i128
132 // CHECK-NEXT:    ret i128 [[TMP0]]
133 //
134 poly128_t test_vreinterpretq_p128_u16(uint16x8_t a) {
135   return vreinterpretq_p128_u16(a);
136 }
137 
138 // CHECK-LABEL: define {{[^@]+}}@test_vreinterpretq_p128_u32
139 // CHECK-SAME: (<4 x i32> noundef [[A:%.*]]) #[[ATTR3]] {
140 // CHECK-NEXT:  entry:
141 // CHECK-NEXT:    [[TMP0:%.*]] = bitcast <4 x i32> [[A]] to i128
142 // CHECK-NEXT:    ret i128 [[TMP0]]
143 //
144 poly128_t test_vreinterpretq_p128_u32(uint32x4_t a) {
145   return vreinterpretq_p128_u32(a);
146 }
147 
148 // CHECK-LABEL: define {{[^@]+}}@test_vreinterpretq_p128_u64
149 // CHECK-SAME: (<2 x i64> noundef [[A:%.*]]) #[[ATTR3]] {
150 // CHECK-NEXT:  entry:
151 // CHECK-NEXT:    [[TMP0:%.*]] = bitcast <2 x i64> [[A]] to i128
152 // CHECK-NEXT:    ret i128 [[TMP0]]
153 //
154 poly128_t test_vreinterpretq_p128_u64(uint64x2_t a) {
155   return vreinterpretq_p128_u64(a);
156 }
157 
158 // CHECK-LABEL: define {{[^@]+}}@test_vreinterpretq_p128_f32
159 // CHECK-SAME: (<4 x float> noundef [[A:%.*]]) #[[ATTR3]] {
160 // CHECK-NEXT:  entry:
161 // CHECK-NEXT:    [[TMP0:%.*]] = bitcast <4 x float> [[A]] to i128
162 // CHECK-NEXT:    ret i128 [[TMP0]]
163 //
164 poly128_t test_vreinterpretq_p128_f32(float32x4_t a) {
165   return vreinterpretq_p128_f32(a);
166 }
167 
168 // CHECK-LABEL: define {{[^@]+}}@test_vreinterpretq_p128_f64
169 // CHECK-SAME: (<2 x double> noundef [[A:%.*]]) #[[ATTR3]] {
170 // CHECK-NEXT:  entry:
171 // CHECK-NEXT:    [[TMP0:%.*]] = bitcast <2 x double> [[A]] to i128
172 // CHECK-NEXT:    ret i128 [[TMP0]]
173 //
174 poly128_t test_vreinterpretq_p128_f64(float64x2_t a) {
175   return vreinterpretq_p128_f64(a);
176 }
177 
178 // CHECK-LABEL: define {{[^@]+}}@test_vreinterpretq_p128_p8
179 // CHECK-SAME: (<16 x i8> noundef [[A:%.*]]) #[[ATTR3]] {
180 // CHECK-NEXT:  entry:
181 // CHECK-NEXT:    [[TMP0:%.*]] = bitcast <16 x i8> [[A]] to i128
182 // CHECK-NEXT:    ret i128 [[TMP0]]
183 //
184 poly128_t test_vreinterpretq_p128_p8(poly8x16_t a) {
185   return vreinterpretq_p128_p8(a);
186 }
187 
188 // CHECK-LABEL: define {{[^@]+}}@test_vreinterpretq_p128_p16
189 // CHECK-SAME: (<8 x i16> noundef [[A:%.*]]) #[[ATTR3]] {
190 // CHECK-NEXT:  entry:
191 // CHECK-NEXT:    [[TMP0:%.*]] = bitcast <8 x i16> [[A]] to i128
192 // CHECK-NEXT:    ret i128 [[TMP0]]
193 //
194 poly128_t test_vreinterpretq_p128_p16(poly16x8_t a) {
195   return vreinterpretq_p128_p16(a);
196 }
197 
198 // CHECK-LABEL: define {{[^@]+}}@test_vreinterpretq_p128_p64
199 // CHECK-SAME: (<2 x i64> noundef [[A:%.*]]) #[[ATTR3]] {
200 // CHECK-NEXT:  entry:
201 // CHECK-NEXT:    [[TMP0:%.*]] = bitcast <2 x i64> [[A]] to i128
202 // CHECK-NEXT:    ret i128 [[TMP0]]
203 //
204 poly128_t test_vreinterpretq_p128_p64(poly64x2_t a) {
205   return vreinterpretq_p128_p64(a);
206 }
207 
208 // CHECK-LABEL: define {{[^@]+}}@test_vreinterpretq_s8_p128
209 // CHECK-SAME: (i128 noundef [[A:%.*]]) #[[ATTR3]] {
210 // CHECK-NEXT:  entry:
211 // CHECK-NEXT:    [[TMP0:%.*]] = bitcast i128 [[A]] to <16 x i8>
212 // CHECK-NEXT:    ret <16 x i8> [[TMP0]]
213 //
214 int8x16_t test_vreinterpretq_s8_p128(poly128_t a) {
215   return vreinterpretq_s8_p128(a);
216 }
217 
218 // CHECK-LABEL: define {{[^@]+}}@test_vreinterpretq_s16_p128
219 // CHECK-SAME: (i128 noundef [[A:%.*]]) #[[ATTR3]] {
220 // CHECK-NEXT:  entry:
221 // CHECK-NEXT:    [[TMP0:%.*]] = bitcast i128 [[A]] to <8 x i16>
222 // CHECK-NEXT:    ret <8 x i16> [[TMP0]]
223 //
224 int16x8_t test_vreinterpretq_s16_p128(poly128_t  a) {
225   return vreinterpretq_s16_p128(a);
226 }
227 
228 // CHECK-LABEL: define {{[^@]+}}@test_vreinterpretq_s32_p128
229 // CHECK-SAME: (i128 noundef [[A:%.*]]) #[[ATTR3]] {
230 // CHECK-NEXT:  entry:
231 // CHECK-NEXT:    [[TMP0:%.*]] = bitcast i128 [[A]] to <4 x i32>
232 // CHECK-NEXT:    ret <4 x i32> [[TMP0]]
233 //
234 int32x4_t test_vreinterpretq_s32_p128(poly128_t a) {
235   return vreinterpretq_s32_p128(a);
236 }
237 
238 // CHECK-LABEL: define {{[^@]+}}@test_vreinterpretq_s64_p128
239 // CHECK-SAME: (i128 noundef [[A:%.*]]) #[[ATTR3]] {
240 // CHECK-NEXT:  entry:
241 // CHECK-NEXT:    [[TMP0:%.*]] = bitcast i128 [[A]] to <2 x i64>
242 // CHECK-NEXT:    ret <2 x i64> [[TMP0]]
243 //
244 int64x2_t test_vreinterpretq_s64_p128(poly128_t  a) {
245   return vreinterpretq_s64_p128(a);
246 }
247 
248 // CHECK-LABEL: define {{[^@]+}}@test_vreinterpretq_u8_p128
249 // CHECK-SAME: (i128 noundef [[A:%.*]]) #[[ATTR3]] {
250 // CHECK-NEXT:  entry:
251 // CHECK-NEXT:    [[TMP0:%.*]] = bitcast i128 [[A]] to <16 x i8>
252 // CHECK-NEXT:    ret <16 x i8> [[TMP0]]
253 //
254 uint8x16_t test_vreinterpretq_u8_p128(poly128_t  a) {
255   return vreinterpretq_u8_p128(a);
256 }
257 
258 // CHECK-LABEL: define {{[^@]+}}@test_vreinterpretq_u16_p128
259 // CHECK-SAME: (i128 noundef [[A:%.*]]) #[[ATTR3]] {
260 // CHECK-NEXT:  entry:
261 // CHECK-NEXT:    [[TMP0:%.*]] = bitcast i128 [[A]] to <8 x i16>
262 // CHECK-NEXT:    ret <8 x i16> [[TMP0]]
263 //
264 uint16x8_t test_vreinterpretq_u16_p128(poly128_t  a) {
265   return vreinterpretq_u16_p128(a);
266 }
267 
268 // CHECK-LABEL: define {{[^@]+}}@test_vreinterpretq_u32_p128
269 // CHECK-SAME: (i128 noundef [[A:%.*]]) #[[ATTR3]] {
270 // CHECK-NEXT:  entry:
271 // CHECK-NEXT:    [[TMP0:%.*]] = bitcast i128 [[A]] to <4 x i32>
272 // CHECK-NEXT:    ret <4 x i32> [[TMP0]]
273 //
274 uint32x4_t test_vreinterpretq_u32_p128(poly128_t  a) {
275   return vreinterpretq_u32_p128(a);
276 }
277 
278 // CHECK-LABEL: define {{[^@]+}}@test_vreinterpretq_u64_p128
279 // CHECK-SAME: (i128 noundef [[A:%.*]]) #[[ATTR3]] {
280 // CHECK-NEXT:  entry:
281 // CHECK-NEXT:    [[TMP0:%.*]] = bitcast i128 [[A]] to <2 x i64>
282 // CHECK-NEXT:    ret <2 x i64> [[TMP0]]
283 //
284 uint64x2_t test_vreinterpretq_u64_p128(poly128_t  a) {
285   return vreinterpretq_u64_p128(a);
286 }
287 
288 // CHECK-LABEL: define {{[^@]+}}@test_vreinterpretq_f32_p128
289 // CHECK-SAME: (i128 noundef [[A:%.*]]) #[[ATTR3]] {
290 // CHECK-NEXT:  entry:
291 // CHECK-NEXT:    [[TMP0:%.*]] = bitcast i128 [[A]] to <4 x float>
292 // CHECK-NEXT:    ret <4 x float> [[TMP0]]
293 //
294 float32x4_t test_vreinterpretq_f32_p128(poly128_t  a) {
295   return vreinterpretq_f32_p128(a);
296 }
297 
298 // CHECK-LABEL: define {{[^@]+}}@test_vreinterpretq_f64_p128
299 // CHECK-SAME: (i128 noundef [[A:%.*]]) #[[ATTR3]] {
300 // CHECK-NEXT:  entry:
301 // CHECK-NEXT:    [[TMP0:%.*]] = bitcast i128 [[A]] to <2 x double>
302 // CHECK-NEXT:    ret <2 x double> [[TMP0]]
303 //
304 float64x2_t test_vreinterpretq_f64_p128(poly128_t  a) {
305   return vreinterpretq_f64_p128(a);
306 }
307 
308 // CHECK-LABEL: define {{[^@]+}}@test_vreinterpretq_p8_p128
309 // CHECK-SAME: (i128 noundef [[A:%.*]]) #[[ATTR3]] {
310 // CHECK-NEXT:  entry:
311 // CHECK-NEXT:    [[TMP0:%.*]] = bitcast i128 [[A]] to <16 x i8>
312 // CHECK-NEXT:    ret <16 x i8> [[TMP0]]
313 //
314 poly8x16_t test_vreinterpretq_p8_p128(poly128_t  a) {
315   return vreinterpretq_p8_p128(a);
316 }
317 
318 // CHECK-LABEL: define {{[^@]+}}@test_vreinterpretq_p16_p128
319 // CHECK-SAME: (i128 noundef [[A:%.*]]) #[[ATTR3]] {
320 // CHECK-NEXT:  entry:
321 // CHECK-NEXT:    [[TMP0:%.*]] = bitcast i128 [[A]] to <8 x i16>
322 // CHECK-NEXT:    ret <8 x i16> [[TMP0]]
323 //
324 poly16x8_t test_vreinterpretq_p16_p128(poly128_t  a) {
325   return vreinterpretq_p16_p128(a);
326 }
327 
328 // CHECK-LABEL: define {{[^@]+}}@test_vreinterpretq_p64_p128
329 // CHECK-SAME: (i128 noundef [[A:%.*]]) #[[ATTR3]] {
330 // CHECK-NEXT:  entry:
331 // CHECK-NEXT:    [[TMP0:%.*]] = bitcast i128 [[A]] to <2 x i64>
332 // CHECK-NEXT:    ret <2 x i64> [[TMP0]]
333 //
334 poly64x2_t test_vreinterpretq_p64_p128(poly128_t  a) {
335   return vreinterpretq_p64_p128(a);
336 }
337