• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +bf16 -ffreestanding -fsyntax-only -verify -msve-vector-bits=128 -fallow-half-arguments-and-returns %s
2 // RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +bf16 -ffreestanding -fsyntax-only -verify -msve-vector-bits=256 -fallow-half-arguments-and-returns %s
3 // RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +bf16 -ffreestanding -fsyntax-only -verify -msve-vector-bits=512 -fallow-half-arguments-and-returns %s
4 // RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +bf16 -ffreestanding -fsyntax-only -verify -msve-vector-bits=1024 -fallow-half-arguments-and-returns %s
5 // RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +bf16 -ffreestanding -fsyntax-only -verify -msve-vector-bits=2048 -fallow-half-arguments-and-returns %s
6 
7 #include <stdint.h>
8 
9 #define N __ARM_FEATURE_SVE_BITS
10 
11 typedef __fp16 float16_t;
12 typedef float float32_t;
13 typedef double float64_t;
14 typedef __SVInt8_t svint8_t;
15 typedef __SVInt16_t svint16_t;
16 typedef __SVInt32_t svint32_t;
17 typedef __SVInt64_t svint64_t;
18 typedef __SVUint8_t svuint8_t;
19 typedef __SVUint16_t svuint16_t;
20 typedef __SVUint32_t svuint32_t;
21 typedef __SVUint64_t svuint64_t;
22 typedef __SVFloat16_t svfloat16_t;
23 typedef __SVFloat32_t svfloat32_t;
24 typedef __SVFloat64_t svfloat64_t;
25 
26 #if defined(__ARM_FEATURE_SVE_BF16)
27 typedef __bf16 bfloat16_t;
28 typedef __SVBFloat16_t svbfloat16_t;
29 #endif
30 
31 typedef __SVBool_t svbool_t;
32 
33 // Define valid fixed-width SVE types
34 typedef svint8_t fixed_int8_t __attribute__((arm_sve_vector_bits(N)));
35 typedef svint16_t fixed_int16_t __attribute__((arm_sve_vector_bits(N)));
36 typedef svint32_t fixed_int32_t __attribute__((arm_sve_vector_bits(N)));
37 typedef svint64_t fixed_int64_t __attribute__((arm_sve_vector_bits(N)));
38 
39 typedef svuint8_t fixed_uint8_t __attribute__((arm_sve_vector_bits(N)));
40 typedef svuint16_t fixed_uint16_t __attribute__((arm_sve_vector_bits(N)));
41 typedef svuint32_t fixed_uint32_t __attribute__((arm_sve_vector_bits(N)));
42 typedef svuint64_t fixed_uint64_t __attribute__((arm_sve_vector_bits(N)));
43 
44 typedef svfloat16_t fixed_float16_t __attribute__((arm_sve_vector_bits(N)));
45 typedef svfloat32_t fixed_float32_t __attribute__((arm_sve_vector_bits(N)));
46 typedef svfloat64_t fixed_float64_t __attribute__((arm_sve_vector_bits(N)));
47 
48 typedef svbfloat16_t fixed_bfloat16_t __attribute__((arm_sve_vector_bits(N)));
49 
50 typedef svbool_t fixed_bool_t __attribute__((arm_sve_vector_bits(N)));
51 
52 // GNU vector types
53 typedef int8_t gnu_int8_t __attribute__((vector_size(N / 8)));
54 typedef int16_t gnu_int16_t __attribute__((vector_size(N / 8)));
55 typedef int32_t gnu_int32_t __attribute__((vector_size(N / 8)));
56 typedef int64_t gnu_int64_t __attribute__((vector_size(N / 8)));
57 
58 typedef uint8_t gnu_uint8_t __attribute__((vector_size(N / 8)));
59 typedef uint16_t gnu_uint16_t __attribute__((vector_size(N / 8)));
60 typedef uint32_t gnu_uint32_t __attribute__((vector_size(N / 8)));
61 typedef uint64_t gnu_uint64_t __attribute__((vector_size(N / 8)));
62 
63 typedef float16_t gnu_float16_t __attribute__((vector_size(N / 8)));
64 typedef float32_t gnu_float32_t __attribute__((vector_size(N / 8)));
65 typedef float64_t gnu_float64_t __attribute__((vector_size(N / 8)));
66 
67 typedef bfloat16_t gnu_bfloat16_t __attribute__((vector_size(N / 8)));
68 
69 // Attribute must have a single argument
70 typedef svint8_t no_argument __attribute__((arm_sve_vector_bits));         // expected-error {{'arm_sve_vector_bits' attribute takes one argument}}
71 typedef svint8_t two_arguments __attribute__((arm_sve_vector_bits(2, 4))); // expected-error {{'arm_sve_vector_bits' attribute takes one argument}}
72 
73 // The number of SVE vector bits must be an integer constant expression
74 typedef svint8_t non_int_size1 __attribute__((arm_sve_vector_bits(2.0)));   // expected-error {{'arm_sve_vector_bits' attribute requires an integer constant}}
75 typedef svint8_t non_int_size2 __attribute__((arm_sve_vector_bits("256"))); // expected-error {{'arm_sve_vector_bits' attribute requires an integer constant}}
76 
77 typedef __clang_svint8x2_t svint8x2_t;
78 typedef __clang_svfloat32x3_t svfloat32x3_t;
79 
80 // Attribute must be attached to a single SVE vector or predicate type.
81 typedef void *badtype1 __attribute__((arm_sve_vector_bits(N)));         // expected-error {{'arm_sve_vector_bits' attribute applied to non-SVE type 'void *'}}
82 typedef int badtype2 __attribute__((arm_sve_vector_bits(N)));           // expected-error {{'arm_sve_vector_bits' attribute applied to non-SVE type 'int'}}
83 typedef float badtype3 __attribute__((arm_sve_vector_bits(N)));         // expected-error {{'arm_sve_vector_bits' attribute applied to non-SVE type 'float'}}
84 typedef svint8x2_t badtype4 __attribute__((arm_sve_vector_bits(N)));    // expected-error {{'arm_sve_vector_bits' attribute applied to non-SVE type 'svint8x2_t' (aka '__clang_svint8x2_t')}}
85 typedef svfloat32x3_t badtype5 __attribute__((arm_sve_vector_bits(N))); // expected-error {{'arm_sve_vector_bits' attribute applied to non-SVE type 'svfloat32x3_t' (aka '__clang_svfloat32x3_t')}}
86 
87 // Attribute only applies to typedefs.
88 svint8_t non_typedef_type __attribute__((arm_sve_vector_bits(N)));  // expected-error {{'arm_sve_vector_bits' attribute only applies to typedefs}}
89 
90 // Test that we can define non-local fixed-length SVE types (unsupported for
91 // sizeless types).
92 fixed_int8_t global_int8;
93 fixed_bfloat16_t global_bfloat16;
94 fixed_bool_t global_bool;
95 
96 extern fixed_int8_t extern_int8;
97 extern fixed_bfloat16_t extern_bfloat16;
98 extern fixed_bool_t extern_bool;
99 
100 static fixed_int8_t static_int8;
101 static fixed_bfloat16_t static_bfloat16;
102 static fixed_bool_t static_bool;
103 
104 fixed_int8_t *global_int8_ptr;
105 extern fixed_int8_t *extern_int8_ptr;
106 static fixed_int8_t *static_int8_ptr;
107 __thread fixed_int8_t thread_int8;
108 
109 typedef fixed_int8_t int8_typedef;
110 typedef fixed_int8_t *int8_ptr_typedef;
111 
112 // Test sized expressions
113 int sizeof_int8 = sizeof(global_int8);
114 int sizeof_int8_var = sizeof(*global_int8_ptr);
115 int sizeof_int8_var_ptr = sizeof(global_int8_ptr);
116 
117 extern fixed_int8_t *extern_int8_ptr;
118 
119 int alignof_int8 = __alignof__(extern_int8);
120 int alignof_int8_var = __alignof__(*extern_int8_ptr);
121 int alignof_int8_var_ptr = __alignof__(extern_int8_ptr);
122 
f(int c)123 void f(int c) {
124   fixed_int8_t fs8;
125   svint8_t ss8;
126   gnu_int8_t gs8;
127 
128   // Check conditional expressions where the result is ambiguous are
129   // ill-formed.
130   void *sel __attribute__((unused));
131   sel = c ? ss8 : fs8; // expected-error {{cannot combine fixed-length and sizeless SVE vectors in expression, result is ambiguous}}
132   sel = c ? fs8 : ss8; // expected-error {{cannot combine fixed-length and sizeless SVE vectors in expression, result is ambiguous}}
133 
134   sel = c ? gs8 : ss8; // expected-error {{cannot combine GNU and SVE vectors in expression, result is ambiguous}}
135   sel = c ? ss8 : gs8; // expected-error {{cannot combine GNU and SVE vectors in expression, result is ambiguous}}
136 
137   sel = c ? gs8 : fs8; // expected-error {{cannot combine GNU and SVE vectors in expression, result is ambiguous}}
138   sel = c ? fs8 : gs8; // expected-error {{cannot combine GNU and SVE vectors in expression, result is ambiguous}}
139 
140   // Check binary expressions where the result is ambiguous are ill-formed.
141   ss8 = ss8 + fs8; // expected-error {{cannot combine fixed-length and sizeless SVE vectors in expression, result is ambiguous}}
142   ss8 = ss8 + gs8; // expected-error {{cannot combine GNU and SVE vectors in expression, result is ambiguous}}
143 
144   fs8 = fs8 + ss8; // expected-error {{cannot combine fixed-length and sizeless SVE vectors in expression, result is ambiguous}}
145   fs8 = fs8 + gs8; // expected-error {{cannot combine GNU and SVE vectors in expression, result is ambiguous}}
146 
147   gs8 = gs8 + ss8; // expected-error {{cannot combine GNU and SVE vectors in expression, result is ambiguous}}
148   gs8 = gs8 + fs8; // expected-error {{cannot combine GNU and SVE vectors in expression, result is ambiguous}}
149 
150   ss8 += fs8; // expected-error {{cannot combine fixed-length and sizeless SVE vectors in expression, result is ambiguous}}
151   ss8 += gs8; // expected-error {{cannot combine GNU and SVE vectors in expression, result is ambiguous}}
152 
153   fs8 += ss8; // expected-error {{cannot combine fixed-length and sizeless SVE vectors in expression, result is ambiguous}}
154   fs8 += gs8; // expected-error {{cannot combine GNU and SVE vectors in expression, result is ambiguous}}
155 
156   gs8 += ss8; // expected-error {{cannot combine GNU and SVE vectors in expression, result is ambiguous}}
157   gs8 += fs8; // expected-error {{cannot combine GNU and SVE vectors in expression, result is ambiguous}}
158 
159   ss8 = ss8 == fs8; // expected-error {{cannot combine fixed-length and sizeless SVE vectors in expression, result is ambiguous}}
160   ss8 = ss8 == gs8; // expected-error {{cannot combine GNU and SVE vectors in expression, result is ambiguous}}
161 
162   fs8 = fs8 == ss8; // expected-error {{cannot combine fixed-length and sizeless SVE vectors in expression, result is ambiguous}}
163   fs8 = fs8 == gs8; // expected-error {{cannot combine GNU and SVE vectors in expression, result is ambiguous}}
164 
165   gs8 = gs8 == ss8; // expected-error {{cannot combine GNU and SVE vectors in expression, result is ambiguous}}
166   gs8 = gs8 == fs8; // expected-error {{cannot combine GNU and SVE vectors in expression, result is ambiguous}}
167 
168   ss8 = ss8 & fs8; // expected-error {{invalid operands to binary expression}}
169   ss8 = ss8 & gs8; // expected-error {{invalid operands to binary expression}}
170 
171   fs8 = fs8 & ss8; // expected-error {{invalid operands to binary expression}}
172   fs8 = fs8 & gs8; // expected-error {{cannot combine GNU and SVE vectors in expression, result is ambiguous}}
173 
174   gs8 = gs8 & ss8; // expected-error {{invalid operands to binary expression}}
175   gs8 = gs8 & fs8; // expected-error {{cannot combine GNU and SVE vectors in expression, result is ambiguous}}
176 }
177 
178 // --------------------------------------------------------------------------//
179 // Sizeof
180 
181 #define VECTOR_SIZE ((N / 8))
182 #define PRED_SIZE ((N / 64))
183 
184 _Static_assert(sizeof(fixed_int8_t) == VECTOR_SIZE, "");
185 
186 _Static_assert(sizeof(fixed_int16_t) == VECTOR_SIZE, "");
187 _Static_assert(sizeof(fixed_int32_t) == VECTOR_SIZE, "");
188 _Static_assert(sizeof(fixed_int64_t) == VECTOR_SIZE, "");
189 
190 _Static_assert(sizeof(fixed_uint8_t) == VECTOR_SIZE, "");
191 _Static_assert(sizeof(fixed_uint16_t) == VECTOR_SIZE, "");
192 _Static_assert(sizeof(fixed_uint32_t) == VECTOR_SIZE, "");
193 _Static_assert(sizeof(fixed_uint64_t) == VECTOR_SIZE, "");
194 
195 _Static_assert(sizeof(fixed_float16_t) == VECTOR_SIZE, "");
196 _Static_assert(sizeof(fixed_float32_t) == VECTOR_SIZE, "");
197 _Static_assert(sizeof(fixed_float64_t) == VECTOR_SIZE, "");
198 
199 _Static_assert(sizeof(fixed_bfloat16_t) == VECTOR_SIZE, "");
200 
201 _Static_assert(sizeof(fixed_bool_t) == PRED_SIZE, "");
202 
203 // --------------------------------------------------------------------------//
204 // Alignof
205 
206 #define VECTOR_ALIGN 16
207 #define PRED_ALIGN 2
208 
209 _Static_assert(__alignof__(fixed_int8_t) == VECTOR_ALIGN, "");
210 _Static_assert(__alignof__(fixed_int16_t) == VECTOR_ALIGN, "");
211 _Static_assert(__alignof__(fixed_int32_t) == VECTOR_ALIGN, "");
212 _Static_assert(__alignof__(fixed_int64_t) == VECTOR_ALIGN, "");
213 
214 _Static_assert(__alignof__(fixed_uint8_t) == VECTOR_ALIGN, "");
215 _Static_assert(__alignof__(fixed_uint16_t) == VECTOR_ALIGN, "");
216 _Static_assert(__alignof__(fixed_uint32_t) == VECTOR_ALIGN, "");
217 _Static_assert(__alignof__(fixed_uint64_t) == VECTOR_ALIGN, "");
218 
219 _Static_assert(__alignof__(fixed_float16_t) == VECTOR_ALIGN, "");
220 _Static_assert(__alignof__(fixed_float32_t) == VECTOR_ALIGN, "");
221 _Static_assert(__alignof__(fixed_float64_t) == VECTOR_ALIGN, "");
222 
223 _Static_assert(__alignof__(fixed_bfloat16_t) == VECTOR_ALIGN, "");
224 
225 _Static_assert(__alignof__(fixed_bool_t) == PRED_ALIGN, "");
226 
227 // --------------------------------------------------------------------------//
228 // Structs
229 
230 struct struct_int64 { fixed_int64_t x, y[5]; };
231 struct struct_float64 { fixed_float64_t x, y[5]; };
232 struct struct_bfloat16 { fixed_bfloat16_t x, y[5]; };
233 struct struct_bool { fixed_bool_t x, y[5]; };
234 
235 // --------------------------------------------------------------------------//
236 // Unions
237 union union_int64 { fixed_int64_t x, y[5]; };
238 union union_float64 { fixed_float64_t x, y[5]; };
239 union union_bfloat16 { fixed_bfloat16_t x, y[5]; };
240 union union_bool { fixed_bool_t x, y[5]; };
241 
242 // --------------------------------------------------------------------------//
243 // Implicit casts
244 
245 #define TEST_CAST_COMMON(TYPE)                                              \
246   sv##TYPE##_t to_sv##TYPE##_t_from_fixed(fixed_##TYPE##_t x) { return x; } \
247   fixed_##TYPE##_t from_sv##TYPE##_t_to_fixed(sv##TYPE##_t x) { return x; }
248 
249 #define TEST_CAST_GNU(PREFIX, TYPE)                                                          \
250   gnu_##TYPE##_t to_gnu_##TYPE##_t_from_##PREFIX##TYPE##_t(PREFIX##TYPE##_t x) { return x; } \
251   PREFIX##TYPE##_t from_gnu_##TYPE##_t_to_##PREFIX##TYPE##_t(gnu_##TYPE##_t x) { return x; }
252 
253 #define TEST_CAST_VECTOR(TYPE) \
254   TEST_CAST_COMMON(TYPE)       \
255   TEST_CAST_GNU(sv, TYPE)      \
256   TEST_CAST_GNU(fixed_, TYPE)
257 
258 TEST_CAST_VECTOR(int8)
TEST_CAST_VECTOR(int16)259 TEST_CAST_VECTOR(int16)
260 TEST_CAST_VECTOR(int32)
261 TEST_CAST_VECTOR(int64)
262 TEST_CAST_VECTOR(uint8)
263 TEST_CAST_VECTOR(uint16)
264 TEST_CAST_VECTOR(uint32)
265 TEST_CAST_VECTOR(uint64)
266 TEST_CAST_VECTOR(float16)
267 TEST_CAST_VECTOR(float32)
268 TEST_CAST_VECTOR(float64)
269 TEST_CAST_VECTOR(bfloat16)
270 TEST_CAST_COMMON(bool)
271 
272 // Test the implicit conversion only applies to valid types
273 fixed_bool_t to_fixed_bool_t__from_svint32_t(svint32_t x) { return x; } // expected-error-re {{returning 'svint32_t' (aka '__SVInt32_t') from a function with incompatible result type 'fixed_bool_t' (vector of {{[0-9]+}} 'unsigned char' values)}}
274 
275 // Test implicit conversion between SVE and GNU vector is invalid when
276 // __ARM_FEATURE_SVE_BITS != N
277 #if defined(__ARM_FEATURE_SVE_BITS) && __ARM_FEATURE_SVE_BITS == 512
278 typedef int32_t int4 __attribute__((vector_size(16)));
badcast(int4 x)279 svint32_t badcast(int4 x) { return x; } // expected-error {{returning 'int4' (vector of 4 'int32_t' values) from a function with incompatible result type 'svint32_t' (aka '__SVInt32_t')}}
280 #endif
281 
282 // Test conversion between predicate and uint8 is invalid, both have the same
283 // memory representation.
to_fixed_bool_t__from_svuint8_t(svuint8_t x)284 fixed_bool_t to_fixed_bool_t__from_svuint8_t(svuint8_t x) { return x; } // expected-error-re {{returning 'svuint8_t' (aka '__SVUint8_t') from a function with incompatible result type 'fixed_bool_t' (vector of {{[0-9]+}} 'unsigned char' values)}}
285 
286 // --------------------------------------------------------------------------//
287 // Test the scalable and fixed-length types can be used interchangeably
288 
289 svint32_t __attribute__((overloadable)) svfunc(svint32_t op1, svint32_t op2);
290 svfloat64_t __attribute__((overloadable)) svfunc(svfloat64_t op1, svfloat64_t op2);
291 svbool_t __attribute__((overloadable)) svfunc(svbool_t op1, svbool_t op2);
292 
293 #define TEST_CALL(TYPE)                                              \
294   fixed_##TYPE##_t                                                   \
295       call_##TYPE##_ff(fixed_##TYPE##_t op1, fixed_##TYPE##_t op2) { \
296     return svfunc(op1, op2);                                         \
297   }                                                                  \
298   fixed_##TYPE##_t                                                   \
299       call_##TYPE##_fs(fixed_##TYPE##_t op1, sv##TYPE##_t op2) {     \
300     return svfunc(op1, op2);                                         \
301   }                                                                  \
302   fixed_##TYPE##_t                                                   \
303       call_##TYPE##_sf(sv##TYPE##_t op1, fixed_##TYPE##_t op2) {     \
304     return svfunc(op1, op2);                                         \
305   }
306 
307 TEST_CALL(int32)
308 TEST_CALL(float64)
309 TEST_CALL(bool)
310 
311 // --------------------------------------------------------------------------//
312 // Vector initialization
313 
314 #if __ARM_FEATURE_SVE_BITS == 256
315 
316 typedef svint32_t int32x8 __attribute__((arm_sve_vector_bits(N)));
317 typedef svfloat64_t float64x4 __attribute__((arm_sve_vector_bits(N)));
318 
319 int32x8 foo = {1, 2, 3, 4, 5, 6, 7, 8};
320 int32x8 foo2 = {1, 2, 3, 4, 5, 6, 7, 8, 9}; // expected-warning{{excess elements in vector initializer}}
321 
322 float64x4 bar = {1.0, 2.0, 3.0, 4.0};
323 float64x4 bar2 = {1.0, 2.0, 3.0, 4.0, 5.0}; // expected-warning{{excess elements in vector initializer}}
324 
325 #endif
326 
327 // --------------------------------------------------------------------------//
328 // Vector ops
329 
330 #define TEST_BINARY(TYPE, NAME, OP)                  \
331   TYPE NAME##_##TYPE(TYPE op1, TYPE op2) {           \
332     return op1 OP op2;                               \
333   }                                                  \
334   TYPE compound##NAME##_##TYPE(TYPE op1, TYPE op2) { \
335     op1 OP##= op2;                                   \
336     return op1;                                      \
337   }
338 
339 #define TEST_COMPARISON(TYPE, NAME, OP)    \
340   TYPE NAME##_##TYPE(TYPE op1, TYPE op2) { \
341     return op1 OP op2;                     \
342   }
343 
344 #define TEST_UNARY(TYPE, NAME, OP) \
345   TYPE NAME##_##TYPE(TYPE op1) {   \
346     return OP op1;                 \
347   }
348 
349 #define TEST_OPS(TYPE)           \
350   TEST_BINARY(TYPE, add, +)      \
351   TEST_BINARY(TYPE, sub, -)      \
352   TEST_BINARY(TYPE, mul, *)      \
353   TEST_BINARY(TYPE, div, /)      \
354   TEST_COMPARISON(TYPE, eq, ==)  \
355   TEST_COMPARISON(TYPE, ne, !=)  \
356   TEST_COMPARISON(TYPE, lt, <)   \
357   TEST_COMPARISON(TYPE, gt, >)   \
358   TEST_COMPARISON(TYPE, lte, <=) \
359   TEST_COMPARISON(TYPE, gte, >=) \
360   TEST_UNARY(TYPE, nop, +)       \
361   TEST_UNARY(TYPE, neg, -)
362 
363 #define TEST_INT_OPS(TYPE)   \
364   TEST_OPS(TYPE)             \
365   TEST_BINARY(TYPE, mod, %)  \
366   TEST_BINARY(TYPE, and, &)  \
367   TEST_BINARY(TYPE, or, |)   \
368   TEST_BINARY(TYPE, xor, ^)  \
369   TEST_BINARY(TYPE, shl, <<) \
370   TEST_BINARY(TYPE, shr, <<) \
371   TEST_UNARY(TYPE, not, ~)
372 
373 TEST_INT_OPS(fixed_int8_t)
374 TEST_INT_OPS(fixed_int16_t)
375 TEST_INT_OPS(fixed_int32_t)
376 TEST_INT_OPS(fixed_int64_t)
377 TEST_INT_OPS(fixed_uint8_t)
378 TEST_INT_OPS(fixed_uint16_t)
379 TEST_INT_OPS(fixed_uint32_t)
380 TEST_INT_OPS(fixed_uint64_t)
381 
382 TEST_OPS(fixed_float16_t)
383 TEST_OPS(fixed_float32_t)
384 TEST_OPS(fixed_float64_t)
385