1 /* ACLE support for Arm MVE (function shapes)
2 Copyright (C) 2023 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
11 GCC is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
22 #include "coretypes.h"
27 #include "insn-codes.h"
29 #include "arm-mve-builtins.h"
30 #include "arm-mve-builtins-shapes.h"
32 /* In the comments below, _t0 represents the first type suffix
33 (e.g. "_s8") and _t1 represents the second. T0/T1 represent the
34 type full names (e.g. int8x16_t). Square brackets enclose
35 characters that are present in only the full name, not the
36 overloaded name. Governing predicate arguments and predicate
37 suffixes are not shown, since they depend on the predication type,
38 which is a separate piece of information from the shape. */
42 /* If INSTANCE has a predicate, add it to the list of argument types
43 in ARGUMENT_TYPES. RETURN_TYPE is the type returned by the
46 apply_predication (const function_instance
&instance
, tree return_type
,
47 vec
<tree
> &argument_types
)
49 if (instance
.pred
!= PRED_none
)
51 /* When predicate is PRED_m, insert a first argument
52 ("inactive") with the same type as return_type. */
53 if (instance
.has_inactive_argument ())
54 argument_types
.quick_insert (0, return_type
);
55 argument_types
.quick_push (get_mve_pred16_t ());
59 /* Parse and move past an element type in FORMAT and return it as a type
60 suffix. The format is:
62 [01] - the element type in type suffix 0 or 1 of INSTANCE.
63 h<elt> - a half-sized version of <elt>
64 s<bits> - a signed type with the given number of bits
65 s[01] - a signed type with the same width as type suffix 0 or 1
66 u<bits> - an unsigned type with the given number of bits
67 u[01] - an unsigned type with the same width as type suffix 0 or 1
68 w<elt> - a double-sized version of <elt>
69 x<bits> - a type with the given number of bits and same signedness
72 Future intrinsics will extend this format. */
73 static type_suffix_index
74 parse_element_type (const function_instance
&instance
, const char *&format
)
79 if (ch
== 's' || ch
== 'u')
81 type_class_index tclass
= (ch
== 'f' ? TYPE_float
82 : ch
== 's' ? TYPE_signed
85 unsigned int bits
= strtol (format
, &end
, 10);
87 if (bits
== 0 || bits
== 1)
88 bits
= instance
.type_suffix (bits
).element_bits
;
89 return find_type_suffix (tclass
, bits
);
94 type_suffix_index suffix
= parse_element_type (instance
, format
);
95 return find_type_suffix (type_suffixes
[suffix
].tclass
,
96 type_suffixes
[suffix
].element_bits
/ 2);
101 type_suffix_index suffix
= parse_element_type (instance
, format
);
102 return find_type_suffix (type_suffixes
[suffix
].tclass
,
103 type_suffixes
[suffix
].element_bits
* 2);
108 const char *next
= format
;
109 next
= strstr (format
, ",");
111 type_suffix_index suffix
= parse_element_type (instance
, next
);
112 type_class_index tclass
= type_suffixes
[suffix
].tclass
;
114 unsigned int bits
= strtol (format
, &end
, 10);
116 return find_type_suffix (tclass
, bits
);
119 if (ch
== '0' || ch
== '1')
120 return instance
.type_suffix_ids
[ch
- '0'];
125 /* Read and return a type from FORMAT for function INSTANCE. Advance
126 FORMAT beyond the type string. The format is:
128 p - predicates with type mve_pred16_t
129 s<elt> - a scalar type with the given element suffix
130 t<elt> - a vector or tuple type with given element suffix [*1]
131 v<elt> - a vector with the given element suffix
133 where <elt> has the format described above parse_element_type.
135 Future intrinsics will extend this format.
137 [*1] the vectors_per_tuple function indicates whether the type should
138 be a tuple, and if so, how many vectors it should contain. */
140 parse_type (const function_instance
&instance
, const char *&format
)
145 return get_mve_pred16_t ();
149 type_suffix_index suffix
= parse_element_type (instance
, format
);
150 return scalar_types
[type_suffixes
[suffix
].vector_type
];
155 type_suffix_index suffix
= parse_element_type (instance
, format
);
156 vector_type_index vector_type
= type_suffixes
[suffix
].vector_type
;
157 unsigned int num_vectors
= instance
.vectors_per_tuple ();
158 return acle_vector_types
[num_vectors
- 1][vector_type
];
163 type_suffix_index suffix
= parse_element_type (instance
, format
);
164 return acle_vector_types
[0][type_suffixes
[suffix
].vector_type
];
170 /* Read a type signature for INSTANCE from FORMAT. Add the argument
171 types to ARGUMENT_TYPES and return the return type. Assert there
172 are no more than MAX_ARGS arguments.
174 The format is a comma-separated list of types (as for parse_type),
175 with the first type being the return type and the rest being the
178 parse_signature (const function_instance
&instance
, const char *format
,
179 vec
<tree
> &argument_types
, unsigned int max_args
)
181 tree return_type
= parse_type (instance
, format
);
182 unsigned int args
= 0;
183 while (format
[0] == ',')
185 gcc_assert (args
< max_args
);
187 tree argument_type
= parse_type (instance
, format
);
188 argument_types
.quick_push (argument_type
);
191 gcc_assert (format
[0] == 0);
195 /* Add one function instance for GROUP, using mode suffix MODE_SUFFIX_ID,
196 the type suffixes at index TI and the predication suffix at index PI.
197 The other arguments are as for build_all. */
199 build_one (function_builder
&b
, const char *signature
,
200 const function_group_info
&group
, mode_suffix_index mode_suffix_id
,
201 unsigned int ti
, unsigned int pi
, bool preserve_user_namespace
,
202 bool force_direct_overloads
)
204 /* Current functions take at most five arguments. Match
205 parse_signature parameter below. */
206 auto_vec
<tree
, 5> argument_types
;
207 function_instance
instance (group
.base_name
, *group
.base
, *group
.shape
,
208 mode_suffix_id
, group
.types
[ti
],
210 tree return_type
= parse_signature (instance
, signature
, argument_types
, 5);
211 apply_predication (instance
, return_type
, argument_types
);
212 b
.add_unique_function (instance
, return_type
, argument_types
,
213 preserve_user_namespace
, group
.requires_float
,
214 force_direct_overloads
);
217 /* Add a function instance for every type and predicate combination in
218 GROUP, except if requested to use only the predicates listed in
219 RESTRICT_TO_PREDS. Take the function base name from GROUP and the
220 mode suffix from MODE_SUFFIX_ID. Use SIGNATURE to construct the
221 function signature, then use apply_predication to add in the
224 build_all (function_builder
&b
, const char *signature
,
225 const function_group_info
&group
, mode_suffix_index mode_suffix_id
,
226 bool preserve_user_namespace
,
227 bool force_direct_overloads
= false,
228 const predication_index
*restrict_to_preds
= NULL
)
230 for (unsigned int pi
= 0; group
.preds
[pi
] != NUM_PREDS
; ++pi
)
232 unsigned int pi2
= 0;
234 if (restrict_to_preds
)
235 for (; restrict_to_preds
[pi2
] != NUM_PREDS
; ++pi2
)
236 if (restrict_to_preds
[pi2
] == group
.preds
[pi
])
239 if (restrict_to_preds
== NULL
|| restrict_to_preds
[pi2
] != NUM_PREDS
)
240 for (unsigned int ti
= 0;
241 ti
== 0 || group
.types
[ti
][0] != NUM_TYPE_SUFFIXES
; ++ti
)
242 build_one (b
, signature
, group
, mode_suffix_id
, ti
, pi
,
243 preserve_user_namespace
, force_direct_overloads
);
247 /* Add a function instance for every type and predicate combination in
248 GROUP, except if requested to use only the predicates listed in
249 RESTRICT_TO_PREDS, and only for 16-bit and 32-bit integers. Take
250 the function base name from GROUP and the mode suffix from
251 MODE_SUFFIX_ID. Use SIGNATURE to construct the function signature,
252 then use apply_predication to add in the predicate. */
254 build_16_32 (function_builder
&b
, const char *signature
,
255 const function_group_info
&group
, mode_suffix_index mode_suffix_id
,
256 bool preserve_user_namespace
,
257 bool force_direct_overloads
= false,
258 const predication_index
*restrict_to_preds
= NULL
)
260 for (unsigned int pi
= 0; group
.preds
[pi
] != NUM_PREDS
; ++pi
)
262 unsigned int pi2
= 0;
264 if (restrict_to_preds
)
265 for (; restrict_to_preds
[pi2
] != NUM_PREDS
; ++pi2
)
266 if (restrict_to_preds
[pi2
] == group
.preds
[pi
])
269 if (restrict_to_preds
== NULL
|| restrict_to_preds
[pi2
] != NUM_PREDS
)
270 for (unsigned int ti
= 0;
271 ti
== 0 || group
.types
[ti
][0] != NUM_TYPE_SUFFIXES
; ++ti
)
273 unsigned int element_bits
= type_suffixes
[group
.types
[ti
][0]].element_bits
;
274 type_class_index tclass
= type_suffixes
[group
.types
[ti
][0]].tclass
;
275 if ((tclass
== TYPE_signed
|| tclass
== TYPE_unsigned
)
276 && (element_bits
== 16 || element_bits
== 32))
277 build_one (b
, signature
, group
, mode_suffix_id
, ti
, pi
,
278 preserve_user_namespace
, force_direct_overloads
);
283 /* Declare the function shape NAME, pointing it to an instance
284 of class <NAME>_def. */
285 #define SHAPE(NAME) \
286 static CONSTEXPR const NAME##_def NAME##_obj; \
287 namespace shapes { const function_shape *const NAME = &NAME##_obj; }
289 /* Base class for functions that are not overloaded. */
290 struct nonoverloaded_base
: public function_shape
293 explicit_type_suffix_p (unsigned int, enum predication_index
, enum mode_suffix_index
) const override
299 explicit_mode_suffix_p (enum predication_index
, enum mode_suffix_index
) const override
305 skip_overload_p (enum predication_index
, enum mode_suffix_index
) const override
311 resolve (function_resolver
&) const override
317 /* Base class for overloaded functions. Bit N of EXPLICIT_MASK is true
318 if type suffix N appears in the overloaded name. */
319 template<unsigned int EXPLICIT_MASK
>
320 struct overloaded_base
: public function_shape
323 explicit_type_suffix_p (unsigned int i
, enum predication_index
, enum mode_suffix_index
) const override
325 return (EXPLICIT_MASK
>> i
) & 1;
329 explicit_mode_suffix_p (enum predication_index
, enum mode_suffix_index
) const override
335 skip_overload_p (enum predication_index
, enum mode_suffix_index
) const override
341 /* <T0>_t vfoo[_t0](<T0>_t, <T0>_t)
343 i.e. the standard shape for binary operations that operate on
347 int8x16_t [__arm_]vandq[_s8](int8x16_t a, int8x16_t b)
348 int8x16_t [__arm_]vandq_m[_s8](int8x16_t inactive, int8x16_t a, int8x16_t b, mve_pred16_t p)
349 int8x16_t [__arm_]vandq_x[_s8](int8x16_t a, int8x16_t b, mve_pred16_t p) */
350 struct binary_def
: public overloaded_base
<0>
353 build (function_builder
&b
, const function_group_info
&group
,
354 bool preserve_user_namespace
) const override
356 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
357 build_all (b
, "v0,v0,v0", group
, MODE_none
, preserve_user_namespace
);
361 resolve (function_resolver
&r
) const override
363 return r
.resolve_uniform (2);
368 /* <[u]int32>_t vfoo[_<t0>](<T0>_t, <T0>_t)
370 i.e. the shape for binary operations that operate on a pair of
371 vectors and produce an int32_t or an uint32_t depending on the
372 signedness of the input elements.
375 int32_t [__arm_]vmladavq[_s16](int16x8_t m1, int16x8_t m2)
376 int32_t [__arm_]vmladavq_p[_s16](int16x8_t m1, int16x8_t m2, mve_pred16_t p) */
377 struct binary_acc_int32_def
: public overloaded_base
<0>
380 build (function_builder
&b
, const function_group_info
&group
,
381 bool preserve_user_namespace
) const override
383 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
384 build_all (b
, "sx32,v0,v0", group
, MODE_none
, preserve_user_namespace
);
388 resolve (function_resolver
&r
) const override
390 return r
.resolve_uniform (2);
393 SHAPE (binary_acc_int32
)
395 /* <[u]int64>_t vfoo[_<t0>](<T0>_t, <T0>_t)
398 int64_t [__arm_]vmlaldavq[_s16](int16x8_t m1, int16x8_t m2)
399 int64_t [__arm_]vmlaldavq_p[_s16](int16x8_t m1, int16x8_t m2, mve_pred16_t p) */
400 struct binary_acc_int64_def
: public overloaded_base
<0>
403 build (function_builder
&b
, const function_group_info
&group
,
404 bool preserve_user_namespace
) const override
406 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
407 build_all (b
, "sx64,v0,v0", group
, MODE_none
, preserve_user_namespace
);
411 resolve (function_resolver
&r
) const override
413 return r
.resolve_uniform (2);
416 SHAPE (binary_acc_int64
)
418 /* <[u]int32>_t vfoo[_<t0>]([u]int32_t, <T0>_t, <T0>_t)
421 int32_t [__arm_]vmladavaq[_s16](int32_t add, int16x8_t m1, int16x8_t m2)
422 int32_t [__arm_]vmladavaq_p[_s16](int32_t add, int16x8_t m1, int16x8_t m2, mve_pred16_t p) */
423 struct binary_acca_int32_def
: public overloaded_base
<0>
426 build (function_builder
&b
, const function_group_info
&group
,
427 bool preserve_user_namespace
) const override
429 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
430 build_all (b
, "sx32,sx32,v0,v0", group
, MODE_none
, preserve_user_namespace
);
434 resolve (function_resolver
&r
) const override
436 unsigned int i
, nargs
;
437 type_suffix_index type
;
438 if (!r
.check_gp_argument (3, i
, nargs
)
439 || (type
= r
.infer_vector_type (1)) == NUM_TYPE_SUFFIXES
)
440 return error_mark_node
;
442 unsigned int last_arg
= i
;
443 for (i
= 1; i
< last_arg
; i
++)
444 if (!r
.require_matching_vector_type (i
, type
))
445 return error_mark_node
;
447 if (!r
.require_integer_immediate (0))
448 return error_mark_node
;
450 return r
.resolve_to (r
.mode_suffix_id
, type
);
453 SHAPE (binary_acca_int32
)
455 /* [u]int64_t vfoo[_<t0>]([u]int64_t, <T0>_t, <T0>_t)
458 int64_t [__arm_]vmlaldavaq[_s16](int64_t add, int16x8_t m1, int16x8_t m2)
459 int64_t [__arm_]vmlaldavaq_p[_s16](int64_t add, int16x8_t m1, int16x8_t m2, mve_pred16_t p) */
460 struct binary_acca_int64_def
: public overloaded_base
<0>
463 build (function_builder
&b
, const function_group_info
&group
,
464 bool preserve_user_namespace
) const override
466 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
467 build_all (b
, "sx64,sx64,v0,v0", group
, MODE_none
, preserve_user_namespace
);
471 resolve (function_resolver
&r
) const override
473 unsigned int i
, nargs
;
474 type_suffix_index type
;
475 if (!r
.check_gp_argument (3, i
, nargs
)
476 || (type
= r
.infer_vector_type (1)) == NUM_TYPE_SUFFIXES
)
477 return error_mark_node
;
479 unsigned int last_arg
= i
;
480 for (i
= 1; i
< last_arg
; i
++)
481 if (!r
.require_matching_vector_type (i
, type
))
482 return error_mark_node
;
484 if (!r
.require_integer_immediate (0))
485 return error_mark_node
;
487 return r
.resolve_to (r
.mode_suffix_id
, type
);
490 SHAPE (binary_acca_int64
)
492 /* <T0>_t vfoo[_n_t0](<T0>_t, int32_t)
494 i.e. the shape for binary operations that operate on
495 a vector and an int32_t.
498 int16x8_t [__arm_]vbrsrq[_n_s16](int16x8_t a, int32_t b)
499 int16x8_t [__arm_]vbrsrq_m[_n_s16](int16x8_t inactive, int16x8_t a, int32_t b, mve_pred16_t p)
500 int16x8_t [__arm_]vbrsrq_x[_n_s16](int16x8_t a, int32_t b, mve_pred16_t p) */
501 struct binary_imm32_def
: public overloaded_base
<0>
504 build (function_builder
&b
, const function_group_info
&group
,
505 bool preserve_user_namespace
) const override
507 b
.add_overloaded_functions (group
, MODE_n
, preserve_user_namespace
);
508 build_all (b
, "v0,v0,ss32", group
, MODE_n
, preserve_user_namespace
);
512 resolve (function_resolver
&r
) const override
514 return r
.resolve_uniform (1, 1);
519 /* <T0>_t vfoo[_n_t0](<T0>_t, const int)
521 Shape for vector shift right operations that take a vector first
522 argument and an integer, and produce a vector.
524 Check that 'imm' is in the [1..#bits] range.
527 int8x16_t [__arm_]vrshrq[_n_s8](int8x16_t a, const int imm)
528 int8x16_t [__arm_]vrshrq_m[_n_s8](int8x16_t inactive, int8x16_t a, const int imm, mve_pred16_t p)
529 int8x16_t [__arm_]vrshrq_x[_n_s8](int8x16_t a, const int imm, mve_pred16_t p) */
530 struct binary_rshift_def
: public overloaded_base
<0>
533 build (function_builder
&b
, const function_group_info
&group
,
534 bool preserve_user_namespace
) const override
536 b
.add_overloaded_functions (group
, MODE_n
, preserve_user_namespace
);
537 build_all (b
, "v0,v0,ss32", group
, MODE_n
, preserve_user_namespace
);
541 resolve (function_resolver
&r
) const override
543 return r
.resolve_uniform (1, 1);
547 check (function_checker
&c
) const override
549 unsigned int bits
= c
.type_suffix (0).element_bits
;
550 return c
.require_immediate_range (1, 1, bits
);
553 SHAPE (binary_rshift
)
556 /* <uT0>_t vfoo[_n_t0](<T0>_t, int)
558 Shape for vector saturating shift left operations that take a
559 vector of signed elements as first argument and an integer, and
560 produce a vector of unsigned elements.
562 Check that 'imm' is in the [0..#bits-1] range.
565 uint16x8_t [__arm_]vqshluq[_n_s16](int16x8_t a, const int imm)
566 uint16x8_t [__arm_]vqshluq_m[_n_s16](uint16x8_t inactive, int16x8_t a, const int imm, mve_pred16_t p) */
567 struct binary_lshift_unsigned_def
: public overloaded_base
<0>
570 build (function_builder
&b
, const function_group_info
&group
,
571 bool preserve_user_namespace
) const override
573 b
.add_overloaded_functions (group
, MODE_n
, preserve_user_namespace
);
574 build_all (b
, "vu0,vs0,ss32", group
, MODE_n
, preserve_user_namespace
);
578 resolve (function_resolver
&r
) const override
580 unsigned int i
, nargs
;
581 type_suffix_index type
;
582 if (!r
.check_gp_argument (2, i
, nargs
)
583 || (type
= r
.infer_vector_type (i
-1)) == NUM_TYPE_SUFFIXES
)
584 return error_mark_node
;
586 if (r
.pred
== PRED_m
)
588 /* With PRED_m, check that the 'inactive' first argument has
589 the expeected unsigned type. */
590 type_suffix_index return_type
591 = find_type_suffix (TYPE_unsigned
, type_suffixes
[type
].element_bits
);
593 if (!r
.require_matching_vector_type (0, return_type
))
594 return error_mark_node
;
597 for (; i
< nargs
; ++i
)
598 if (!r
.require_integer_immediate (i
))
599 return error_mark_node
;
601 return r
.resolve_to (r
.mode_suffix_id
, type
);
605 check (function_checker
&c
) const override
607 unsigned int bits
= c
.type_suffix (0).element_bits
;
608 return c
.require_immediate_range (1, 0, bits
- 1);
612 SHAPE (binary_lshift_unsigned
)
614 /* <uT0>_t vfoo[_t0](<uT0>_t, <T0>_t)
616 i.e. binary operations that take a vector of unsigned elements as first argument and a
617 vector of signed elements as second argument, and produce a vector of unsigned elements.
620 uint8x16_t [__arm_]vminaq[_s8](uint8x16_t a, int8x16_t b)
621 uint8x16_t [__arm_]vminaq_m[_s8](uint8x16_t a, int8x16_t b, mve_pred16_t p) */
622 struct binary_maxamina_def
: public overloaded_base
<0>
625 build (function_builder
&b
, const function_group_info
&group
,
626 bool preserve_user_namespace
) const override
628 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
629 build_all (b
, "vu0,vu0,vs0", group
, MODE_none
, preserve_user_namespace
);
633 resolve (function_resolver
&r
) const override
635 unsigned int i
, nargs
;
636 type_suffix_index type
;
637 if (!r
.check_gp_argument (2, i
, nargs
)
638 || (type
= r
.infer_vector_type (i
)) == NUM_TYPE_SUFFIXES
)
639 return error_mark_node
;
641 /* Check that the first argument has the expeected unsigned
643 type_suffix_index return_type
644 = find_type_suffix (TYPE_unsigned
, type_suffixes
[type
].element_bits
);
645 if (!r
.require_matching_vector_type (0, return_type
))
646 return error_mark_node
;
648 return r
.resolve_to (r
.mode_suffix_id
, type
);
651 SHAPE (binary_maxamina
)
653 /* <uS0>_t vfoo[_<t0>](<uS0>_t, <T0>_t)
656 uint8_t [__arm_]vmaxavq[_s8](uint8_t a, int8x16_t b)
657 uint8_t [__arm_]vmaxavq_p[_s8](uint8_t a, int8x16_t b, mve_pred16_t p) */
658 struct binary_maxavminav_def
: public overloaded_base
<0>
661 build (function_builder
&b
, const function_group_info
&group
,
662 bool preserve_user_namespace
) const override
664 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
665 build_all (b
, "su0,su0,v0", group
, MODE_none
, preserve_user_namespace
);
669 resolve (function_resolver
&r
) const override
671 unsigned int i
, nargs
;
672 type_suffix_index type
;
673 if (!r
.check_gp_argument (2, i
, nargs
)
674 || !r
.require_derived_scalar_type (0, TYPE_unsigned
)
675 || (type
= r
.infer_vector_type (1)) == NUM_TYPE_SUFFIXES
)
676 return error_mark_node
;
678 return r
.resolve_to (r
.mode_suffix_id
, type
);
681 SHAPE (binary_maxavminav
)
683 /* <S0>_t vfoo[_<t0>](<S0>_t, <T0>_t)
686 int8_t [__arm_]vmaxvq[_s8](int8_t a, int8x16_t b)
687 int8_t [__arm_]vmaxvq_p[_s8](int8_t a, int8x16_t b, mve_pred16_t p) */
688 struct binary_maxvminv_def
: public overloaded_base
<0>
691 build (function_builder
&b
, const function_group_info
&group
,
692 bool preserve_user_namespace
) const override
694 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
695 build_all (b
, "s0,s0,v0", group
, MODE_none
, preserve_user_namespace
);
699 resolve (function_resolver
&r
) const override
701 unsigned int i
, nargs
;
702 type_suffix_index type
;
703 if (!r
.check_gp_argument (2, i
, nargs
)
704 || !r
.require_derived_scalar_type (0, r
.SAME_TYPE_CLASS
)
705 || (type
= r
.infer_vector_type (1)) == NUM_TYPE_SUFFIXES
)
706 return error_mark_node
;
708 return r
.resolve_to (r
.mode_suffix_id
, type
);
711 SHAPE (binary_maxvminv
)
713 /* <T0:half>_t vfoo[_t0](<T0:half>_t, <T0>_t)
716 int8x16_t [__arm_]vmovnbq[_s16](int8x16_t a, int16x8_t b)
717 int8x16_t [__arm_]vmovnbq_m[_s16](int8x16_t a, int16x8_t b, mve_pred16_t p) */
718 struct binary_move_narrow_def
: public overloaded_base
<0>
721 build (function_builder
&b
, const function_group_info
&group
,
722 bool preserve_user_namespace
) const override
724 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
725 build_all (b
, "vh0,vh0,v0", group
, MODE_none
, preserve_user_namespace
);
729 resolve (function_resolver
&r
) const override
731 unsigned int i
, nargs
;
732 type_suffix_index type
;
733 if (!r
.check_gp_argument (2, i
, nargs
)
734 || (type
= r
.infer_vector_type (1)) == NUM_TYPE_SUFFIXES
)
735 return error_mark_node
;
737 type_suffix_index narrow_suffix
738 = find_type_suffix (type_suffixes
[type
].tclass
,
739 type_suffixes
[type
].element_bits
/ 2);
742 if (!r
.require_matching_vector_type (0, narrow_suffix
))
743 return error_mark_node
;
745 return r
.resolve_to (r
.mode_suffix_id
, type
);
748 SHAPE (binary_move_narrow
)
750 /* <uT0:half>_t vfoo[_t0](<uT0:half>_t, <T0>_t)
753 uint8x16_t [__arm_]vqmovunbq[_s16](uint8x16_t a, int16x8_t b)
754 uint8x16_t [__arm_]vqmovunbq_m[_s16](uint8x16_t a, int16x8_t b, mve_pred16_t p) */
755 struct binary_move_narrow_unsigned_def
: public overloaded_base
<0>
758 build (function_builder
&b
, const function_group_info
&group
,
759 bool preserve_user_namespace
) const override
761 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
762 build_all (b
, "vhu0,vhu0,v0", group
, MODE_none
, preserve_user_namespace
);
766 resolve (function_resolver
&r
) const override
768 unsigned int i
, nargs
;
769 type_suffix_index type
;
770 if (!r
.check_gp_argument (2, i
, nargs
)
771 || (type
= r
.infer_vector_type (1)) == NUM_TYPE_SUFFIXES
)
772 return error_mark_node
;
774 type_suffix_index narrow_suffix
775 = find_type_suffix (TYPE_unsigned
,
776 type_suffixes
[type
].element_bits
/ 2);
778 if (!r
.require_matching_vector_type (0, narrow_suffix
))
779 return error_mark_node
;
781 return r
.resolve_to (r
.mode_suffix_id
, type
);
784 SHAPE (binary_move_narrow_unsigned
)
786 /* <T0>_t vfoo[_t0](<T0>_t, <T0>_t)
787 <T0>_t vfoo[_n_t0](<T0>_t, <S0>_t)
789 i.e. the standard shape for binary operations that operate on
793 int8x16_t [__arm_]vaddq[_s8](int8x16_t a, int8x16_t b)
794 int8x16_t [__arm_]vaddq[_n_s8](int8x16_t a, int8_t b)
795 int8x16_t [__arm_]vaddq_m[_s8](int8x16_t inactive, int8x16_t a, int8x16_t b, mve_pred16_t p)
796 int8x16_t [__arm_]vaddq_m[_n_s8](int8x16_t inactive, int8x16_t a, int8_t b, mve_pred16_t p)
797 int8x16_t [__arm_]vaddq_x[_s8](int8x16_t a, int8x16_t b, mve_pred16_t p)
798 int8x16_t [__arm_]vaddq_x[_n_s8](int8x16_t a, int8_t b, mve_pred16_t p) */
799 struct binary_opt_n_def
: public overloaded_base
<0>
802 build (function_builder
&b
, const function_group_info
&group
,
803 bool preserve_user_namespace
) const override
805 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
806 build_all (b
, "v0,v0,v0", group
, MODE_none
, preserve_user_namespace
);
807 build_all (b
, "v0,v0,s0", group
, MODE_n
, preserve_user_namespace
);
811 resolve (function_resolver
&r
) const override
813 return r
.resolve_uniform_opt_n (2);
818 /* <T0>_t vfoo[t0](<T0>_t, <T0>_t)
819 <T0>_t vfoo[_n_t0](<T0>_t, <S0>_t)
821 Where the _n form only supports s16/s32/u16/u32 types as for vorrq.
824 int16x8_t [__arm_]vorrq[_s16](int16x8_t a, int16x8_t b)
825 int16x8_t [__arm_]vorrq_m[_s16](int16x8_t inactive, int16x8_t a, int16x8_t b, mve_pred16_t p)
826 int16x8_t [__arm_]vorrq_x[_s16](int16x8_t a, int16x8_t b, mve_pred16_t p)
827 int16x8_t [__arm_]vorrq[_n_s16](int16x8_t a, const int16_t imm)
828 int16x8_t [__arm_]vorrq_m_n[_s16](int16x8_t a, const int16_t imm, mve_pred16_t p) */
829 struct binary_orrq_def
: public overloaded_base
<0>
832 explicit_mode_suffix_p (enum predication_index pred
, enum mode_suffix_index mode
) const override
834 return (mode
== MODE_n
839 skip_overload_p (enum predication_index pred
, enum mode_suffix_index mode
) const override
846 /* For MODE_n, share the overloaded instance with MODE_none, except for PRED_m. */
848 return pred
!= PRED_m
;
856 build (function_builder
&b
, const function_group_info
&group
,
857 bool preserve_user_namespace
) const override
859 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
860 b
.add_overloaded_functions (group
, MODE_n
, preserve_user_namespace
);
861 build_all (b
, "v0,v0,v0", group
, MODE_none
, preserve_user_namespace
);
862 build_16_32 (b
, "v0,v0,s0", group
, MODE_n
, preserve_user_namespace
, false, preds_m_or_none
);
866 resolve (function_resolver
&r
) const override
868 unsigned int i
, nargs
;
869 type_suffix_index type
;
870 if (!r
.check_gp_argument (2, i
, nargs
)
871 || (type
= r
.infer_vector_type (0)) == NUM_TYPE_SUFFIXES
)
872 return error_mark_node
;
874 return r
.finish_opt_n_resolution (i
, 0, type
);
879 /* <T0>_t vfoo[t0](<T0>_t, <T0>_t)
880 <T0>_t vfoo[_n_t0](<T0>_t, int32_t)
882 Shape for rounding shift left operations.
885 int8x16_t [__arm_]vrshlq[_n_s8](int8x16_t a, int32_t b)
886 int8x16_t [__arm_]vrshlq_m_n[_s8](int8x16_t a, int32_t b, mve_pred16_t p)
887 int8x16_t [__arm_]vrshlq[_s8](int8x16_t a, int8x16_t b)
888 int8x16_t [__arm_]vrshlq_m[_s8](int8x16_t inactive, int8x16_t a, int8x16_t b, mve_pred16_t p)
889 int8x16_t [__arm_]vrshlq_x[_s8](int8x16_t a, int8x16_t b, mve_pred16_t p) */
890 struct binary_round_lshift_def
: public overloaded_base
<0>
893 explicit_mode_suffix_p (enum predication_index pred
, enum mode_suffix_index mode
) const override
895 return ((mode
== MODE_n
)
896 && (pred
== PRED_m
));
900 skip_overload_p (enum predication_index pred
, enum mode_suffix_index mode
) const override
907 /* For MODE_n, share the overloaded instance with MODE_none, except for PRED_m. */
909 return pred
!= PRED_m
;
917 build (function_builder
&b
, const function_group_info
&group
,
918 bool preserve_user_namespace
) const override
920 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
921 b
.add_overloaded_functions (group
, MODE_n
, preserve_user_namespace
);
922 build_all (b
, "v0,v0,vs0", group
, MODE_none
, preserve_user_namespace
);
923 build_all (b
, "v0,v0,ss32", group
, MODE_n
, preserve_user_namespace
, false, preds_m_or_none
);
927 resolve (function_resolver
&r
) const override
929 unsigned int i
, nargs
;
930 type_suffix_index type
;
931 if (!r
.check_gp_argument (2, i
, nargs
)
932 || (type
= r
.infer_vector_type (0)) == NUM_TYPE_SUFFIXES
)
933 return error_mark_node
;
935 return r
.finish_opt_n_resolution (i
, 0, type
, TYPE_signed
);
938 SHAPE (binary_round_lshift
)
940 /* <T0>_t vfoo[_t0](<T0>_t, <T0>_t)
941 <T0>_t vfoo_n[_t0](<T0>_t, const int)
943 i.e. the standard shape for left shift operations that operate on
946 For the MODE_n versions, check that 'imm' is in the [0..#bits-1] range.
949 int8x16_t [__arm_]vshlq[_s8](int8x16_t a, int8x16_t b)
950 int8x16_t [__arm_]vshlq_m[_s8](int8x16_t inactive, int8x16_t a, int8x16_t b, mve_pred16_t p)
951 int8x16_t [__arm_]vshlq_x[_s8](int8x16_t a, int8x16_t b, mve_pred16_t p)
952 int8x16_t [__arm_]vshlq_n[_s8](int8x16_t a, const int imm)
953 int8x16_t [__arm_]vshlq_m_n[_s8](int8x16_t inactive, int8x16_t a, const int imm, mve_pred16_t p)
954 int8x16_t [__arm_]vshlq_x_n[_s8](int8x16_t a, const int imm, mve_pred16_t p) */
955 struct binary_lshift_def
: public overloaded_base
<0>
958 explicit_mode_suffix_p (enum predication_index
, enum mode_suffix_index
) const override
964 build (function_builder
&b
, const function_group_info
&group
,
965 bool preserve_user_namespace
) const override
967 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
968 b
.add_overloaded_functions (group
, MODE_n
, preserve_user_namespace
);
969 build_all (b
, "v0,v0,vs0", group
, MODE_none
, preserve_user_namespace
);
970 build_all (b
, "v0,v0,ss32", group
, MODE_n
, preserve_user_namespace
);
974 resolve (function_resolver
&r
) const override
976 unsigned int i
, nargs
;
977 type_suffix_index type
;
978 if (!r
.check_gp_argument (2, i
, nargs
)
979 || (type
= r
.infer_vector_type (0)) == NUM_TYPE_SUFFIXES
)
980 return error_mark_node
;
982 return r
.finish_opt_n_resolution (i
, 0, type
, TYPE_signed
);
986 check (function_checker
&c
) const override
988 if (c
.mode_suffix_id
!= MODE_n
)
991 unsigned int bits
= c
.type_suffix (0).element_bits
;
992 return c
.require_immediate_range (1, 0, bits
- 1);
995 SHAPE (binary_lshift
)
997 /* Used with the above form, but only for the MODE_r case which does
998 not always support the same set of predicates as MODE_none and
999 MODE_n. For vqshlq they are the same, but for vshlq they are not.
1001 <T0>_t vfoo_r[_t0](<T0>_t, int32_t)
1003 i.e. the standard shape for shift operations that operate on
1006 int8x16_t [__arm_]vshlq_r[_s8](int8x16_t a, int32_t b)
1007 int8x16_t [__arm_]vshlq_m_r[_s8](int8x16_t a, int32_t b, mve_pred16_t p) */
1008 struct binary_lshift_r_def
: public overloaded_base
<0>
1011 explicit_mode_suffix_p (enum predication_index
, enum mode_suffix_index
) const override
1017 build (function_builder
&b
, const function_group_info
&group
,
1018 bool preserve_user_namespace
) const override
1020 b
.add_overloaded_functions (group
, MODE_r
, preserve_user_namespace
);
1021 build_all (b
, "v0,v0,ss32", group
, MODE_r
, preserve_user_namespace
, false, preds_m_or_none
);
1025 resolve (function_resolver
&r
) const override
1027 unsigned int i
, nargs
;
1028 type_suffix_index type
;
1029 if (!r
.check_gp_argument (2, i
, nargs
)
1030 || (type
= r
.infer_vector_type (0)) == NUM_TYPE_SUFFIXES
)
1031 return error_mark_node
;
1033 return r
.finish_opt_n_resolution (i
, 0, type
, TYPE_signed
);
1036 SHAPE (binary_lshift_r
)
1038 /* <T0:half>_t vfoo[_n_t0](<T0:half>_t, <T0>_t, const int)
1040 Narrowing right shifts.
1041 Check that 'imm' is in the [1..#bits/2] range.
1044 int8x16_t [__arm_]vqrshrnbq[_n_s16](int8x16_t a, int16x8_t b, const int imm)
1045 int8x16_t [__arm_]vqrshrnbq_m[_n_s16](int8x16_t a, int16x8_t b, const int imm, mve_pred16_t p) */
1046 struct binary_rshift_narrow_def
: public overloaded_base
<0>
1049 build (function_builder
&b
, const function_group_info
&group
,
1050 bool preserve_user_namespace
) const override
1052 b
.add_overloaded_functions (group
, MODE_n
, preserve_user_namespace
);
1053 build_all (b
, "vh0,vh0,v0,ss32", group
, MODE_n
, preserve_user_namespace
);
1057 resolve (function_resolver
&r
) const override
1059 unsigned int i
, nargs
;
1060 type_suffix_index type
;
1061 if (!r
.check_gp_argument (3, i
, nargs
)
1062 || (type
= r
.infer_vector_type (1)) == NUM_TYPE_SUFFIXES
1063 || !r
.require_integer_immediate (i
))
1064 return error_mark_node
;
1066 type_suffix_index narrow_suffix
1067 = find_type_suffix (type_suffixes
[type
].tclass
,
1068 type_suffixes
[type
].element_bits
/ 2);
1070 if (!r
.require_matching_vector_type (0, narrow_suffix
))
1071 return error_mark_node
;
1073 return r
.resolve_to (r
.mode_suffix_id
, type
);
1077 check (function_checker
&c
) const override
1079 unsigned int bits
= c
.type_suffix (0).element_bits
;
1080 return c
.require_immediate_range (2, 1, bits
/ 2);
1083 SHAPE (binary_rshift_narrow
)
1085 /* <uT0:half>_t vfoo[_n_t0](<uT0:half>_t, <T0>_t, const int)
1087 Vector saturating rounding shift right and narrow.
1088 Check that 'imm' is in the [1..#bits/2] range.
1091 uint8x16_t [__arm_]vqshrunbq[_n_s16](uint8x16_t a, int16x8_t b, const int imm)
1092 uint8x16_t [__arm_]vqshrunbq_m[_n_s16](uint8x16_t a, int16x8_t b, const int imm, mve_pred16_t p) */
1093 struct binary_rshift_narrow_unsigned_def
: public overloaded_base
<0>
1096 build (function_builder
&b
, const function_group_info
&group
,
1097 bool preserve_user_namespace
) const override
1099 b
.add_overloaded_functions (group
, MODE_n
, preserve_user_namespace
);
1100 build_all (b
, "vhu0,vhu0,v0,ss32", group
, MODE_n
, preserve_user_namespace
);
1104 resolve (function_resolver
&r
) const override
1106 unsigned int i
, nargs
;
1107 type_suffix_index type
;
1108 if (!r
.check_gp_argument (3, i
, nargs
)
1109 || (type
= r
.infer_vector_type (1)) == NUM_TYPE_SUFFIXES
1110 || !r
.require_integer_immediate (i
))
1111 return error_mark_node
;
1113 type_suffix_index narrow_suffix
1114 = find_type_suffix (TYPE_unsigned
,
1115 type_suffixes
[type
].element_bits
/ 2);
1117 if (!r
.require_matching_vector_type (0, narrow_suffix
))
1118 return error_mark_node
;
1120 return r
.resolve_to (r
.mode_suffix_id
, type
);
1124 check (function_checker
&c
) const override
1126 unsigned int bits
= c
.type_suffix (0).element_bits
;
1127 return c
.require_immediate_range (2, 1, bits
/ 2);
1131 SHAPE (binary_rshift_narrow_unsigned
)
1133 /* <T0:twice>_t vfoo[_n_t0](<T0>_t, const int)
1135 Check that 'imm' is in the [1..#bits] range.
1138 int16x8_t [__arm_]vshllbq[_n_s8](int8x16_t a, const int imm)
1139 int16x8_t [__arm_]vshllbq_m[_n_s8](int16x8_t inactive, int8x16_t a, const int imm, mve_pred16_t p)
1140 int16x8_t [__arm_]vshllbq_x[_n_s8](int8x16_t a, const int imm, mve_pred16_t p) */
1141 struct binary_widen_n_def
: public overloaded_base
<0>
1144 build (function_builder
&b
, const function_group_info
&group
,
1145 bool preserve_user_namespace
) const override
1147 b
.add_overloaded_functions (group
, MODE_n
, preserve_user_namespace
);
1148 build_all (b
, "vw0,v0,s0", group
, MODE_n
, preserve_user_namespace
);
1152 resolve (function_resolver
&r
) const override
1154 unsigned int i
, nargs
;
1155 type_suffix_index type
;
1157 if (!r
.check_gp_argument (2, i
, nargs
)
1158 || (type
= r
.infer_vector_type (i
- 1)) == NUM_TYPE_SUFFIXES
1159 || !r
.require_integer_immediate (i
))
1160 return error_mark_node
;
1162 type_suffix_index wide_suffix
1163 = find_type_suffix (type_suffixes
[type
].tclass
,
1164 type_suffixes
[type
].element_bits
* 2);
1166 /* Check the inactive argument has the wide type. */
1167 if (((r
.pred
== PRED_m
) && (r
.infer_vector_type (0) == wide_suffix
))
1168 || r
.pred
== PRED_none
1169 || r
.pred
== PRED_x
)
1170 if ((res
= r
.lookup_form (r
.mode_suffix_id
, type
)))
1173 return r
.report_no_such_form (type
);
1177 check (function_checker
&c
) const override
1179 unsigned int bits
= c
.type_suffix (0).element_bits
;
1180 return c
.require_immediate_range (1, 1, bits
);
1184 SHAPE (binary_widen_n
)
1186 /* <T0:twice>_t vfoo[_t0](<T0>_t, <T0>_t)
1187 <T0:twice>_t vfoo[_n_t0](<T0>_t, <S0>_t)
1190 int32x4_t [__arm_]vqdmulltq[_n_s16](int16x8_t a, int16_t b)
1191 int32x4_t [__arm_]vqdmulltq_m[_n_s16](int32x4_t inactive, int16x8_t a, int16_t b, mve_pred16_t p)
1192 int32x4_t [__arm_]vqdmulltq[_s16](int16x8_t a, int16x8_t b)
1193 int32x4_t [__arm_]vqdmulltq_m[_s16](int32x4_t inactive, int16x8_t a, int16x8_t b, mve_pred16_t p) */
1194 struct binary_widen_opt_n_def
: public overloaded_base
<0>
1197 build (function_builder
&b
, const function_group_info
&group
,
1198 bool preserve_user_namespace
) const override
1200 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
1201 build_all (b
, "vw0,v0,v0", group
, MODE_none
, preserve_user_namespace
);
1202 build_all (b
, "vw0,v0,s0", group
, MODE_n
, preserve_user_namespace
);
1206 resolve (function_resolver
&r
) const override
1208 unsigned int i
, nargs
;
1209 type_suffix_index type
;
1210 if (!r
.check_gp_argument (2, i
, nargs
)
1211 || (type
= r
.infer_vector_type (i
- 1)) == NUM_TYPE_SUFFIXES
)
1212 return error_mark_node
;
1214 type_suffix_index wide_suffix
1215 = find_type_suffix (type_suffixes
[type
].tclass
,
1216 type_suffixes
[type
].element_bits
* 2);
1218 /* Skip last argument, may be scalar, will be checked below by
1219 finish_opt_n_resolution. */
1220 unsigned int last_arg
= i
--;
1222 if (!r
.require_matching_vector_type (i
, type
))
1223 return error_mark_node
;
1225 /* Check the inactive argument has the wide type. */
1226 if ((r
.pred
== PRED_m
)
1227 && (r
.infer_vector_type (0) != wide_suffix
))
1228 return r
.report_no_such_form (type
);
1230 return r
.finish_opt_n_resolution (last_arg
, 0, type
);
1233 SHAPE (binary_widen_opt_n
)
1235 /* Shape for comparison operations that operate on
1239 mve_pred16_t [__arm_]vcmpeqq[_s16](int16x8_t a, int16x8_t b)
1240 mve_pred16_t [__arm_]vcmpeqq[_n_s16](int16x8_t a, int16_t b)
1241 mve_pred16_t [__arm_]vcmpeqq_m[_s16](int16x8_t a, int16x8_t b, mve_pred16_t p)
1242 mve_pred16_t [__arm_]vcmpeqq_m[_n_s16](int16x8_t a, int16_t b, mve_pred16_t p) */
1243 struct cmp_def
: public overloaded_base
<0>
1246 build (function_builder
&b
, const function_group_info
&group
,
1247 bool preserve_user_namespace
) const override
1249 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
1250 build_all (b
, "p,v0,v0", group
, MODE_none
, preserve_user_namespace
);
1251 build_all (b
, "p,v0,s0", group
, MODE_n
, preserve_user_namespace
);
1255 resolve (function_resolver
&r
) const override
1257 return r
.resolve_uniform_opt_n (2);
1262 /* <T0>xN_t vfoo[_t0](uint64_t, uint64_t)
1264 where there are N arguments in total.
1266 int16x8_t [__arm_]vcreateq_s16(uint64_t a, uint64_t b) */
1267 struct create_def
: public nonoverloaded_base
1270 build (function_builder
&b
, const function_group_info
&group
,
1271 bool preserve_user_namespace
) const override
1273 build_all (b
, "v0,su64,su64", group
, MODE_none
, preserve_user_namespace
);
1277 resolve (function_resolver
&r
) const override
1279 return r
.resolve_uniform (0, 2);
1284 /* <T0>[xN]_t vfoo_t0().
1286 Example: vuninitializedq.
1287 int8x16_t [__arm_]vuninitializedq_s8(void)
1288 int8x16_t [__arm_]vuninitializedq(int8x16_t t) */
1289 struct inherent_def
: public nonoverloaded_base
1292 build (function_builder
&b
, const function_group_info
&group
,
1293 bool preserve_user_namespace
) const override
1295 build_all (b
, "t0", group
, MODE_none
, preserve_user_namespace
);
1300 /* <T0>_t vfoo[_t0](<T0>_t)
1301 <T0>_t vfoo_n_t0(<sT0>_t)
1303 For MODE_n, define only the 16 and 32 bits versions.
1306 int16x8_t [__arm_]vmvnq[_s16](int16x8_t a)
1307 int16x8_t [__arm_]vmvnq_m[_s16](int16x8_t inactive, int16x8_t a, mve_pred16_t p)
1308 int16x8_t [__arm_]vmvnq_x[_s16](int16x8_t a, mve_pred16_t p)
1309 int16x8_t [__arm_]vmvnq_n_s16(const int16_t imm)
1310 int16x8_t [__arm_]vmvnq_m[_n_s16](int16x8_t inactive, const int16_t imm, mve_pred16_t p)
1311 int16x8_t [__arm_]vmvnq_x_n_s16(const int16_t imm, mve_pred16_t p) */
1312 struct mvn_def
: public overloaded_base
<0>
1315 build (function_builder
&b
, const function_group_info
&group
,
1316 bool preserve_user_namespace
) const override
1318 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
1319 /* Do not build a separate instance for MODE_n, since we want to
1320 share vmvnq_m[_n_s16] with vmvnq_m[_s16]. */
1321 build_all (b
, "v0,v0", group
, MODE_none
, preserve_user_namespace
);
1322 build_16_32 (b
, "v0,s0", group
, MODE_n
, preserve_user_namespace
);
1326 resolve (function_resolver
&r
) const override
1328 unsigned int i
, nargs
;
1329 type_suffix_index type
;
1330 if (!r
.check_gp_argument (1, i
, nargs
)
1331 /* Same type for arg 0 and 1 if _m, so using 0 is OK */
1332 || (type
= r
.infer_vector_type (0)) == NUM_TYPE_SUFFIXES
)
1333 return error_mark_node
;
1335 /* Skip last argument, may be scalar. */
1336 unsigned int last_arg
= i
;
1337 for (i
= 0; i
< last_arg
; i
++)
1338 if (!r
.require_matching_vector_type (i
, type
))
1339 return error_mark_node
;
1342 return r
.resolve_to (r
.mode_suffix_id
, type
);
1344 return r
.finish_opt_n_resolution (last_arg
, 0, type
);
1349 /* <T0>_t vfoo[_t0](<T0>_t, <T0>_t, <T0>_t)
1351 i.e. the standard shape for ternary operations that operate on
1354 Example: vqrdmlsdhxq.
1355 int8x16_t [__arm_]vqrdmlsdhxq[_s8](int8x16_t inactive, int8x16_t a, int8x16_t b)
1356 int8x16_t [__arm_]vqrdmlsdhxq_m[_s8](int8x16_t inactive, int8x16_t a, int8x16_t b, mve_pred16_t p) */
1357 struct ternary_def
: public overloaded_base
<0>
1360 build (function_builder
&b
, const function_group_info
&group
,
1361 bool preserve_user_namespace
) const override
1363 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
1364 build_all (b
, "v0,v0,v0,v0", group
, MODE_none
, preserve_user_namespace
);
1368 resolve (function_resolver
&r
) const override
1370 return r
.resolve_uniform_opt_n (3);
1375 /* <T0>_t vfoo[_t0](<T0>_t, <T0>_t, const int)
1377 i.e. ternary operations that operate on a pair of vectors of the
1378 same type as the destination, and take a third integer argument.
1380 Check that 'imm' is in the [0..#bits-1] range.
1383 int16x8_t [__arm_]vsliq[_n_s16](int16x8_t a, int16x8_t b, const int imm)
1384 int16x8_t [__arm_]vsliq_m[_n_s16](int16x8_t a, int16x8_t b, const int imm, mve_pred16_t p) */
1385 struct ternary_lshift_def
: public overloaded_base
<0>
1388 build (function_builder
&b
, const function_group_info
&group
,
1389 bool preserve_user_namespace
) const override
1391 b
.add_overloaded_functions (group
, MODE_n
, preserve_user_namespace
);
1392 build_all (b
, "v0,v0,v0,ss32", group
, MODE_n
, preserve_user_namespace
);
1396 resolve (function_resolver
&r
) const override
1398 return r
.resolve_uniform (2, 1);
1402 check (function_checker
&c
) const override
1404 if (c
.mode_suffix_id
!= MODE_n
)
1407 unsigned int bits
= c
.type_suffix (0).element_bits
;
1408 return c
.require_immediate_range (2, 0, bits
- 1);
1411 SHAPE (ternary_lshift
)
1413 /* <T0>_t vfoo[_n_t0](<T0>_t, <T0>_t, <S0>_t)
1415 i.e. the standard shape for ternary operations that operate on a
1416 pair of vectors of the same type as the destination, and take a
1417 third scalar argument of the same type as the vector elements.
1420 int8x16_t [__arm_]vmlaq[_n_s8](int8x16_t add, int8x16_t m1, int8_t m2)
1421 int8x16_t [__arm_]vmlaq_m[_n_s8](int8x16_t add, int8x16_t m1, int8_t m2, mve_pred16_t p) */
1422 struct ternary_n_def
: public overloaded_base
<0>
1425 build (function_builder
&b
, const function_group_info
&group
,
1426 bool preserve_user_namespace
) const override
1428 b
.add_overloaded_functions (group
, MODE_n
, preserve_user_namespace
);
1429 build_all (b
, "v0,v0,v0,s0", group
, MODE_n
, preserve_user_namespace
);
1433 resolve (function_resolver
&r
) const override
1435 return r
.resolve_uniform (2, 1);
1440 /* <T0>_t vfoo[_t0](<T0>_t, <T0>_t, <T0>_t)
1441 <T0>_t vfoo[_n_t0](<T0>_t, <T0>_t, <S0>_t)
1443 i.e. the standard shape for ternary operations that operate on
1447 float16x8_t [__arm_]vfmaq[_n_f16](float16x8_t add, float16x8_t m1, float16_t m2)
1448 float16x8_t [__arm_]vfmaq_m[_n_f16](float16x8_t add, float16x8_t m1, float16_t m2, mve_pred16_t p)
1449 float16x8_t [__arm_]vfmaq[_f16](float16x8_t add, float16x8_t m1, float16x8_t m2)
1450 float16x8_t [__arm_]vfmaq_m[_f16](float16x8_t add, float16x8_t m1, float16x8_t m2, mve_pred16_t p) */
1451 struct ternary_opt_n_def
: public overloaded_base
<0>
1454 build (function_builder
&b
, const function_group_info
&group
,
1455 bool preserve_user_namespace
) const override
1457 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
1458 build_all (b
, "v0,v0,v0,v0", group
, MODE_none
, preserve_user_namespace
);
1459 build_all (b
, "v0,v0,v0,s0", group
, MODE_n
, preserve_user_namespace
);
1463 resolve (function_resolver
&r
) const override
1465 return r
.resolve_uniform_opt_n (3);
1468 SHAPE (ternary_opt_n
)
1470 /* <T0>_t vfoo[_t0](<T0>_t, <T0>_t, const int)
1472 i.e. ternary operations that operate on a pair of vectors of the
1473 same type as the destination, and take a third integer argument.
1475 Check that 'imm' is in the [1..#bits] range.
1478 int8x16_t [__arm_]vsriq[_n_s8](int8x16_t a, int8x16_t b, const int imm)
1479 int8x16_t [__arm_]vsriq_m[_n_s8](int8x16_t a, int8x16_t b, const int imm, mve_pred16_t p) */
1480 struct ternary_rshift_def
: public overloaded_base
<0>
1483 build (function_builder
&b
, const function_group_info
&group
,
1484 bool preserve_user_namespace
) const override
1486 b
.add_overloaded_functions (group
, MODE_n
, preserve_user_namespace
);
1487 build_all (b
, "v0,v0,v0,ss32", group
, MODE_n
, preserve_user_namespace
);
1491 resolve (function_resolver
&r
) const override
1493 return r
.resolve_uniform (2, 1);
1497 check (function_checker
&c
) const override
1499 if (c
.mode_suffix_id
!= MODE_n
)
1502 unsigned int bits
= c
.type_suffix (0).element_bits
;
1503 return c
.require_immediate_range (2, 1, bits
);
1506 SHAPE (ternary_rshift
)
1508 /* <T0>_t vfoo[_t0](<T0>_t)
1510 i.e. the standard shape for unary operations that operate on
1514 int8x16_t [__arm_]vabsq[_s8](int8x16_t a)
1515 int8x16_t [__arm_]vabsq_m[_s8](int8x16_t inactive, int8x16_t a, mve_pred16_t p)
1516 int8x16_t [__arm_]vabsq_x[_s8](int8x16_t a, mve_pred16_t p) */
1517 struct unary_def
: public overloaded_base
<0>
1520 build (function_builder
&b
, const function_group_info
&group
,
1521 bool preserve_user_namespace
) const override
1523 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
1524 build_all (b
, "v0,v0", group
, MODE_none
, preserve_user_namespace
);
1528 resolve (function_resolver
&r
) const override
1530 return r
.resolve_unary ();
1535 /* <S0:twice>_t vfoo[_<t0>](<T0>_t)
1537 i.e. a version of "unary" in which the source elements are half the
1538 size of the destination scalar, but have the same type class.
1541 int64_t [__arm_]vaddlvq[_s32](int32x4_t a)
1542 int64_t [__arm_]vaddlvq_p[_s32](int32x4_t a, mve_pred16_t p) */
1543 struct unary_acc_def
: public overloaded_base
<0>
1546 build (function_builder
&b
, const function_group_info
&group
,
1547 bool preserve_user_namespace
) const override
1549 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
1550 build_all (b
, "sw0,v0", group
, MODE_none
, preserve_user_namespace
);
1554 resolve (function_resolver
&r
) const override
1556 /* FIXME: check that the return value is actually
1557 twice as wide as arg 0. */
1558 return r
.resolve_unary ();
1563 /* <T0>_t foo_t0[_t1](<T1>_t)
1565 where the target type <t0> must be specified explicitly but the source
1566 type <t1> can be inferred.
1568 Example: vreinterpretq.
1569 int16x8_t [__arm_]vreinterpretq_s16[_s8](int8x16_t a)
1570 int32x4_t [__arm_]vreinterpretq_s32[_s8](int8x16_t a)
1571 int8x16_t [__arm_]vreinterpretq_s8[_s16](int16x8_t a)
1572 int8x16_t [__arm_]vreinterpretq_s8[_s32](int32x4_t a) */
1573 struct unary_convert_def
: public overloaded_base
<1>
1576 build (function_builder
&b
, const function_group_info
&group
,
1577 bool preserve_user_namespace
) const override
1579 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
1580 build_all (b
, "v0,v1", group
, MODE_none
, preserve_user_namespace
);
1584 resolve (function_resolver
&r
) const override
1586 return r
.resolve_unary ();
1589 SHAPE (unary_convert
)
1591 /* [u]int32_t vfoo[_<t0>](<T0>_t)
1593 i.e. a version of "unary" which generates a scalar of type int32_t
1594 or uint32_t depending on the signedness of the elements of of input
1598 int32_t [__arm_]vaddvq[_s16](int16x8_t a)
1599 int32_t [__arm_]vaddvq_p[_s16](int16x8_t a, mve_pred16_t p) */
1600 struct unary_int32_def
: public overloaded_base
<0>
1603 build (function_builder
&b
, const function_group_info
&group
,
1604 bool preserve_user_namespace
) const override
1606 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
1607 build_all (b
, "sx32,v0", group
, MODE_none
, preserve_user_namespace
);
1611 resolve (function_resolver
&r
) const override
1613 return r
.resolve_uniform (1);
1618 /* [u]int32_t vfoo[_<t0>]([u]int32_t, <T0>_t)
1620 i.e. a version of "unary" which accumulates into scalar of type
1621 int32_t or uint32_t depending on the signedness of the elements of
1625 int32_t [__arm_]vaddvaq[_s16](int32_t a, int16x8_t b)
1626 int32_t [__arm_]vaddvaq_p[_s16](int32_t a, int16x8_t b, mve_pred16_t p) */
1627 struct unary_int32_acc_def
: public overloaded_base
<0>
1630 build (function_builder
&b
, const function_group_info
&group
,
1631 bool preserve_user_namespace
) const override
1633 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
1634 build_all (b
, "sx32,sx32,v0", group
, MODE_none
, preserve_user_namespace
);
1638 resolve (function_resolver
&r
) const override
1640 unsigned int i
, nargs
;
1641 type_suffix_index type
;
1642 if (!r
.check_gp_argument (2, i
, nargs
)
1643 || !r
.require_integer_immediate (0)
1644 || (type
= r
.infer_vector_type (1)) == NUM_TYPE_SUFFIXES
)
1645 return error_mark_node
;
1647 return r
.resolve_to (r
.mode_suffix_id
, type
);
1650 SHAPE (unary_int32_acc
)
1652 /* <T0>_t vfoo[_n]_t0(<S0>_t)
1655 int16x8_t [__arm_]vdupq_n_s16(int16_t a)
1656 int16x8_t [__arm_]vdupq_m[_n_s16](int16x8_t inactive, int16_t a, mve_pred16_t p)
1657 int16x8_t [__arm_]vdupq_x_n_s16(int16_t a, mve_pred16_t p) */
1658 struct unary_n_def
: public overloaded_base
<0>
1661 explicit_type_suffix_p (unsigned int, enum predication_index pred
,
1662 enum mode_suffix_index
) const override
1664 return pred
!= PRED_m
;
1668 explicit_mode_suffix_p (enum predication_index pred
,
1669 enum mode_suffix_index mode
) const override
1671 return ((mode
== MODE_n
)
1672 && (pred
!= PRED_m
));
1676 skip_overload_p (enum predication_index pred
, enum mode_suffix_index mode
)
1682 return pred
!= PRED_m
;
1690 build (function_builder
&b
, const function_group_info
&group
,
1691 bool preserve_user_namespace
) const override
1693 b
.add_overloaded_functions (group
, MODE_n
, preserve_user_namespace
);
1694 build_all (b
, "v0,s0", group
, MODE_n
, preserve_user_namespace
);
1698 resolve (function_resolver
&r
) const override
1700 return r
.resolve_unary_n ();
1705 /* <T0:twice>_t vfoo[_t0](<T0>_t)
1707 i.e. a version of "unary" in which the source elements are half the
1708 size of the destination, but have the same type class.
1711 int32x4_t [__arm_]vmovlbq[_s16](int16x8_t a)
1712 int32x4_t [__arm_]vmovlbq_m[_s16](int32x4_t inactive, int16x8_t a, mve_pred16_t p)
1713 int32x4_t [__arm_]vmovlbq_x[_s16](int16x8_t a, mve_pred16_t p) */
1714 struct unary_widen_def
: public overloaded_base
<0>
1717 build (function_builder
&b
, const function_group_info
&group
,
1718 bool preserve_user_namespace
) const override
1720 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
1721 build_all (b
, "vw0,v0", group
, MODE_none
, preserve_user_namespace
);
1725 resolve (function_resolver
&r
) const override
1727 unsigned int i
, nargs
;
1728 type_suffix_index type
;
1730 if (!r
.check_gp_argument (1, i
, nargs
)
1731 || (type
= r
.infer_vector_type (i
)) == NUM_TYPE_SUFFIXES
)
1732 return error_mark_node
;
1734 type_suffix_index wide_suffix
1735 = find_type_suffix (type_suffixes
[type
].tclass
,
1736 type_suffixes
[type
].element_bits
* 2);
1738 /* Check the inactive argument has the wide type. */
1739 if ((r
.pred
== PRED_m
)
1740 && (r
.infer_vector_type (0) != wide_suffix
))
1741 return r
.report_no_such_form (type
);
1743 if ((res
= r
.lookup_form (r
.mode_suffix_id
, type
)))
1746 return r
.report_no_such_form (type
);
1751 /* <S0:twice>_t vfoo[_<t0>](<S0:twice>_t, <T0>_t)
1753 i.e. a version of "unary" in which the source elements are half the
1754 size of the destination scalar and accumulator, but have the same
1758 int64_t [__arm_]vaddlvaq[_s32](int64_t a, int32x4_t b)
1759 int64_t [__arm_]vaddlvaq_p[_s32](int64_t a, int32x4_t b, mve_pred16_t p) */
1760 struct unary_widen_acc_def
: public overloaded_base
<0>
1763 build (function_builder
&b
, const function_group_info
&group
,
1764 bool preserve_user_namespace
) const override
1766 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
1767 build_all (b
, "sw0,sw0,v0", group
, MODE_none
, preserve_user_namespace
);
1771 resolve (function_resolver
&r
) const override
1773 unsigned int i
, nargs
;
1774 type_suffix_index type
;
1775 if (!r
.check_gp_argument (2, i
, nargs
)
1776 || !r
.require_derived_scalar_type (0, r
.SAME_TYPE_CLASS
)
1777 || (type
= r
.infer_vector_type (i
)) == NUM_TYPE_SUFFIXES
)
1778 return error_mark_node
;
1780 return r
.resolve_to (r
.mode_suffix_id
, type
);
1783 SHAPE (unary_widen_acc
)
1785 /* <T0>_t vfoo[_t0](<T0>_t, <T0>_t, mve_pred16_t)
1787 i.e. a version of the standard ternary shape in which
1788 the final argument is always a set of predicates.
1791 int16x8_t [__arm_]vpselq[_s16](int16x8_t a, int16x8_t b, mve_pred16_t p) */
1792 struct vpsel_def
: public overloaded_base
<0>
1795 build (function_builder
&b
, const function_group_info
&group
,
1796 bool preserve_user_namespace
) const override
1798 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
1799 build_all (b
, "v0,v0,v0,p", group
, MODE_none
, preserve_user_namespace
);
1803 resolve (function_resolver
&r
) const override
1805 unsigned int i
, nargs
;
1806 type_suffix_index type
;
1807 if (!r
.check_gp_argument (3, i
, nargs
)
1808 || (type
= r
.infer_vector_type (0)) == NUM_TYPE_SUFFIXES
)
1809 return error_mark_node
;
1811 unsigned int last_arg
= i
;
1812 for (i
= 0; i
< last_arg
; i
++)
1813 if (!r
.require_matching_vector_type (i
, type
))
1814 return error_mark_node
;
1816 if (!r
.require_vector_type (2 , VECTOR_TYPE_mve_pred16_t
))
1817 return error_mark_node
;
1819 return r
.resolve_to (r
.mode_suffix_id
, type
);
1824 } /* end namespace arm_mve */