1 /* ACLE support for Arm MVE (function shapes)
2 Copyright (C) 2023-2025 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 /* Return a representation of "const T *". */
44 build_const_pointer (tree t
)
46 return build_pointer_type (build_qualified_type (t
, TYPE_QUAL_CONST
));
49 /* If INSTANCE has a predicate, add it to the list of argument types
50 in ARGUMENT_TYPES. RETURN_TYPE is the type returned by the
53 apply_predication (const function_instance
&instance
, tree return_type
,
54 vec
<tree
> &argument_types
)
56 if (instance
.pred
!= PRED_none
)
58 /* When predicate is PRED_m, insert a first argument
59 ("inactive") with the same type as return_type. */
60 if (instance
.has_inactive_argument ())
61 argument_types
.quick_insert (0, return_type
);
62 argument_types
.quick_push (get_mve_pred16_t ());
66 /* Parse and move past an element type in FORMAT and return it as a type
67 suffix. The format is:
69 [01] - the element type in type suffix 0 or 1 of INSTANCE.
70 h<elt> - a half-sized version of <elt>
71 p<elt> - a poly type with the same width as <elt>
72 s<bits> - a signed type with the given number of bits
73 s[01] - a signed type with the same width as type suffix 0 or 1
74 u<bits> - an unsigned type with the given number of bits
75 u[01] - an unsigned type with the same width as type suffix 0 or 1
76 U<elt> - an unsigned type with the double width as <elt>
77 w<elt> - a double-sized version of <elt>
78 x<bits> - a type with the given number of bits and same signedness
81 Future intrinsics will extend this format. */
82 static type_suffix_index
83 parse_element_type (const function_instance
&instance
, const char *&format
)
88 if (ch
== 's' || ch
== 'u')
90 type_class_index tclass
= (ch
== 's' ? TYPE_signed
93 unsigned int bits
= strtol (format
, &end
, 10);
95 if (bits
== 0 || bits
== 1)
96 bits
= instance
.type_suffix (bits
).element_bits
;
97 return find_type_suffix (tclass
, bits
);
102 type_suffix_index suffix
= parse_element_type (instance
, format
);
103 return find_type_suffix (type_suffixes
[suffix
].tclass
,
104 type_suffixes
[suffix
].element_bits
/ 2);
109 type_suffix_index suffix
= parse_element_type (instance
, format
);
110 return find_type_suffix (type_suffixes
[suffix
].tclass
,
111 type_suffixes
[suffix
].element_bits
* 2);
116 type_suffix_index suffix
= parse_element_type (instance
, format
);
117 return find_type_suffix (TYPE_unsigned
,
118 type_suffixes
[suffix
].element_bits
* 2);
123 type_suffix_index suffix
= parse_element_type (instance
, format
);
124 return find_type_suffix (TYPE_poly
,
125 type_suffixes
[suffix
].element_bits
);
130 const char *next
= format
;
131 next
= strstr (format
, ",");
133 type_suffix_index suffix
= parse_element_type (instance
, next
);
134 type_class_index tclass
= type_suffixes
[suffix
].tclass
;
136 unsigned int bits
= strtol (format
, &end
, 10);
138 return find_type_suffix (tclass
, bits
);
141 if (ch
== '0' || ch
== '1')
142 return instance
.type_suffix_ids
[ch
- '0'];
147 /* Read and return a type from FORMAT for function INSTANCE. Advance
148 FORMAT beyond the type string. The format is:
151 al - array pointer for loads
152 as - array pointer for stores
153 b - pointer to vector of unsigned, width given by the first type suffix
154 p - predicates with type mve_pred16_t
155 s<elt> - a scalar type with the given element suffix
156 t<elt> - a vector or tuple type with given element suffix [*1]
157 v<elt> - a vector with the given element suffix
159 where <elt> has the format described above parse_element_type.
161 Future intrinsics will extend this format.
163 [*1] the vectors_per_tuple function indicates whether the type should
164 be a tuple, and if so, how many vectors it should contain. */
166 parse_type (const function_instance
&instance
, const char *&format
)
172 return void_type_node
;
178 return build_const_pointer (instance
.memory_scalar_type ());
180 return build_pointer_type (instance
.memory_scalar_type ());
187 type_class_index tclass
= TYPE_unsigned
;
188 unsigned int bits
= instance
.type_suffix (0).element_bits
;
189 type_suffix_index suffix
= find_type_suffix (tclass
, bits
);
190 tree acle_type
= acle_vector_types
[0][type_suffixes
[suffix
].vector_type
];
191 return build_pointer_type (acle_type
);
195 return get_mve_pred16_t ();
199 type_suffix_index suffix
= parse_element_type (instance
, format
);
200 return scalar_types
[type_suffixes
[suffix
].vector_type
];
205 type_suffix_index suffix
= parse_element_type (instance
, format
);
206 vector_type_index vector_type
= type_suffixes
[suffix
].vector_type
;
207 unsigned int num_vectors
= instance
.vectors_per_tuple ();
208 return acle_vector_types
[num_vectors
>> 1][vector_type
];
213 type_suffix_index suffix
= parse_element_type (instance
, format
);
214 return acle_vector_types
[0][type_suffixes
[suffix
].vector_type
];
220 /* Read a type signature for INSTANCE from FORMAT. Add the argument
221 types to ARGUMENT_TYPES and return the return type. Assert there
222 are no more than MAX_ARGS arguments.
224 The format is a comma-separated list of types (as for parse_type),
225 with the first type being the return type and the rest being the
228 parse_signature (const function_instance
&instance
, const char *format
,
229 vec
<tree
> &argument_types
, unsigned int max_args
)
231 tree return_type
= parse_type (instance
, format
);
232 unsigned int args
= 0;
233 while (format
[0] == ',')
235 gcc_assert (args
< max_args
);
237 tree argument_type
= parse_type (instance
, format
);
238 argument_types
.quick_push (argument_type
);
241 gcc_assert (format
[0] == 0);
245 /* Add one function instance for GROUP, using mode suffix MODE_SUFFIX_ID,
246 the type suffixes at index TI and the predication suffix at index PI.
247 The other arguments are as for build_all. */
249 build_one (function_builder
&b
, const char *signature
,
250 const function_group_info
&group
, mode_suffix_index mode_suffix_id
,
251 unsigned int ti
, unsigned int pi
, bool preserve_user_namespace
,
252 bool force_direct_overloads
)
254 /* Current functions take at most five arguments. Match
255 parse_signature parameter below. */
256 auto_vec
<tree
, 5> argument_types
;
257 function_instance
instance (group
.base_name
, *group
.base
, *group
.shape
,
258 mode_suffix_id
, group
.types
[ti
],
260 tree return_type
= parse_signature (instance
, signature
, argument_types
, 5);
261 apply_predication (instance
, return_type
, argument_types
);
262 b
.add_unique_function (instance
, return_type
, argument_types
,
263 preserve_user_namespace
, group
.requires_float
,
264 force_direct_overloads
);
267 /* Add a function instance for every type and predicate combination in
268 GROUP, except if requested to use only the predicates listed in
269 RESTRICT_TO_PREDS. Take the function base name from GROUP and the
270 mode suffix from MODE_SUFFIX_ID. Use SIGNATURE to construct the
271 function signature, then use apply_predication to add in the
274 build_all (function_builder
&b
, const char *signature
,
275 const function_group_info
&group
, mode_suffix_index mode_suffix_id
,
276 bool preserve_user_namespace
,
277 bool force_direct_overloads
= false,
278 const predication_index
*restrict_to_preds
= NULL
)
280 for (unsigned int pi
= 0; group
.preds
[pi
] != NUM_PREDS
; ++pi
)
282 unsigned int pi2
= 0;
284 if (restrict_to_preds
)
285 for (; restrict_to_preds
[pi2
] != NUM_PREDS
; ++pi2
)
286 if (restrict_to_preds
[pi2
] == group
.preds
[pi
])
289 if (restrict_to_preds
== NULL
|| restrict_to_preds
[pi2
] != NUM_PREDS
)
290 for (unsigned int ti
= 0;
291 ti
== 0 || group
.types
[ti
][0] != NUM_TYPE_SUFFIXES
; ++ti
)
292 build_one (b
, signature
, group
, mode_suffix_id
, ti
, pi
,
293 preserve_user_namespace
, force_direct_overloads
);
297 /* Add a function instance for every type and predicate combination in
298 GROUP, except if requested to use only the predicates listed in
299 RESTRICT_TO_PREDS, and only for 16-bit and 32-bit integers. Take
300 the function base name from GROUP and the mode suffix from
301 MODE_SUFFIX_ID. Use SIGNATURE to construct the function signature,
302 then use apply_predication to add in the predicate. */
304 build_16_32 (function_builder
&b
, const char *signature
,
305 const function_group_info
&group
, mode_suffix_index mode_suffix_id
,
306 bool preserve_user_namespace
,
307 bool force_direct_overloads
= false,
308 const predication_index
*restrict_to_preds
= NULL
)
310 for (unsigned int pi
= 0; group
.preds
[pi
] != NUM_PREDS
; ++pi
)
312 unsigned int pi2
= 0;
314 if (restrict_to_preds
)
315 for (; restrict_to_preds
[pi2
] != NUM_PREDS
; ++pi2
)
316 if (restrict_to_preds
[pi2
] == group
.preds
[pi
])
319 if (restrict_to_preds
== NULL
|| restrict_to_preds
[pi2
] != NUM_PREDS
)
320 for (unsigned int ti
= 0;
321 ti
== 0 || group
.types
[ti
][0] != NUM_TYPE_SUFFIXES
; ++ti
)
323 unsigned int element_bits
= type_suffixes
[group
.types
[ti
][0]].element_bits
;
324 type_class_index tclass
= type_suffixes
[group
.types
[ti
][0]].tclass
;
325 if ((tclass
== TYPE_signed
|| tclass
== TYPE_unsigned
)
326 && (element_bits
== 16 || element_bits
== 32))
327 build_one (b
, signature
, group
, mode_suffix_id
, ti
, pi
,
328 preserve_user_namespace
, force_direct_overloads
);
333 /* TYPE is the largest type suffix associated with the arguments of R, but the
334 result is twice as wide. Return the associated type suffix of
335 EXPECTED_TCLASS if it exists, otherwise report an appropriate error and
336 return NUM_TYPE_SUFFIXES. */
337 static type_suffix_index
338 long_type_suffix (function_resolver
&r
,
339 type_suffix_index type
,
340 type_class_index expected_tclass
)
342 unsigned int element_bits
= type_suffixes
[type
].element_bits
;
343 if (expected_tclass
== function_resolver::SAME_TYPE_CLASS
)
344 expected_tclass
= type_suffixes
[type
].tclass
;
346 if (type_suffixes
[type
].integer_p
&& element_bits
< 64)
347 return find_type_suffix (expected_tclass
, element_bits
* 2);
349 r
.report_no_such_form (type
);
350 return NUM_TYPE_SUFFIXES
;
353 /* Return the type suffix half as wide as TYPE with EXPECTED_TCLASS if it
354 exists, otherwise report an appropriate error and return
355 NUM_TYPE_SUFFIXES. */
356 static type_suffix_index
357 half_type_suffix (function_resolver
&r
,
358 type_suffix_index type
,
359 type_class_index expected_tclass
)
361 unsigned int element_bits
= type_suffixes
[type
].element_bits
;
362 if (expected_tclass
== function_resolver::SAME_TYPE_CLASS
)
363 expected_tclass
= type_suffixes
[type
].tclass
;
365 if (type_suffixes
[type
].integer_p
&& element_bits
> 8)
366 return find_type_suffix (expected_tclass
, element_bits
/ 2);
368 r
.report_no_such_form (type
);
369 return NUM_TYPE_SUFFIXES
;
372 /* Declare the function shape NAME, pointing it to an instance
373 of class <NAME>_def. */
374 #define SHAPE(NAME) \
375 static CONSTEXPR const NAME##_def NAME##_obj; \
376 namespace shapes { const function_shape *const NAME = &NAME##_obj; }
378 /* Base class for functions that are not overloaded. */
379 struct nonoverloaded_base
: public function_shape
382 explicit_type_suffix_p (unsigned int, enum predication_index
,
383 enum mode_suffix_index
, type_suffix_info
) const override
389 explicit_mode_suffix_p (enum predication_index
, enum mode_suffix_index
) const override
395 skip_overload_p (enum predication_index
, enum mode_suffix_index
) const override
401 mode_after_pred () const override
407 resolve (function_resolver
&) const override
413 /* Base class for overloaded functions. Bit N of EXPLICIT_MASK is true
414 if type suffix N appears in the overloaded name. */
415 template<unsigned int EXPLICIT_MASK
>
416 struct overloaded_base
: public function_shape
419 explicit_type_suffix_p (unsigned int i
, enum predication_index
,
420 enum mode_suffix_index
, type_suffix_info
) const override
422 return (EXPLICIT_MASK
>> i
) & 1;
426 explicit_mode_suffix_p (enum predication_index
, enum mode_suffix_index
) const override
432 skip_overload_p (enum predication_index
, enum mode_suffix_index
) const override
438 mode_after_pred () const override
444 /* <T0>_t vfoo[_t0](<T0>_t, <T0>_t)
446 i.e. the standard shape for binary operations that operate on
450 int8x16_t [__arm_]vandq[_s8](int8x16_t a, int8x16_t b)
451 int8x16_t [__arm_]vandq_m[_s8](int8x16_t inactive, int8x16_t a, int8x16_t b, mve_pred16_t p)
452 int8x16_t [__arm_]vandq_x[_s8](int8x16_t a, int8x16_t b, mve_pred16_t p) */
453 struct binary_def
: public overloaded_base
<0>
456 build (function_builder
&b
, const function_group_info
&group
,
457 bool preserve_user_namespace
) const override
459 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
460 build_all (b
, "v0,v0,v0", group
, MODE_none
, preserve_user_namespace
);
464 resolve (function_resolver
&r
) const override
466 return r
.resolve_uniform (2);
471 /* <[u]int32>_t vfoo[_<t0>](<T0>_t, <T0>_t)
473 i.e. the shape for binary operations that operate on a pair of
474 vectors and produce an int32_t or an uint32_t depending on the
475 signedness of the input elements.
478 int32_t [__arm_]vmladavq[_s16](int16x8_t m1, int16x8_t m2)
479 int32_t [__arm_]vmladavq_p[_s16](int16x8_t m1, int16x8_t m2, mve_pred16_t p) */
480 struct binary_acc_int32_def
: public overloaded_base
<0>
483 build (function_builder
&b
, const function_group_info
&group
,
484 bool preserve_user_namespace
) const override
486 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
487 build_all (b
, "sx32,v0,v0", group
, MODE_none
, preserve_user_namespace
);
491 resolve (function_resolver
&r
) const override
493 return r
.resolve_uniform (2);
496 SHAPE (binary_acc_int32
)
498 /* <[u]int64>_t vfoo[_<t0>](<T0>_t, <T0>_t)
501 int64_t [__arm_]vmlaldavq[_s16](int16x8_t m1, int16x8_t m2)
502 int64_t [__arm_]vmlaldavq_p[_s16](int16x8_t m1, int16x8_t m2, mve_pred16_t p) */
503 struct binary_acc_int64_def
: public overloaded_base
<0>
506 build (function_builder
&b
, const function_group_info
&group
,
507 bool preserve_user_namespace
) const override
509 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
510 build_all (b
, "sx64,v0,v0", group
, MODE_none
, preserve_user_namespace
);
514 resolve (function_resolver
&r
) const override
516 return r
.resolve_uniform (2);
519 SHAPE (binary_acc_int64
)
521 /* <[u]int32>_t vfoo[_<t0>]([u]int32_t, <T0>_t, <T0>_t)
524 int32_t [__arm_]vmladavaq[_s16](int32_t add, int16x8_t m1, int16x8_t m2)
525 int32_t [__arm_]vmladavaq_p[_s16](int32_t add, int16x8_t m1, int16x8_t m2, mve_pred16_t p) */
526 struct binary_acca_int32_def
: public overloaded_base
<0>
529 build (function_builder
&b
, const function_group_info
&group
,
530 bool preserve_user_namespace
) const override
532 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
533 build_all (b
, "sx32,sx32,v0,v0", group
, MODE_none
, preserve_user_namespace
);
537 resolve (function_resolver
&r
) const override
539 unsigned int i
, nargs
;
540 type_suffix_index type
;
541 const char *first_type_name
;
543 if (!r
.check_gp_argument (3, i
, nargs
)
544 || (type
= r
.infer_vector_type (1)) == NUM_TYPE_SUFFIXES
)
545 return error_mark_node
;
547 first_type_name
= (type_suffixes
[type
].unsigned_p
550 if (!r
.require_scalar_type (0, first_type_name
))
551 return error_mark_node
;
553 unsigned int last_arg
= i
+ 1;
554 for (i
= 1; i
< last_arg
; i
++)
555 if (!r
.require_matching_vector_type (i
, type
))
556 return error_mark_node
;
558 return r
.resolve_to (r
.mode_suffix_id
, type
);
561 SHAPE (binary_acca_int32
)
563 /* [u]int64_t vfoo[_<t0>]([u]int64_t, <T0>_t, <T0>_t)
566 int64_t [__arm_]vmlaldavaq[_s16](int64_t add, int16x8_t m1, int16x8_t m2)
567 int64_t [__arm_]vmlaldavaq_p[_s16](int64_t add, int16x8_t m1, int16x8_t m2, mve_pred16_t p) */
568 struct binary_acca_int64_def
: public overloaded_base
<0>
571 build (function_builder
&b
, const function_group_info
&group
,
572 bool preserve_user_namespace
) const override
574 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
575 build_all (b
, "sx64,sx64,v0,v0", group
, MODE_none
, preserve_user_namespace
);
579 resolve (function_resolver
&r
) const override
581 unsigned int i
, nargs
;
582 type_suffix_index type
;
583 const char *first_type_name
;
585 if (!r
.check_gp_argument (3, i
, nargs
)
586 || (type
= r
.infer_vector_type (1)) == NUM_TYPE_SUFFIXES
)
587 return error_mark_node
;
590 first_type_name
= (type_suffixes
[type
].unsigned_p
593 if (!r
.require_scalar_type (0, first_type_name
))
594 return error_mark_node
;
596 unsigned int last_arg
= i
+ 1;
597 for (i
= 1; i
< last_arg
; i
++)
598 if (!r
.require_matching_vector_type (i
, type
))
599 return error_mark_node
;
601 return r
.resolve_to (r
.mode_suffix_id
, type
);
604 SHAPE (binary_acca_int64
)
606 /* <T0>_t vfoo[_n_t0](<T0>_t, int32_t)
608 i.e. the shape for binary operations that operate on
609 a vector and an int32_t.
612 int16x8_t [__arm_]vbrsrq[_n_s16](int16x8_t a, int32_t b)
613 int16x8_t [__arm_]vbrsrq_m[_n_s16](int16x8_t inactive, int16x8_t a, int32_t b, mve_pred16_t p)
614 int16x8_t [__arm_]vbrsrq_x[_n_s16](int16x8_t a, int32_t b, mve_pred16_t p) */
615 struct binary_imm32_def
: public overloaded_base
<0>
618 build (function_builder
&b
, const function_group_info
&group
,
619 bool preserve_user_namespace
) const override
621 b
.add_overloaded_functions (group
, MODE_n
, preserve_user_namespace
);
622 build_all (b
, "v0,v0,ss32", group
, MODE_n
, preserve_user_namespace
);
626 resolve (function_resolver
&r
) const override
628 return r
.resolve_uniform (1, 1);
633 /* <T0>_t vfoo[_n_t0](<T0>_t, const int)
635 Shape for vector shift right operations that take a vector first
636 argument and an integer, and produce a vector.
638 Check that 'imm' is in the [1..#bits] range.
641 int8x16_t [__arm_]vrshrq[_n_s8](int8x16_t a, const int imm)
642 int8x16_t [__arm_]vrshrq_m[_n_s8](int8x16_t inactive, int8x16_t a, const int imm, mve_pred16_t p)
643 int8x16_t [__arm_]vrshrq_x[_n_s8](int8x16_t a, const int imm, mve_pred16_t p) */
644 struct binary_rshift_def
: public overloaded_base
<0>
647 build (function_builder
&b
, const function_group_info
&group
,
648 bool preserve_user_namespace
) const override
650 b
.add_overloaded_functions (group
, MODE_n
, preserve_user_namespace
);
651 build_all (b
, "v0,v0,ss32", group
, MODE_n
, preserve_user_namespace
);
655 resolve (function_resolver
&r
) const override
657 return r
.resolve_uniform (1, 1);
661 check (function_checker
&c
) const override
663 unsigned int bits
= c
.type_suffix (0).element_bits
;
664 return c
.require_immediate_range (1, 1, bits
);
667 SHAPE (binary_rshift
)
670 /* <uT0>_t vfoo[_n_t0](<T0>_t, int)
672 Shape for vector saturating shift left operations that take a
673 vector of signed elements as first argument and an integer, and
674 produce a vector of unsigned elements.
676 Check that 'imm' is in the [0..#bits-1] range.
679 uint16x8_t [__arm_]vqshluq[_n_s16](int16x8_t a, const int imm)
680 uint16x8_t [__arm_]vqshluq_m[_n_s16](uint16x8_t inactive, int16x8_t a, const int imm, mve_pred16_t p) */
681 struct binary_lshift_unsigned_def
: public overloaded_base
<0>
684 build (function_builder
&b
, const function_group_info
&group
,
685 bool preserve_user_namespace
) const override
687 b
.add_overloaded_functions (group
, MODE_n
, preserve_user_namespace
);
688 build_all (b
, "vu0,vs0,su64", group
, MODE_n
, preserve_user_namespace
);
692 resolve (function_resolver
&r
) const override
694 unsigned int i
, nargs
;
695 type_suffix_index type
;
696 if (!r
.check_gp_argument (2, i
, nargs
)
697 || !r
.require_integer_immediate (i
)
698 || (type
= r
.infer_vector_type (i
-1)) == NUM_TYPE_SUFFIXES
)
699 return error_mark_node
;
701 if (r
.pred
== PRED_m
)
703 /* With PRED_m, check that the 'inactive' first argument has
704 the expeected unsigned type. */
705 type_suffix_index return_type
706 = find_type_suffix (TYPE_unsigned
, type_suffixes
[type
].element_bits
);
708 if (!r
.require_matching_vector_type (0, return_type
))
709 return error_mark_node
;
712 return r
.resolve_to (r
.mode_suffix_id
, type
);
716 check (function_checker
&c
) const override
718 unsigned int bits
= c
.type_suffix (0).element_bits
;
719 return c
.require_immediate_range (1, 0, bits
- 1);
723 SHAPE (binary_lshift_unsigned
)
725 /* <uT0>_t vfoo[_t0](<uT0>_t, <T0>_t)
727 i.e. binary operations that take a vector of unsigned elements as first argument and a
728 vector of signed elements as second argument, and produce a vector of unsigned elements.
731 uint8x16_t [__arm_]vminaq[_s8](uint8x16_t a, int8x16_t b)
732 uint8x16_t [__arm_]vminaq_m[_s8](uint8x16_t a, int8x16_t b, mve_pred16_t p) */
733 struct binary_maxamina_def
: public overloaded_base
<0>
736 build (function_builder
&b
, const function_group_info
&group
,
737 bool preserve_user_namespace
) const override
739 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
740 build_all (b
, "vu0,vu0,vs0", group
, MODE_none
, preserve_user_namespace
);
744 resolve (function_resolver
&r
) const override
746 unsigned int i
, nargs
;
747 type_suffix_index type
;
748 if (!r
.check_gp_argument (2, i
, nargs
)
749 || (type
= r
.infer_vector_type (i
)) == NUM_TYPE_SUFFIXES
)
750 return error_mark_node
;
752 /* Check that the first argument has the expeected unsigned
754 type_suffix_index return_type
755 = find_type_suffix (TYPE_unsigned
, type_suffixes
[type
].element_bits
);
756 if (!r
.require_matching_vector_type (0, return_type
))
757 return error_mark_node
;
759 return r
.resolve_to (r
.mode_suffix_id
, type
);
762 SHAPE (binary_maxamina
)
764 /* <uS0>_t vfoo[_<t0>](<uS0>_t, <T0>_t)
767 uint8_t [__arm_]vmaxavq[_s8](uint8_t a, int8x16_t b)
768 uint8_t [__arm_]vmaxavq_p[_s8](uint8_t a, int8x16_t b, mve_pred16_t p) */
769 struct binary_maxavminav_def
: public overloaded_base
<0>
772 build (function_builder
&b
, const function_group_info
&group
,
773 bool preserve_user_namespace
) const override
775 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
776 build_all (b
, "su0,su0,v0", group
, MODE_none
, preserve_user_namespace
);
780 resolve (function_resolver
&r
) const override
782 unsigned int i
, nargs
;
783 type_suffix_index type
;
784 if (!r
.check_gp_argument (2, i
, nargs
)
785 || !r
.require_derived_scalar_type (0, TYPE_unsigned
)
786 || (type
= r
.infer_vector_type (1)) == NUM_TYPE_SUFFIXES
)
787 return error_mark_node
;
789 return r
.resolve_to (r
.mode_suffix_id
, type
);
792 SHAPE (binary_maxavminav
)
794 /* <S0>_t vfoo[_<t0>](<S0>_t, <T0>_t)
797 int8_t [__arm_]vmaxvq[_s8](int8_t a, int8x16_t b)
798 int8_t [__arm_]vmaxvq_p[_s8](int8_t a, int8x16_t b, mve_pred16_t p) */
799 struct binary_maxvminv_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
, "s0,s0,v0", group
, MODE_none
, preserve_user_namespace
);
810 resolve (function_resolver
&r
) const override
812 unsigned int i
, nargs
;
813 type_suffix_index type
;
814 if (!r
.check_gp_argument (2, i
, nargs
)
815 || !r
.require_derived_scalar_type (0, r
.SAME_TYPE_CLASS
)
816 || (type
= r
.infer_vector_type (1)) == NUM_TYPE_SUFFIXES
)
817 return error_mark_node
;
819 return r
.resolve_to (r
.mode_suffix_id
, type
);
822 SHAPE (binary_maxvminv
)
824 /* <T0:half>_t vfoo[_t0](<T0:half>_t, <T0>_t)
827 int8x16_t [__arm_]vmovnbq[_s16](int8x16_t a, int16x8_t b)
828 int8x16_t [__arm_]vmovnbq_m[_s16](int8x16_t a, int16x8_t b, mve_pred16_t p) */
829 struct binary_move_narrow_def
: public overloaded_base
<0>
832 build (function_builder
&b
, const function_group_info
&group
,
833 bool preserve_user_namespace
) const override
835 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
836 build_all (b
, "vh0,vh0,v0", group
, MODE_none
, preserve_user_namespace
);
840 resolve (function_resolver
&r
) const override
842 unsigned int i
, nargs
;
843 type_suffix_index type
, narrow_suffix
;
844 if (!r
.check_gp_argument (2, i
, nargs
)
845 || (type
= r
.infer_vector_type (1)) == NUM_TYPE_SUFFIXES
846 || ((narrow_suffix
= half_type_suffix (r
, type
, r
.SAME_TYPE_CLASS
))
847 == NUM_TYPE_SUFFIXES
))
848 return error_mark_node
;
850 if (!r
.require_matching_vector_type (0, narrow_suffix
))
851 return error_mark_node
;
853 return r
.resolve_to (r
.mode_suffix_id
, type
);
856 SHAPE (binary_move_narrow
)
858 /* <uT0:half>_t vfoo[_t0](<uT0:half>_t, <T0>_t)
861 uint8x16_t [__arm_]vqmovunbq[_s16](uint8x16_t a, int16x8_t b)
862 uint8x16_t [__arm_]vqmovunbq_m[_s16](uint8x16_t a, int16x8_t b, mve_pred16_t p) */
863 struct binary_move_narrow_unsigned_def
: public overloaded_base
<0>
866 build (function_builder
&b
, const function_group_info
&group
,
867 bool preserve_user_namespace
) const override
869 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
870 build_all (b
, "vhu0,vhu0,v0", group
, MODE_none
, preserve_user_namespace
);
874 resolve (function_resolver
&r
) const override
876 unsigned int i
, nargs
;
877 type_suffix_index type
, narrow_suffix
;
878 if (!r
.check_gp_argument (2, i
, nargs
)
879 || (type
= r
.infer_vector_type (1)) == NUM_TYPE_SUFFIXES
880 || ((narrow_suffix
= half_type_suffix (r
, type
, TYPE_unsigned
))
881 == NUM_TYPE_SUFFIXES
))
882 return error_mark_node
;
884 if (!r
.require_matching_vector_type (0, narrow_suffix
))
885 return error_mark_node
;
887 return r
.resolve_to (r
.mode_suffix_id
, type
);
890 SHAPE (binary_move_narrow_unsigned
)
892 /* <T0>_t vfoo[_t0](<T0>_t, <T0>_t)
893 <T0>_t vfoo[_n_t0](<T0>_t, <S0>_t)
895 i.e. the standard shape for binary operations that operate on
899 int8x16_t [__arm_]vaddq[_s8](int8x16_t a, int8x16_t b)
900 int8x16_t [__arm_]vaddq[_n_s8](int8x16_t a, int8_t b)
901 int8x16_t [__arm_]vaddq_m[_s8](int8x16_t inactive, int8x16_t a, int8x16_t b, mve_pred16_t p)
902 int8x16_t [__arm_]vaddq_m[_n_s8](int8x16_t inactive, int8x16_t a, int8_t b, mve_pred16_t p)
903 int8x16_t [__arm_]vaddq_x[_s8](int8x16_t a, int8x16_t b, mve_pred16_t p)
904 int8x16_t [__arm_]vaddq_x[_n_s8](int8x16_t a, int8_t b, mve_pred16_t p) */
905 struct binary_opt_n_def
: public overloaded_base
<0>
908 build (function_builder
&b
, const function_group_info
&group
,
909 bool preserve_user_namespace
) const override
911 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
912 build_all (b
, "v0,v0,v0", group
, MODE_none
, preserve_user_namespace
);
913 build_all (b
, "v0,v0,s0", group
, MODE_n
, preserve_user_namespace
);
917 resolve (function_resolver
&r
) const override
919 return r
.resolve_uniform_opt_n (2);
924 /* <T0>_t vfoo[t0](<T0>_t, <T0>_t)
925 <T0>_t vfoo[_n_t0](<T0>_t, <S0>_t)
927 Where the _n form only supports s16/s32/u16/u32 types as for vorrq.
930 int16x8_t [__arm_]vorrq[_s16](int16x8_t a, int16x8_t b)
931 int16x8_t [__arm_]vorrq_m[_s16](int16x8_t inactive, int16x8_t a, int16x8_t b, mve_pred16_t p)
932 int16x8_t [__arm_]vorrq_x[_s16](int16x8_t a, int16x8_t b, mve_pred16_t p)
933 int16x8_t [__arm_]vorrq[_n_s16](int16x8_t a, const int16_t imm)
934 int16x8_t [__arm_]vorrq_m_n[_s16](int16x8_t a, const int16_t imm, mve_pred16_t p)
936 No "_n" forms for floating-point, nor 8-bit integers:
937 float16x8_t [__arm_]vorrq[_f16](float16x8_t a, float16x8_t b)
938 float16x8_t [__arm_]vorrq_m[_f16](float16x8_t inactive, float16x8_t a, float16x8_t b, mve_pred16_t p)
939 float16x8_t [__arm_]vorrq_x[_f16](float16x8_t a, float16x8_t b, mve_pred16_t p) */
940 struct binary_orrq_def
: public overloaded_base
<0>
943 explicit_mode_suffix_p (enum predication_index pred
, enum mode_suffix_index mode
) const override
945 return (mode
== MODE_n
950 skip_overload_p (enum predication_index pred
, enum mode_suffix_index mode
) const override
957 /* For MODE_n, share the overloaded instance with MODE_none, except for PRED_m. */
959 return pred
!= PRED_m
;
967 build (function_builder
&b
, const function_group_info
&group
,
968 bool preserve_user_namespace
) const override
970 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
971 b
.add_overloaded_functions (group
, MODE_n
, preserve_user_namespace
);
972 build_all (b
, "v0,v0,v0", group
, MODE_none
, preserve_user_namespace
);
973 build_16_32 (b
, "v0,v0,s0", group
, MODE_n
, preserve_user_namespace
, false, preds_m_or_none
);
977 resolve (function_resolver
&r
) const override
979 unsigned int i
, nargs
;
980 type_suffix_index type
;
981 if (!r
.check_gp_argument (2, i
, nargs
)
982 || (type
= r
.infer_vector_type (0)) == NUM_TYPE_SUFFIXES
)
983 return error_mark_node
;
985 return r
.finish_opt_n_resolution (i
, 0, type
);
990 /* <T0>_t vfoo[t0](<T0>_t, <T0>_t)
991 <T0>_t vfoo[_n_t0](<T0>_t, int32_t)
993 Shape for rounding shift left operations.
996 int8x16_t [__arm_]vrshlq[_n_s8](int8x16_t a, int32_t b)
997 int8x16_t [__arm_]vrshlq_m_n[_s8](int8x16_t a, int32_t b, mve_pred16_t p)
998 int8x16_t [__arm_]vrshlq[_s8](int8x16_t a, int8x16_t b)
999 int8x16_t [__arm_]vrshlq_m[_s8](int8x16_t inactive, int8x16_t a, int8x16_t b, mve_pred16_t p)
1000 int8x16_t [__arm_]vrshlq_x[_s8](int8x16_t a, int8x16_t b, mve_pred16_t p) */
1001 struct binary_round_lshift_def
: public overloaded_base
<0>
1004 explicit_mode_suffix_p (enum predication_index pred
, enum mode_suffix_index mode
) const override
1006 return ((mode
== MODE_n
)
1007 && (pred
== PRED_m
));
1011 skip_overload_p (enum predication_index pred
, enum mode_suffix_index mode
) const override
1018 /* For MODE_n, share the overloaded instance with MODE_none, except for PRED_m. */
1020 return pred
!= PRED_m
;
1028 build (function_builder
&b
, const function_group_info
&group
,
1029 bool preserve_user_namespace
) const override
1031 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
1032 b
.add_overloaded_functions (group
, MODE_n
, preserve_user_namespace
);
1033 build_all (b
, "v0,v0,vs0", group
, MODE_none
, preserve_user_namespace
);
1034 build_all (b
, "v0,v0,ss32", group
, MODE_n
, preserve_user_namespace
, false, preds_m_or_none
);
1038 resolve (function_resolver
&r
) const override
1040 unsigned int i
, nargs
;
1041 type_suffix_index type
;
1042 if (!r
.check_gp_argument (2, i
, nargs
)
1043 || (type
= r
.infer_vector_type (0)) == NUM_TYPE_SUFFIXES
)
1044 return error_mark_node
;
1046 return r
.finish_opt_n_resolution (i
, 0, type
, TYPE_signed
);
1049 SHAPE (binary_round_lshift
)
1051 /* <T0>_t vfoo[_t0](<T0>_t, <T0>_t)
1052 <T0>_t vfoo_n[_t0](<T0>_t, const int)
1054 i.e. the standard shape for left shift operations that operate on
1057 For the MODE_n versions, check that 'imm' is in the [0..#bits-1] range.
1060 int8x16_t [__arm_]vshlq[_s8](int8x16_t a, int8x16_t b)
1061 int8x16_t [__arm_]vshlq_m[_s8](int8x16_t inactive, int8x16_t a, int8x16_t b, mve_pred16_t p)
1062 int8x16_t [__arm_]vshlq_x[_s8](int8x16_t a, int8x16_t b, mve_pred16_t p)
1063 int8x16_t [__arm_]vshlq_n[_s8](int8x16_t a, const int imm)
1064 int8x16_t [__arm_]vshlq_m_n[_s8](int8x16_t inactive, int8x16_t a, const int imm, mve_pred16_t p)
1065 int8x16_t [__arm_]vshlq_x_n[_s8](int8x16_t a, const int imm, mve_pred16_t p) */
1066 struct binary_lshift_def
: public overloaded_base
<0>
1069 explicit_mode_suffix_p (enum predication_index
, enum mode_suffix_index
) const override
1075 build (function_builder
&b
, const function_group_info
&group
,
1076 bool preserve_user_namespace
) const override
1078 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
1079 b
.add_overloaded_functions (group
, MODE_n
, preserve_user_namespace
);
1080 build_all (b
, "v0,v0,vs0", group
, MODE_none
, preserve_user_namespace
);
1081 build_all (b
, "v0,v0,ss32", group
, MODE_n
, preserve_user_namespace
);
1085 resolve (function_resolver
&r
) const override
1087 unsigned int i
, nargs
;
1088 type_suffix_index type
;
1089 if (!r
.check_gp_argument (2, i
, nargs
)
1090 || (type
= r
.infer_vector_type (0)) == NUM_TYPE_SUFFIXES
)
1091 return error_mark_node
;
1093 return r
.finish_opt_n_resolution (i
, 0, type
, TYPE_signed
);
1097 check (function_checker
&c
) const override
1099 if (c
.mode_suffix_id
!= MODE_n
)
1102 unsigned int bits
= c
.type_suffix (0).element_bits
;
1103 return c
.require_immediate_range (1, 0, bits
- 1);
1106 SHAPE (binary_lshift
)
1108 /* Used with the above form, but only for the MODE_r case which does
1109 not always support the same set of predicates as MODE_none and
1110 MODE_n. For vqshlq they are the same, but for vshlq they are not.
1112 <T0>_t vfoo_r[_t0](<T0>_t, int32_t)
1114 i.e. the standard shape for shift operations that operate on
1117 int8x16_t [__arm_]vshlq_r[_s8](int8x16_t a, int32_t b)
1118 int8x16_t [__arm_]vshlq_m_r[_s8](int8x16_t a, int32_t b, mve_pred16_t p) */
1119 struct binary_lshift_r_def
: public overloaded_base
<0>
1122 explicit_mode_suffix_p (enum predication_index
, enum mode_suffix_index
) const override
1128 build (function_builder
&b
, const function_group_info
&group
,
1129 bool preserve_user_namespace
) const override
1131 b
.add_overloaded_functions (group
, MODE_r
, preserve_user_namespace
);
1132 build_all (b
, "v0,v0,ss32", group
, MODE_r
, preserve_user_namespace
, false, preds_m_or_none
);
1136 resolve (function_resolver
&r
) const override
1138 unsigned int i
, nargs
;
1139 type_suffix_index type
;
1140 if (!r
.check_gp_argument (2, i
, nargs
)
1141 || (type
= r
.infer_vector_type (0)) == NUM_TYPE_SUFFIXES
)
1142 return error_mark_node
;
1144 return r
.finish_opt_n_resolution (i
, 0, type
, TYPE_signed
);
1147 SHAPE (binary_lshift_r
)
1149 /* <T0:half>_t vfoo[_n_t0](<T0:half>_t, <T0>_t, const int)
1151 Narrowing right shifts.
1152 Check that 'imm' is in the [1..#bits/2] range.
1155 int8x16_t [__arm_]vqrshrnbq[_n_s16](int8x16_t a, int16x8_t b, const int imm)
1156 int8x16_t [__arm_]vqrshrnbq_m[_n_s16](int8x16_t a, int16x8_t b, const int imm, mve_pred16_t p) */
1157 struct binary_rshift_narrow_def
: public overloaded_base
<0>
1160 build (function_builder
&b
, const function_group_info
&group
,
1161 bool preserve_user_namespace
) const override
1163 b
.add_overloaded_functions (group
, MODE_n
, preserve_user_namespace
);
1164 build_all (b
, "vh0,vh0,v0,su64", group
, MODE_n
, preserve_user_namespace
);
1168 resolve (function_resolver
&r
) const override
1170 unsigned int i
, nargs
;
1171 type_suffix_index type
, narrow_suffix
;
1172 if (!r
.check_gp_argument (3, i
, nargs
)
1173 || (type
= r
.infer_vector_type (1)) == NUM_TYPE_SUFFIXES
1174 || ((narrow_suffix
= half_type_suffix (r
, type
, r
.SAME_TYPE_CLASS
))
1175 == NUM_TYPE_SUFFIXES
)
1176 || !r
.require_integer_immediate (i
))
1177 return error_mark_node
;
1179 if (!r
.require_matching_vector_type (0, narrow_suffix
))
1180 return error_mark_node
;
1182 return r
.resolve_to (r
.mode_suffix_id
, type
);
1186 check (function_checker
&c
) const override
1188 unsigned int bits
= c
.type_suffix (0).element_bits
;
1189 return c
.require_immediate_range (2, 1, bits
/ 2);
1192 SHAPE (binary_rshift_narrow
)
1194 /* <uT0:half>_t vfoo[_n_t0](<uT0:half>_t, <T0>_t, const int)
1196 Vector saturating rounding shift right and narrow.
1197 Check that 'imm' is in the [1..#bits/2] range.
1200 uint8x16_t [__arm_]vqshrunbq[_n_s16](uint8x16_t a, int16x8_t b, const int imm)
1201 uint8x16_t [__arm_]vqshrunbq_m[_n_s16](uint8x16_t a, int16x8_t b, const int imm, mve_pred16_t p) */
1202 struct binary_rshift_narrow_unsigned_def
: public overloaded_base
<0>
1205 build (function_builder
&b
, const function_group_info
&group
,
1206 bool preserve_user_namespace
) const override
1208 b
.add_overloaded_functions (group
, MODE_n
, preserve_user_namespace
);
1209 build_all (b
, "vhu0,vhu0,v0,su64", group
, MODE_n
, preserve_user_namespace
);
1213 resolve (function_resolver
&r
) const override
1215 unsigned int i
, nargs
;
1216 type_suffix_index type
, narrow_suffix
;
1217 if (!r
.check_gp_argument (3, i
, nargs
)
1218 || (type
= r
.infer_vector_type (1)) == NUM_TYPE_SUFFIXES
1219 || ((narrow_suffix
= half_type_suffix (r
, type
, TYPE_unsigned
))
1220 == NUM_TYPE_SUFFIXES
)
1221 || !r
.require_integer_immediate (i
))
1222 return error_mark_node
;
1224 if (!r
.require_matching_vector_type (0, narrow_suffix
))
1225 return error_mark_node
;
1227 return r
.resolve_to (r
.mode_suffix_id
, type
);
1231 check (function_checker
&c
) const override
1233 unsigned int bits
= c
.type_suffix (0).element_bits
;
1234 return c
.require_immediate_range (2, 1, bits
/ 2);
1238 SHAPE (binary_rshift_narrow_unsigned
)
1240 /* <T0:twice>_t vfoo[_t0](<T0>_t, <T0>_t)
1243 int32x4_t [__arm_]vmullbq_int[_s16](int16x8_t a, int16x8_t b)
1244 int32x4_t [__arm_]vmullbq_int_m[_s16](int32x4_t inactive, int16x8_t a, int16x8_t b, mve_pred16_t p)
1245 int32x4_t [__arm_]vmullbq_int_x[_s16](int16x8_t a, int16x8_t b, mve_pred16_t p) */
1246 struct binary_widen_def
: public overloaded_base
<0>
1249 build (function_builder
&b
, const function_group_info
&group
,
1250 bool preserve_user_namespace
) const override
1252 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
1253 build_all (b
, "vw0,v0,v0", group
, MODE_none
, preserve_user_namespace
);
1257 resolve (function_resolver
&r
) const override
1259 unsigned int i
, nargs
;
1260 type_suffix_index type
, wide_suffix
;
1261 if (!r
.check_gp_argument (2, i
, nargs
)
1262 || (type
= r
.infer_vector_type (i
- 1)) == NUM_TYPE_SUFFIXES
1263 || ((wide_suffix
= long_type_suffix (r
, type
, r
.SAME_TYPE_CLASS
))
1264 == NUM_TYPE_SUFFIXES
))
1265 return error_mark_node
;
1267 if (!r
.require_matching_vector_type (i
, type
))
1268 return error_mark_node
;
1270 /* Check the inactive argument has the wide type. */
1271 if ((r
.pred
== PRED_m
)
1272 && (r
.infer_vector_type (0) != wide_suffix
))
1273 return r
.report_no_such_form (type
);
1275 return r
.resolve_to (r
.mode_suffix_id
, type
);
1278 SHAPE (binary_widen
)
1280 /* <T0:twice>_t vfoo[_t0](<T0>_t, <T0>_t)
1282 Example: vmullbq_poly.
1283 uint32x4_t [__arm_]vmullbq_poly[_p16](uint16x8_t a, uint16x8_t b)
1284 uint32x4_t [__arm_]vmullbq_poly_m[_p16](uint32x4_t inactive, uint16x8_t a, uint16x8_t b, mve_pred16_t p)
1285 uint32x4_t [__arm_]vmullbq_poly_x[_p16](uint16x8_t a, uint16x8_t b, mve_pred16_t p) */
1286 struct binary_widen_poly_def
: public overloaded_base
<0>
1289 build (function_builder
&b
, const function_group_info
&group
,
1290 bool preserve_user_namespace
) const override
1292 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
1293 build_all (b
, "vU0,vp0,vp0", group
, MODE_none
, preserve_user_namespace
);
1297 resolve (function_resolver
&r
) const override
1299 unsigned int i
, nargs
;
1300 type_suffix_index type
;
1301 if (!r
.check_gp_argument (2, i
, nargs
)
1302 || (type
= r
.infer_vector_type (i
- 1)) == NUM_TYPE_SUFFIXES
)
1303 return error_mark_node
;
1305 /* infer_vector_type found the 'unsigned' version of the 'poly'
1306 type we are looking for, so find the 'poly' type with the same
1308 type
= find_type_suffix (TYPE_poly
, type_suffixes
[type
].element_bits
);
1310 type_suffix_index wide_suffix
1311 = find_type_suffix (TYPE_unsigned
,
1312 type_suffixes
[type
].element_bits
* 2);
1314 /* Require the 'poly' type, require_matching_vector_type would try
1315 and fail with the 'unsigned' one. */
1316 if (!r
.require_vector_type (i
, type_suffixes
[type
].vector_type
))
1317 return error_mark_node
;
1319 /* Check the inactive argument has the wide type. */
1320 if ((r
.pred
== PRED_m
)
1321 && (r
.infer_vector_type (0) != wide_suffix
))
1322 return r
.report_no_such_form (type
);
1324 return r
.resolve_to (r
.mode_suffix_id
, type
);
1327 SHAPE (binary_widen_poly
)
1329 /* <T0:twice>_t vfoo[_n_t0](<T0>_t, const int)
1331 Check that 'imm' is in the [1..#bits] range.
1334 int16x8_t [__arm_]vshllbq[_n_s8](int8x16_t a, const int imm)
1335 int16x8_t [__arm_]vshllbq_m[_n_s8](int16x8_t inactive, int8x16_t a, const int imm, mve_pred16_t p)
1336 int16x8_t [__arm_]vshllbq_x[_n_s8](int8x16_t a, const int imm, mve_pred16_t p) */
1337 struct binary_widen_n_def
: public overloaded_base
<0>
1340 build (function_builder
&b
, const function_group_info
&group
,
1341 bool preserve_user_namespace
) const override
1343 b
.add_overloaded_functions (group
, MODE_n
, preserve_user_namespace
);
1344 build_all (b
, "vw0,v0,s0", group
, MODE_n
, preserve_user_namespace
);
1348 resolve (function_resolver
&r
) const override
1350 unsigned int i
, nargs
;
1351 type_suffix_index type
, wide_suffix
;
1353 if (!r
.check_gp_argument (2, i
, nargs
)
1354 || (type
= r
.infer_vector_type (i
- 1)) == NUM_TYPE_SUFFIXES
1355 || ((wide_suffix
= long_type_suffix (r
, type
, r
.SAME_TYPE_CLASS
))
1356 == NUM_TYPE_SUFFIXES
)
1357 || !r
.require_integer_immediate (i
))
1358 return error_mark_node
;
1360 /* Check the inactive argument has the wide type. */
1361 if (((r
.pred
== PRED_m
) && (r
.infer_vector_type (0) == wide_suffix
))
1362 || r
.pred
== PRED_none
1363 || r
.pred
== PRED_x
)
1364 if ((res
= r
.lookup_form (r
.mode_suffix_id
, type
)))
1367 return r
.report_no_such_form (type
);
1371 check (function_checker
&c
) const override
1373 unsigned int bits
= c
.type_suffix (0).element_bits
;
1374 return c
.require_immediate_range (1, 1, bits
);
1378 SHAPE (binary_widen_n
)
1380 /* <T0:twice>_t vfoo[_t0](<T0>_t, <T0>_t)
1381 <T0:twice>_t vfoo[_n_t0](<T0>_t, <S0>_t)
1384 int32x4_t [__arm_]vqdmulltq[_n_s16](int16x8_t a, int16_t b)
1385 int32x4_t [__arm_]vqdmulltq_m[_n_s16](int32x4_t inactive, int16x8_t a, int16_t b, mve_pred16_t p)
1386 int32x4_t [__arm_]vqdmulltq[_s16](int16x8_t a, int16x8_t b)
1387 int32x4_t [__arm_]vqdmulltq_m[_s16](int32x4_t inactive, int16x8_t a, int16x8_t b, mve_pred16_t p) */
1388 struct binary_widen_opt_n_def
: public overloaded_base
<0>
1391 build (function_builder
&b
, const function_group_info
&group
,
1392 bool preserve_user_namespace
) const override
1394 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
1395 build_all (b
, "vw0,v0,v0", group
, MODE_none
, preserve_user_namespace
);
1396 build_all (b
, "vw0,v0,s0", group
, MODE_n
, preserve_user_namespace
);
1400 resolve (function_resolver
&r
) const override
1402 unsigned int i
, nargs
;
1403 type_suffix_index type
, wide_suffix
;
1404 if (!r
.check_gp_argument (2, i
, nargs
)
1405 || (type
= r
.infer_vector_type (i
- 1)) == NUM_TYPE_SUFFIXES
1406 || ((wide_suffix
= long_type_suffix (r
, type
, r
.SAME_TYPE_CLASS
))
1407 == NUM_TYPE_SUFFIXES
))
1408 return error_mark_node
;
1410 /* Skip last argument, may be scalar, will be checked below by
1411 finish_opt_n_resolution. */
1412 unsigned int last_arg
= i
--;
1414 if (!r
.require_matching_vector_type (i
, type
))
1415 return error_mark_node
;
1417 /* Check the inactive argument has the wide type. */
1418 if ((r
.pred
== PRED_m
)
1419 && (r
.infer_vector_type (0) != wide_suffix
))
1420 return r
.report_no_such_form (type
);
1422 return r
.finish_opt_n_resolution (last_arg
, 0, type
);
1425 SHAPE (binary_widen_opt_n
)
1427 /* Shape for comparison operations that operate on
1431 mve_pred16_t [__arm_]vcmpeqq[_s16](int16x8_t a, int16x8_t b)
1432 mve_pred16_t [__arm_]vcmpeqq[_n_s16](int16x8_t a, int16_t b)
1433 mve_pred16_t [__arm_]vcmpeqq_m[_s16](int16x8_t a, int16x8_t b, mve_pred16_t p)
1434 mve_pred16_t [__arm_]vcmpeqq_m[_n_s16](int16x8_t a, int16_t b, mve_pred16_t p) */
1435 struct cmp_def
: public overloaded_base
<0>
1438 build (function_builder
&b
, const function_group_info
&group
,
1439 bool preserve_user_namespace
) const override
1441 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
1442 build_all (b
, "p,v0,v0", group
, MODE_none
, preserve_user_namespace
);
1443 build_all (b
, "p,v0,s0", group
, MODE_n
, preserve_user_namespace
);
1447 resolve (function_resolver
&r
) const override
1449 return r
.resolve_uniform_opt_n (2);
1454 /* <T0>xN_t vfoo[_t0](uint64_t, uint64_t)
1456 where there are N arguments in total.
1458 int16x8_t [__arm_]vcreateq_s16(uint64_t a, uint64_t b) */
1459 struct create_def
: public nonoverloaded_base
1462 build (function_builder
&b
, const function_group_info
&group
,
1463 bool preserve_user_namespace
) const override
1465 build_all (b
, "v0,su64,su64", group
, MODE_none
, preserve_user_namespace
);
1470 /* <T0>[xN]_t vfoo_t0().
1472 Example: vuninitializedq.
1473 int8x16_t [__arm_]vuninitializedq_s8(void)
1474 int8x16_t [__arm_]vuninitializedq(int8x16_t t) */
1475 struct inherent_def
: public nonoverloaded_base
1478 build (function_builder
&b
, const function_group_info
&group
,
1479 bool preserve_user_namespace
) const override
1481 build_all (b
, "t0", group
, MODE_none
, preserve_user_namespace
);
1486 /* <T0>_t vfoo[_t0](const <s0>_t *)
1488 where <s0> is the scalar name of <T0>.
1491 int8x16_t [__arm_]vld1q[_s8](int8_t const *base)
1492 int8x16_t [__arm_]vld1q_z[_s8](int8_t const *base, mve_pred16_t p) */
1493 struct load_def
: public overloaded_base
<0>
1496 build (function_builder
&b
, const function_group_info
&group
,
1497 bool preserve_user_namespace
) const override
1499 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
1500 build_all (b
, "t0,al", group
, MODE_none
, preserve_user_namespace
);
1503 /* Resolve a call based purely on a pointer argument. */
1505 resolve (function_resolver
&r
) const override
1507 gcc_assert (r
.mode_suffix_id
== MODE_none
);
1509 unsigned int i
, nargs
;
1510 type_suffix_index type
;
1511 if (!r
.check_gp_argument (1, i
, nargs
)
1512 || (type
= r
.infer_pointer_type (i
)) == NUM_TYPE_SUFFIXES
)
1513 return error_mark_node
;
1515 return r
.resolve_to (r
.mode_suffix_id
, type
);
1520 /* <T0>_t foo_t0 (const <X>_t *)
1522 where <X> is determined by the function base name.
1525 int32x4_t [__arm_]vldrwq_s32 (int32_t const *base)
1526 uint32x4_t [__arm_]vldrhq_z_u32 (uint16_t const *base, mve_pred16_t p) */
1527 struct load_ext_def
: public nonoverloaded_base
1530 build (function_builder
&b
, const function_group_info
&group
,
1531 bool preserve_user_namespace
) const override
1533 build_all (b
, "t0,al", group
, MODE_none
, preserve_user_namespace
);
1538 /* Base class for load_ext_gather_offset and load_ext_gather_shifted_offset,
1539 which differ only in the units of the displacement. */
1540 struct load_ext_gather
: public overloaded_base
<0>
1543 explicit_mode_suffix_p (enum predication_index
, enum mode_suffix_index
) const override
1549 mode_after_pred () const override
1555 /* <T0>_t vfoo[_t0](<X>_t, const int)
1557 where <X> has the same width as <T0> but is of unsigned type.
1559 Example: vldrwq_gather_base
1560 int32x4_t [__arm_]vldrwq_gather_base_s32(uint32x4_t addr, const int offset)
1561 float32x4_t [__arm_]vldrwq_gather_base_z_f32(uint32x4_t addr, const int offset, mve_pred16_t p)
1562 int64x2_t [__arm_]vldrdq_gather_base_wb_s64(uint64x2_t *addr, const int offset) */
1563 struct load_gather_base_def
: public nonoverloaded_base
1566 explicit_mode_suffix_p (enum predication_index
, enum mode_suffix_index
) const override
1572 mode_after_pred () const override
1578 build (function_builder
&b
, const function_group_info
&group
,
1579 bool preserve_user_namespace
) const override
1581 build_all (b
, "v0,vu0,ss64", group
, MODE_none
, preserve_user_namespace
);
1582 build_all (b
, "v0,b,ss64", group
, MODE_wb
, preserve_user_namespace
);
1586 check (function_checker
&c
) const override
1588 unsigned int multiple
= c
.type_suffix (0).element_bits
/ 8;
1589 int bound
= 127 * multiple
;
1590 return c
.require_immediate_range_multiple (1, -bound
, bound
, multiple
);
1593 SHAPE (load_gather_base
)
1595 /* <T0>_t vfoo[_t0](<X>_t const *, <Y>_t)
1597 where <X> might be tied to <t0> (for non-extending loads) or might
1598 depend on the function base name (for extending loads),
1599 <Y> has the same width as <T0> but is of unsigned type.
1601 Example: vldrhq_gather_offset
1602 int16x8_t [__arm_]vldrhq_gather_offset[_s16](int16_t const *base, uint16x8_t offset)
1603 int32x4_t [__arm_]vldrhq_gather_offset_z[_s32](int16_t const *base, uint32x4_t offset, mve_pred16_t p) */
1604 struct load_ext_gather_offset_def
: public load_ext_gather
1607 build (function_builder
&b
, const function_group_info
&group
,
1608 bool preserve_user_namespace
) const override
1610 b
.add_overloaded_functions (group
, MODE_offset
, preserve_user_namespace
);
1611 build_all (b
, "v0,al,vu0", group
, MODE_offset
, preserve_user_namespace
);
1615 resolve (function_resolver
&r
) const override
1617 unsigned int i
, nargs
;
1618 mode_suffix_index mode
= MODE_offset
;
1619 type_suffix_index ptr_type
;
1620 type_suffix_index offset_type
;
1621 if (!r
.check_gp_argument (2, i
, nargs
)
1622 || (ptr_type
= r
.infer_pointer_type (0)) == NUM_TYPE_SUFFIXES
1623 || (offset_type
= r
.infer_vector_type (1)) == NUM_TYPE_SUFFIXES
)
1624 return error_mark_node
;
1626 /* tclass comes from base argument, element bits come from the offset
1628 type_suffix_index type
= find_type_suffix (type_suffixes
[ptr_type
].tclass
,
1629 type_suffixes
[offset_type
].element_bits
);
1631 return r
.resolve_to (mode
, type
);
1634 SHAPE (load_ext_gather_offset
)
1636 /* <T0>_t vfoo[_t0](<T0>_t)
1637 <T0>_t vfoo_n_t0(<sT0>_t)
1639 For MODE_n, define only the 16 and 32 bits versions.
1642 int16x8_t [__arm_]vmvnq[_s16](int16x8_t a)
1643 int16x8_t [__arm_]vmvnq_m[_s16](int16x8_t inactive, int16x8_t a, mve_pred16_t p)
1644 int16x8_t [__arm_]vmvnq_x[_s16](int16x8_t a, mve_pred16_t p)
1645 int16x8_t [__arm_]vmvnq_n_s16(const int16_t imm)
1646 int16x8_t [__arm_]vmvnq_m[_n_s16](int16x8_t inactive, const int16_t imm, mve_pred16_t p)
1647 int16x8_t [__arm_]vmvnq_x_n_s16(const int16_t imm, mve_pred16_t p) */
1648 struct mvn_def
: public overloaded_base
<0>
1651 build (function_builder
&b
, const function_group_info
&group
,
1652 bool preserve_user_namespace
) const override
1654 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
1655 /* Do not build a separate instance for MODE_n, since we want to
1656 share vmvnq_m[_n_s16] with vmvnq_m[_s16]. */
1657 build_all (b
, "v0,v0", group
, MODE_none
, preserve_user_namespace
);
1658 build_16_32 (b
, "v0,s0", group
, MODE_n
, preserve_user_namespace
);
1662 resolve (function_resolver
&r
) const override
1664 unsigned int i
, nargs
;
1665 type_suffix_index type
;
1666 if (!r
.check_gp_argument (1, i
, nargs
)
1667 /* Same type for arg 0 and 1 if _m, so using 0 is OK */
1668 || (type
= r
.infer_vector_type (0)) == NUM_TYPE_SUFFIXES
)
1669 return error_mark_node
;
1671 /* Skip last argument, may be scalar. */
1672 unsigned int last_arg
= i
;
1673 for (i
= 0; i
< last_arg
; i
++)
1674 if (!r
.require_matching_vector_type (i
, type
))
1675 return error_mark_node
;
1678 return r
.resolve_to (r
.mode_suffix_id
, type
);
1680 return r
.finish_opt_n_resolution (last_arg
, 0, type
);
1685 /* void vfoo[_t0](<X>_t *, <T0>[xN]_t)
1687 where <X> might be tied to <t0> (for non-truncating stores) or might
1688 depend on the function base name (for truncating stores).
1691 void [__arm_]vst1q[_s8](int8_t *base, int8x16_t value)
1692 void [__arm_]vst1q_p[_s8](int8_t *base, int8x16_t value, mve_pred16_t p)
1695 void [__arm_]vstrbq[_s16](int8_t *base, int16x8_t value)
1696 void [__arm_]vstrbq_p[_s16](int8_t *base, int16x8_t value, mve_pred16_t p) */
1697 struct store_def
: public overloaded_base
<0>
1700 build (function_builder
&b
, const function_group_info
&group
,
1701 bool preserve_user_namespace
) const override
1703 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
1704 build_all (b
, "_,as,t0", group
, MODE_none
, preserve_user_namespace
);
1708 resolve (function_resolver
&r
) const override
1710 gcc_assert (r
.mode_suffix_id
== MODE_none
);
1712 unsigned int i
, nargs
;
1713 type_suffix_index type
;
1714 if (!r
.check_gp_argument (2, i
, nargs
)
1715 || !r
.require_pointer_type (0)
1716 || (type
= r
.infer_tuple_type (1)) == NUM_TYPE_SUFFIXES
)
1717 return error_mark_node
;
1719 return r
.resolve_to (r
.mode_suffix_id
, type
);
1724 /* Base class for store_scatter_offset and store_scatter_shifted_offset, which
1725 differ only in the units of the displacement. Also used by
1726 store_scatter_base. */
1727 struct store_scatter
: public overloaded_base
<0>
1730 explicit_mode_suffix_p (enum predication_index
, enum mode_suffix_index
) const override
1736 mode_after_pred () const override
1742 /* void vfoo[_t0](<X>_t *, <Y>_t, <T0>_t)
1744 where <X> might be tied to <t0> (for non-truncating stores) or might
1745 depend on the function base name (for truncating stores),
1746 <Y> has the same width as <T0> but is of unsigned type.
1748 Example: vstrbq_scatter_offset
1749 void [__arm_]vstrbq_scatter_offset[_s16](int8_t *base, uint16x8_t offset, int16x8_t value)
1750 void [__arm_]vstrbq_scatter_offset_p[_s16](int8_t *base, uint16x8_t offset, int16x8_t value, mve_pred16_t p) */
1751 struct store_scatter_offset_def
: public store_scatter
1754 build (function_builder
&b
, const function_group_info
&group
,
1755 bool preserve_user_namespace
) const override
1757 b
.add_overloaded_functions (group
, MODE_offset
, preserve_user_namespace
);
1758 build_all (b
, "_,as,vu0,v0", group
, MODE_offset
, preserve_user_namespace
);
1761 /* Resolve a scatter store that takes a scalar pointer base and a vector
1764 The stored data is the final argument, and it determines the
1767 resolve (function_resolver
&r
) const override
1769 unsigned int i
, nargs
;
1770 type_suffix_index type
;
1771 if (!r
.check_gp_argument (3, i
, nargs
)
1772 || !r
.require_pointer_type (0)
1773 || (type
= r
.infer_vector_type (2)) == NUM_TYPE_SUFFIXES
)
1774 return error_mark_node
;
1776 /* Offset (arg 1) should be a vector of unsigned with same width as value
1778 type_suffix_index offset_type
1779 = find_type_suffix (TYPE_unsigned
, type_suffixes
[type
].element_bits
);
1780 if (!r
.require_matching_vector_type (1, offset_type
))
1781 return error_mark_node
;
1783 return r
.resolve_to (r
.mode_suffix_id
, type
);
1786 SHAPE (store_scatter_offset
)
1788 /* void vfoo[_t0](<Y>_t, const int, <T0>_t)
1790 where <X> is tied to <t0>.
1791 <Y> has the same width as <T0> but is of unsigned type.
1793 Example: vstrbq_scatter_base
1794 void [__arm_]vstrwq_scatter_base[_s32](uint32x4_t addr, const int offset, int32x4_t value)
1795 void [__arm_]vstrwq_scatter_base_p[_s32](uint32x4_t addr, const int offset, int32x4_t value, mve_pred16_t p)
1796 void [__arm_]vstrdq_scatter_base_wb[_s64](uint64x2_t *addr, const int offset, int64x2_t value) */
1797 struct store_scatter_base_def
: public store_scatter
1800 build (function_builder
&b
, const function_group_info
&group
,
1801 bool preserve_user_namespace
) const override
1803 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
1804 b
.add_overloaded_functions (group
, MODE_wb
, preserve_user_namespace
);
1805 build_all (b
, "_,vu0,ss64,v0", group
, MODE_none
, preserve_user_namespace
);
1806 build_all (b
, "_,b,ss64,v0", group
, MODE_wb
, preserve_user_namespace
);
1810 resolve (function_resolver
&r
) const override
1812 gcc_assert ((r
.mode_suffix_id
== MODE_none
)
1813 || (r
.mode_suffix_id
== MODE_wb
));
1815 unsigned int i
, nargs
;
1816 type_suffix_index type
;
1817 if (!r
.check_gp_argument (3, i
, nargs
)
1818 || !r
.require_integer_immediate (1)
1819 || (type
= r
.infer_vector_type (2)) == NUM_TYPE_SUFFIXES
)
1820 return error_mark_node
;
1822 type_suffix_index base_type
1823 = find_type_suffix (TYPE_unsigned
, type_suffixes
[type
].element_bits
);
1825 if (r
.mode_suffix_id
== MODE_none
)
1827 /* Base (arg 0) should be a vector of unsigned with same width as value
1829 if (!r
.require_matching_vector_type (0, base_type
))
1830 return error_mark_node
;
1834 /* Base (arg 0) should be a pointer to a vector of unsigned with the
1835 same width as value (arg 2). */
1836 if (!r
.require_pointer_to_type (0, r
.get_vector_type (base_type
)))
1837 return error_mark_node
;
1840 return r
.resolve_to (r
.mode_suffix_id
, type
);
1844 check (function_checker
&c
) const override
1846 int multiple
= c
.type_suffix (0).element_bits
/ 8;
1847 int bound
= 127 * multiple
;
1848 return c
.require_immediate_range_multiple (1, -bound
, bound
, multiple
);
1851 SHAPE (store_scatter_base
)
1853 /* <T0>_t vfoo[_t0](<T0>_t, <T0>_t, <T0>_t)
1855 i.e. the standard shape for ternary operations that operate on
1858 Example: vqrdmlsdhxq.
1859 int8x16_t [__arm_]vqrdmlsdhxq[_s8](int8x16_t inactive, int8x16_t a, int8x16_t b)
1860 int8x16_t [__arm_]vqrdmlsdhxq_m[_s8](int8x16_t inactive, int8x16_t a, int8x16_t b, mve_pred16_t p) */
1861 struct ternary_def
: public overloaded_base
<0>
1864 build (function_builder
&b
, const function_group_info
&group
,
1865 bool preserve_user_namespace
) const override
1867 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
1868 build_all (b
, "v0,v0,v0,v0", group
, MODE_none
, preserve_user_namespace
);
1872 resolve (function_resolver
&r
) const override
1874 return r
.resolve_uniform_opt_n (3);
1879 /* <T0>_t vfoo[_t0](<T0>_t, <T0>_t, const int)
1881 i.e. ternary operations that operate on a pair of vectors of the
1882 same type as the destination, and take a third integer argument.
1884 Check that 'imm' is in the [0..#bits-1] range.
1887 int16x8_t [__arm_]vsliq[_n_s16](int16x8_t a, int16x8_t b, const int imm)
1888 int16x8_t [__arm_]vsliq_m[_n_s16](int16x8_t a, int16x8_t b, const int imm, mve_pred16_t p) */
1889 struct ternary_lshift_def
: public overloaded_base
<0>
1892 build (function_builder
&b
, const function_group_info
&group
,
1893 bool preserve_user_namespace
) const override
1895 b
.add_overloaded_functions (group
, MODE_n
, preserve_user_namespace
);
1896 build_all (b
, "v0,v0,v0,su64", group
, MODE_n
, preserve_user_namespace
);
1900 resolve (function_resolver
&r
) const override
1902 return r
.resolve_uniform (2, 1);
1906 check (function_checker
&c
) const override
1908 if (c
.mode_suffix_id
!= MODE_n
)
1911 unsigned int bits
= c
.type_suffix (0).element_bits
;
1912 return c
.require_immediate_range (2, 0, bits
- 1);
1915 SHAPE (ternary_lshift
)
1917 /* <T0>_t vfoo[_n_t0](<T0>_t, <T0>_t, <S0>_t)
1919 i.e. the standard shape for ternary operations that operate on a
1920 pair of vectors of the same type as the destination, and take a
1921 third scalar argument of the same type as the vector elements.
1924 int8x16_t [__arm_]vmlaq[_n_s8](int8x16_t add, int8x16_t m1, int8_t m2)
1925 int8x16_t [__arm_]vmlaq_m[_n_s8](int8x16_t add, int8x16_t m1, int8_t m2, mve_pred16_t p) */
1926 struct ternary_n_def
: public overloaded_base
<0>
1929 build (function_builder
&b
, const function_group_info
&group
,
1930 bool preserve_user_namespace
) const override
1932 b
.add_overloaded_functions (group
, MODE_n
, preserve_user_namespace
);
1933 build_all (b
, "v0,v0,v0,s0", group
, MODE_n
, preserve_user_namespace
);
1937 resolve (function_resolver
&r
) const override
1939 return r
.resolve_uniform (2, 1);
1944 /* <T0>_t vfoo[_t0](<T0>_t, <T0>_t, <T0>_t)
1945 <T0>_t vfoo[_n_t0](<T0>_t, <T0>_t, <S0>_t)
1947 i.e. the standard shape for ternary operations that operate on
1951 float16x8_t [__arm_]vfmaq[_n_f16](float16x8_t add, float16x8_t m1, float16_t m2)
1952 float16x8_t [__arm_]vfmaq_m[_n_f16](float16x8_t add, float16x8_t m1, float16_t m2, mve_pred16_t p)
1953 float16x8_t [__arm_]vfmaq[_f16](float16x8_t add, float16x8_t m1, float16x8_t m2)
1954 float16x8_t [__arm_]vfmaq_m[_f16](float16x8_t add, float16x8_t m1, float16x8_t m2, mve_pred16_t p) */
1955 struct ternary_opt_n_def
: public overloaded_base
<0>
1958 build (function_builder
&b
, const function_group_info
&group
,
1959 bool preserve_user_namespace
) const override
1961 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
1962 build_all (b
, "v0,v0,v0,v0", group
, MODE_none
, preserve_user_namespace
);
1963 build_all (b
, "v0,v0,v0,s0", group
, MODE_n
, preserve_user_namespace
);
1967 resolve (function_resolver
&r
) const override
1969 return r
.resolve_uniform_opt_n (3);
1972 SHAPE (ternary_opt_n
)
1974 /* <T0>_t vfoo[_t0](<T0>_t, <T0>_t, const int)
1976 i.e. ternary operations that operate on a pair of vectors of the
1977 same type as the destination, and take a third integer argument.
1979 Check that 'imm' is in the [1..#bits] range.
1982 int8x16_t [__arm_]vsriq[_n_s8](int8x16_t a, int8x16_t b, const int imm)
1983 int8x16_t [__arm_]vsriq_m[_n_s8](int8x16_t a, int8x16_t b, const int imm, mve_pred16_t p) */
1984 struct ternary_rshift_def
: public overloaded_base
<0>
1987 build (function_builder
&b
, const function_group_info
&group
,
1988 bool preserve_user_namespace
) const override
1990 b
.add_overloaded_functions (group
, MODE_n
, preserve_user_namespace
);
1991 build_all (b
, "v0,v0,v0,su64", group
, MODE_n
, preserve_user_namespace
);
1995 resolve (function_resolver
&r
) const override
1997 return r
.resolve_uniform (2, 1);
2001 check (function_checker
&c
) const override
2003 if (c
.mode_suffix_id
!= MODE_n
)
2006 unsigned int bits
= c
.type_suffix (0).element_bits
;
2007 return c
.require_immediate_range (2, 1, bits
);
2010 SHAPE (ternary_rshift
)
2012 /* <T0>_t vfoo[_t0](<T0>_t)
2014 i.e. the standard shape for unary operations that operate on
2018 int8x16_t [__arm_]vabsq[_s8](int8x16_t a)
2019 int8x16_t [__arm_]vabsq_m[_s8](int8x16_t inactive, int8x16_t a, mve_pred16_t p)
2020 int8x16_t [__arm_]vabsq_x[_s8](int8x16_t a, mve_pred16_t p) */
2021 struct unary_def
: public overloaded_base
<0>
2024 build (function_builder
&b
, const function_group_info
&group
,
2025 bool preserve_user_namespace
) const override
2027 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
2028 build_all (b
, "v0,v0", group
, MODE_none
, preserve_user_namespace
);
2032 resolve (function_resolver
&r
) const override
2034 return r
.resolve_unary ();
2039 /* <S0:twice>_t vfoo[_<t0>](<T0>_t)
2041 i.e. a version of "unary" in which the source elements are half the
2042 size of the destination scalar, but have the same type class.
2045 int64_t [__arm_]vaddlvq[_s32](int32x4_t a)
2046 int64_t [__arm_]vaddlvq_p[_s32](int32x4_t a, mve_pred16_t p) */
2047 struct unary_acc_def
: public overloaded_base
<0>
2050 build (function_builder
&b
, const function_group_info
&group
,
2051 bool preserve_user_namespace
) const override
2053 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
2054 build_all (b
, "sw0,v0", group
, MODE_none
, preserve_user_namespace
);
2058 resolve (function_resolver
&r
) const override
2060 /* FIXME: check that the return value is actually
2061 twice as wide as arg 0. */
2062 return r
.resolve_unary ();
2067 /* <T0>_t foo_t0[_t1](<T1>_t)
2069 where the target type <t0> must be specified explicitly but the source
2070 type <t1> can be inferred.
2072 Example: vreinterpretq.
2073 int16x8_t [__arm_]vreinterpretq_s16[_s8](int8x16_t a)
2074 int32x4_t [__arm_]vreinterpretq_s32[_s8](int8x16_t a)
2075 int8x16_t [__arm_]vreinterpretq_s8[_s16](int16x8_t a)
2076 int8x16_t [__arm_]vreinterpretq_s8[_s32](int32x4_t a) */
2077 struct unary_convert_def
: public overloaded_base
<1>
2080 build (function_builder
&b
, const function_group_info
&group
,
2081 bool preserve_user_namespace
) const override
2083 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
2084 build_all (b
, "v0,v1", group
, MODE_none
, preserve_user_namespace
);
2088 resolve (function_resolver
&r
) const override
2090 return r
.resolve_unary ();
2093 SHAPE (unary_convert
)
2095 /* [u]int32_t vfoo[_<t0>](<T0>_t)
2097 i.e. a version of "unary" which generates a scalar of type int32_t
2098 or uint32_t depending on the signedness of the elements of of input
2102 int32_t [__arm_]vaddvq[_s16](int16x8_t a)
2103 int32_t [__arm_]vaddvq_p[_s16](int16x8_t a, mve_pred16_t p) */
2104 struct unary_int32_def
: public overloaded_base
<0>
2107 build (function_builder
&b
, const function_group_info
&group
,
2108 bool preserve_user_namespace
) const override
2110 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
2111 build_all (b
, "sx32,v0", group
, MODE_none
, preserve_user_namespace
);
2115 resolve (function_resolver
&r
) const override
2117 return r
.resolve_uniform (1);
2122 /* [u]int32_t vfoo[_<t0>]([u]int32_t, <T0>_t)
2124 i.e. a version of "unary" which accumulates into scalar of type
2125 int32_t or uint32_t depending on the signedness of the elements of
2129 int32_t [__arm_]vaddvaq[_s16](int32_t a, int16x8_t b)
2130 int32_t [__arm_]vaddvaq_p[_s16](int32_t a, int16x8_t b, mve_pred16_t p) */
2131 struct unary_int32_acc_def
: public overloaded_base
<0>
2134 build (function_builder
&b
, const function_group_info
&group
,
2135 bool preserve_user_namespace
) const override
2137 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
2138 build_all (b
, "sx32,sx32,v0", group
, MODE_none
, preserve_user_namespace
);
2142 resolve (function_resolver
&r
) const override
2144 unsigned int i
, nargs
;
2145 type_suffix_index type
;
2146 const char *first_type_name
;
2148 if (!r
.check_gp_argument (2, i
, nargs
)
2149 || (type
= r
.infer_vector_type (1)) == NUM_TYPE_SUFFIXES
)
2150 return error_mark_node
;
2152 first_type_name
= (type_suffixes
[type
].unsigned_p
2155 if (!r
.require_scalar_type (0, first_type_name
))
2156 return error_mark_node
;
2158 return r
.resolve_to (r
.mode_suffix_id
, type
);
2161 SHAPE (unary_int32_acc
)
2163 /* <T0>_t vfoo[_n]_t0(<S0>_t)
2166 int16x8_t [__arm_]vdupq_n_s16(int16_t a)
2167 int16x8_t [__arm_]vdupq_m[_n_s16](int16x8_t inactive, int16_t a, mve_pred16_t p)
2168 int16x8_t [__arm_]vdupq_x_n_s16(int16_t a, mve_pred16_t p) */
2169 struct unary_n_def
: public overloaded_base
<0>
2172 explicit_type_suffix_p (unsigned int, enum predication_index pred
,
2173 enum mode_suffix_index
, type_suffix_info
) const override
2175 return pred
!= PRED_m
;
2179 explicit_mode_suffix_p (enum predication_index pred
,
2180 enum mode_suffix_index mode
) const override
2182 return ((mode
== MODE_n
)
2183 && (pred
!= PRED_m
));
2187 skip_overload_p (enum predication_index pred
, enum mode_suffix_index mode
)
2193 return pred
!= PRED_m
;
2201 build (function_builder
&b
, const function_group_info
&group
,
2202 bool preserve_user_namespace
) const override
2204 b
.add_overloaded_functions (group
, MODE_n
, preserve_user_namespace
);
2205 build_all (b
, "v0,s0", group
, MODE_n
, preserve_user_namespace
);
2209 resolve (function_resolver
&r
) const override
2211 return r
.resolve_unary_n ();
2216 /* <T0:twice>_t vfoo[_t0](<T0>_t)
2218 i.e. a version of "unary" in which the source elements are half the
2219 size of the destination, but have the same type class.
2222 int32x4_t [__arm_]vmovlbq[_s16](int16x8_t a)
2223 int32x4_t [__arm_]vmovlbq_m[_s16](int32x4_t inactive, int16x8_t a, mve_pred16_t p)
2224 int32x4_t [__arm_]vmovlbq_x[_s16](int16x8_t a, mve_pred16_t p) */
2225 struct unary_widen_def
: public overloaded_base
<0>
2228 build (function_builder
&b
, const function_group_info
&group
,
2229 bool preserve_user_namespace
) const override
2231 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
2232 build_all (b
, "vw0,v0", group
, MODE_none
, preserve_user_namespace
);
2236 resolve (function_resolver
&r
) const override
2238 unsigned int i
, nargs
;
2239 type_suffix_index type
, wide_suffix
;
2241 if (!r
.check_gp_argument (1, i
, nargs
)
2242 || (type
= r
.infer_vector_type (i
)) == NUM_TYPE_SUFFIXES
2243 || ((wide_suffix
= long_type_suffix (r
, type
, r
.SAME_TYPE_CLASS
))
2244 == NUM_TYPE_SUFFIXES
))
2245 return error_mark_node
;
2247 /* Check the inactive argument has the wide type. */
2248 if ((r
.pred
== PRED_m
)
2249 && (r
.infer_vector_type (0) != wide_suffix
))
2250 return r
.report_no_such_form (type
);
2252 if ((res
= r
.lookup_form (r
.mode_suffix_id
, type
)))
2255 return r
.report_no_such_form (type
);
2260 /* <S0:twice>_t vfoo[_<t0>](<S0:twice>_t, <T0>_t)
2262 i.e. a version of "unary" in which the source elements are half the
2263 size of the destination scalar and accumulator, but have the same
2267 int64_t [__arm_]vaddlvaq[_s32](int64_t a, int32x4_t b)
2268 int64_t [__arm_]vaddlvaq_p[_s32](int64_t a, int32x4_t b, mve_pred16_t p) */
2269 struct unary_widen_acc_def
: public overloaded_base
<0>
2272 build (function_builder
&b
, const function_group_info
&group
,
2273 bool preserve_user_namespace
) const override
2275 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
2276 build_all (b
, "sw0,sw0,v0", group
, MODE_none
, preserve_user_namespace
);
2280 resolve (function_resolver
&r
) const override
2282 unsigned int i
, nargs
;
2283 type_suffix_index type
;
2284 if (!r
.check_gp_argument (2, i
, nargs
)
2285 || !r
.require_derived_scalar_type (0, r
.SAME_TYPE_CLASS
)
2286 || (type
= r
.infer_vector_type (i
)) == NUM_TYPE_SUFFIXES
)
2287 return error_mark_node
;
2289 return r
.resolve_to (r
.mode_suffix_id
, type
);
2292 SHAPE (unary_widen_acc
)
2294 /* <T0>_t vfoo[_t0](T0, T0, uint32_t*)
2297 int32x4_t [__arm_]vadcq[_s32](int32x4_t a, int32x4_t b, unsigned *carry)
2298 int32x4_t [__arm_]vadcq_m[_s32](int32x4_t inactive, int32x4_t a, int32x4_t b, unsigned *carry, mve_pred16_t p) */
2299 struct vadc_vsbc_def
: public overloaded_base
<0>
2302 build (function_builder
&b
, const function_group_info
&group
,
2303 bool preserve_user_namespace
) const override
2305 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
2306 build_all (b
, "v0,v0,v0,as", group
, MODE_none
, preserve_user_namespace
);
2310 resolve (function_resolver
&r
) const override
2312 unsigned int i
, nargs
;
2313 type_suffix_index type
;
2314 if (!r
.check_gp_argument (3, i
, nargs
)
2315 || (type
= r
.infer_vector_type (0)) == NUM_TYPE_SUFFIXES
)
2316 return error_mark_node
;
2318 if (!r
.require_matching_vector_type (1, type
))
2319 return error_mark_node
;
2321 /* Check that last arg is a pointer. */
2322 if (!POINTER_TYPE_P (r
.get_argument_type (i
)))
2323 return error_mark_node
;
2325 return r
.resolve_to (r
.mode_suffix_id
, type
);
2330 /* mve_pred16_t foo_t0(uint32_t)
2333 mve_pred16_t [__arm_]vctp16q(uint32_t a)
2334 mve_pred16_t [__arm_]vctp16q_m(uint32_t a, mve_pred16_t p) */
2335 struct vctp_def
: public nonoverloaded_base
2338 build (function_builder
&b
, const function_group_info
&group
,
2339 bool preserve_user_namespace
) const override
2341 build_all (b
, "p,su32", group
, MODE_none
, preserve_user_namespace
);
2346 /* <T0>_t foo_t0[_t1](<T1>_t)
2347 <T0>_t foo_t0_n[_t1](<T1>_t, const int)
2350 float32x4_t [__arm_]vcvtq[_f32_s32](int32x4_t a)
2351 float32x4_t [__arm_]vcvtq_m[_f32_s32](float32x4_t inactive, int32x4_t a, mve_pred16_t p)
2352 float32x4_t [__arm_]vcvtq_x[_f32_s32](int32x4_t a, mve_pred16_t p)
2353 float32x4_t [__arm_]vcvtq_n[_f32_s32](int32x4_t a, const int imm6)
2354 float32x4_t [__arm_]vcvtq_m_n[_f32_s32](float32x4_t inactive, int32x4_t a, const int imm6, mve_pred16_t p)
2355 float32x4_t [__arm_]vcvtq_x_n[_f32_s32](int32x4_t a, const int imm6, mve_pred16_t p)
2356 int32x4_t [__arm_]vcvtq_s32_f32(float32x4_t a)
2357 int32x4_t [__arm_]vcvtq_m[_s32_f32](int32x4_t inactive, float32x4_t a, mve_pred16_t p)
2358 int32x4_t [__arm_]vcvtq_x_s32_f32(float32x4_t a, mve_pred16_t p)
2359 int32x4_t [__arm_]vcvtq_n_s32_f32(float32x4_t a, const int imm6)
2360 int32x4_t [__arm_]vcvtq_m_n[_s32_f32](int32x4_t inactive, float32x4_t a, const int imm6, mve_pred16_t p)
2361 int32x4_t [__arm_]vcvtq_x_n_s32_f32(float32x4_t a, const int imm6, mve_pred16_t p) */
2362 struct vcvt_def
: public overloaded_base
<0>
2365 explicit_type_suffix_p (unsigned int i
, enum predication_index pred
,
2366 enum mode_suffix_index
,
2367 type_suffix_info type_info
) const override
2370 && ((i
== 0 && type_info
.integer_p
)
2371 || (i
== 1 && type_info
.float_p
)))
2377 explicit_mode_suffix_p (enum predication_index
,
2378 enum mode_suffix_index
) const override
2384 build (function_builder
&b
, const function_group_info
&group
,
2385 bool preserve_user_namespace
) const override
2387 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
2388 b
.add_overloaded_functions (group
, MODE_n
, preserve_user_namespace
);
2389 build_all (b
, "v0,v1", group
, MODE_none
, preserve_user_namespace
);
2390 build_all (b
, "v0,v1,su64", group
, MODE_n
, preserve_user_namespace
);
2394 resolve (function_resolver
&r
) const override
2396 unsigned int i
, nargs
;
2397 type_suffix_index from_type
;
2399 unsigned int nimm
= (r
.mode_suffix_id
== MODE_none
) ? 0 : 1;
2401 if (!r
.check_gp_argument (1 + nimm
, i
, nargs
)
2403 = r
.infer_vector_type (i
- nimm
)) == NUM_TYPE_SUFFIXES
)
2404 return error_mark_node
;
2407 && !r
.require_integer_immediate (i
))
2408 return error_mark_node
;
2410 type_suffix_index to_type
;
2412 if (type_suffixes
[from_type
].integer_p
)
2414 to_type
= find_type_suffix (TYPE_float
,
2415 type_suffixes
[from_type
].element_bits
);
2419 /* This should not happen: when 'from_type' is float, the type
2420 suffixes are not overloaded (except for "m" predication,
2422 gcc_assert (r
.pred
== PRED_m
);
2424 /* Get the return type from the 'inactive' argument. */
2425 to_type
= r
.infer_vector_type (0);
2428 if ((res
= r
.lookup_form (r
.mode_suffix_id
, to_type
, from_type
)))
2431 return r
.report_no_such_form (from_type
);
2435 check (function_checker
&c
) const override
2437 if (c
.mode_suffix_id
== MODE_none
)
2440 unsigned int bits
= c
.type_suffix (0).element_bits
;
2441 return c
.require_immediate_range (1, 1, bits
);
2446 /* float16x8_t foo_f16_f32(float16x8_t, float32x4_t)
2448 Example: vcvttq_f16_f32.
2449 float16x8_t [__arm_]vcvttq_f16_f32(float16x8_t a, float32x4_t b)
2450 float16x8_t [__arm_]vcvttq_m_f16_f32(float16x8_t a, float32x4_t b, mve_pred16_t p)
2452 struct vcvt_f16_f32_def
: public nonoverloaded_base
2455 build (function_builder
&b
, const function_group_info
&group
,
2456 bool preserve_user_namespace
) const override
2458 build_all (b
, "v0,v0,v1", group
, MODE_none
, preserve_user_namespace
);
2461 SHAPE (vcvt_f16_f32
)
2463 /* float32x4_t foo_f32_f16(float16x8_t)
2465 Example: vcvttq_f32_f16.
2466 float32x4_t [__arm_]vcvttq_f32_f16(float16x8_t a)
2467 float32x4_t [__arm_]vcvttq_m_f32_f16(float32x4_t inactive, float16x8_t a, mve_pred16_t p)
2468 float32x4_t [__arm_]vcvttq_x_f32_f16(float16x8_t a, mve_pred16_t p)
2470 struct vcvt_f32_f16_def
: public nonoverloaded_base
2473 build (function_builder
&b
, const function_group_info
&group
,
2474 bool preserve_user_namespace
) const override
2476 build_all (b
, "v0,v1", group
, MODE_none
, preserve_user_namespace
);
2479 SHAPE (vcvt_f32_f16
)
2481 /* <T0>_t foo_t0[_t1](<T1>_t)
2484 int16x8_t [__arm_]vcvtaq_s16_f16(float16x8_t a)
2485 int16x8_t [__arm_]vcvtaq_m[_s16_f16](int16x8_t inactive, float16x8_t a, mve_pred16_t p)
2486 int16x8_t [__arm_]vcvtaq_x_s16_f16(float16x8_t a, mve_pred16_t p)
2488 struct vcvtx_def
: public overloaded_base
<0>
2491 explicit_type_suffix_p (unsigned int, enum predication_index pred
,
2492 enum mode_suffix_index
,
2493 type_suffix_info
) const override
2495 return pred
!= PRED_m
;
2499 skip_overload_p (enum predication_index pred
, enum mode_suffix_index
)
2502 return pred
!= PRED_m
;
2506 build (function_builder
&b
, const function_group_info
&group
,
2507 bool preserve_user_namespace
) const override
2509 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
2510 build_all (b
, "v0,v1", group
, MODE_none
, preserve_user_namespace
);
2514 resolve (function_resolver
&r
) const override
2516 unsigned int i
, nargs
;
2517 type_suffix_index from_type
;
2520 if (!r
.check_gp_argument (1, i
, nargs
)
2522 = r
.infer_vector_type (i
)) == NUM_TYPE_SUFFIXES
)
2523 return error_mark_node
;
2525 type_suffix_index to_type
;
2527 gcc_assert (r
.pred
== PRED_m
);
2529 /* Get the return type from the 'inactive' argument. */
2530 to_type
= r
.infer_vector_type (0);
2532 if ((res
= r
.lookup_form (r
.mode_suffix_id
, to_type
, from_type
)))
2535 return r
.report_no_such_form (from_type
);
2540 /* <T0>_t vfoo[_n]_t0(uint32_t, const int)
2541 <T0>_t vfoo[_wb]_t0(uint32_t *, const int)
2543 Shape for vector increment or decrement and duplicate operations that take
2544 an integer or pointer to integer first argument and an immediate, and
2547 Check that 'imm' is one of 1, 2, 4 or 8.
2550 uint8x16_t [__arm_]vddupq[_n]_u8(uint32_t a, const int imm)
2551 uint8x16_t [__arm_]vddupq[_wb]_u8(uint32_t *a, const int imm)
2552 uint8x16_t [__arm_]vddupq_m[_n_u8](uint8x16_t inactive, uint32_t a, const int imm, mve_pred16_t p)
2553 uint8x16_t [__arm_]vddupq_m[_wb_u8](uint8x16_t inactive, uint32_t *a, const int imm, mve_pred16_t p)
2554 uint8x16_t [__arm_]vddupq_x[_n]_u8(uint32_t a, const int imm, mve_pred16_t p)
2555 uint8x16_t [__arm_]vddupq_x[_wb]_u8(uint32_t *a, const int imm, mve_pred16_t p) */
2556 struct viddup_def
: public overloaded_base
<0>
2559 explicit_type_suffix_p (unsigned int i
, enum predication_index pred
,
2560 enum mode_suffix_index
,
2561 type_suffix_info
) const override
2563 return ((i
== 0) && (pred
!= PRED_m
));
2567 skip_overload_p (enum predication_index
, enum mode_suffix_index mode
) const override
2569 /* For MODE_wb, share the overloaded instance with MODE_n. */
2570 if (mode
== MODE_wb
)
2577 build (function_builder
&b
, const function_group_info
&group
,
2578 bool preserve_user_namespace
) const override
2580 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
2581 build_all (b
, "v0,su32,su64", group
, MODE_n
, preserve_user_namespace
);
2582 build_all (b
, "v0,as,su64", group
, MODE_wb
, preserve_user_namespace
);
2586 resolve (function_resolver
&r
) const override
2588 unsigned int i
, nargs
;
2589 type_suffix_index type_suffix
= NUM_TYPE_SUFFIXES
;
2590 if (!r
.check_gp_argument (2, i
, nargs
))
2591 return error_mark_node
;
2593 type_suffix
= r
.type_suffix_ids
[0];
2594 /* With PRED_m, ther is no type suffix, so infer it from the first (inactive)
2596 if (type_suffix
== NUM_TYPE_SUFFIXES
)
2597 type_suffix
= r
.infer_vector_type (0);
2599 unsigned int last_arg
= i
- 1;
2600 /* Check that last_arg is either scalar or pointer. */
2601 if (!r
.scalar_argument_p (last_arg
))
2602 return error_mark_node
;
2604 if (!r
.require_integer_immediate (last_arg
+ 1))
2605 return error_mark_node
;
2607 /* With MODE_n we expect a scalar, with MODE_wb we expect a pointer. */
2608 mode_suffix_index mode_suffix
;
2609 if (POINTER_TYPE_P (r
.get_argument_type (last_arg
)))
2610 mode_suffix
= MODE_wb
;
2612 mode_suffix
= MODE_n
;
2614 return r
.resolve_to (mode_suffix
, type_suffix
);
2618 check (function_checker
&c
) const override
2620 return c
.require_immediate_one_of (1, 1, 2, 4, 8);
2625 /* <T0>_t vfoo[_n]_t0(uint32_t, uint32_t, const int)
2626 <T0>_t vfoo[_wb]_t0(uint32_t *, uint32_t, const int)
2628 Shape for vector increment or decrement with wrap and duplicate operations
2629 that take an integer or pointer to integer first argument, an integer second
2630 argument and an immediate, and produce a vector.
2632 Check that 'imm' is one of 1, 2, 4 or 8.
2635 uint8x16_t [__arm_]vdwdupq[_n]_u8(uint32_t a, uint32_t b, const int imm)
2636 uint8x16_t [__arm_]vdwdupq[_wb]_u8(uint32_t *a, uint32_t b, const int imm)
2637 uint8x16_t [__arm_]vdwdupq_m[_n_u8](uint8x16_t inactive, uint32_t a, uint32_t b, const int imm, mve_pred16_t p)
2638 uint8x16_t [__arm_]vdwdupq_m[_wb_u8](uint8x16_t inactive, uint32_t *a, uint32_t b, const int imm, mve_pred16_t p)
2639 uint8x16_t [__arm_]vdwdupq_x[_n]_u8(uint32_t a, uint32_t b, const int imm, mve_pred16_t p)
2640 uint8x16_t [__arm_]vdwdupq_x[_wb]_u8(uint32_t *a, uint32_t b, const int imm, mve_pred16_t p) */
2641 struct vidwdup_def
: public overloaded_base
<0>
2644 explicit_type_suffix_p (unsigned int i
, enum predication_index pred
,
2645 enum mode_suffix_index
,
2646 type_suffix_info
) const override
2648 return ((i
== 0) && (pred
!= PRED_m
));
2652 skip_overload_p (enum predication_index
, enum mode_suffix_index mode
) const override
2654 /* For MODE_wb, share the overloaded instance with MODE_n. */
2655 if (mode
== MODE_wb
)
2662 build (function_builder
&b
, const function_group_info
&group
,
2663 bool preserve_user_namespace
) const override
2665 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
2666 build_all (b
, "v0,su32,su32,su64", group
, MODE_n
, preserve_user_namespace
);
2667 build_all (b
, "v0,as,su32,su64", group
, MODE_wb
, preserve_user_namespace
);
2671 resolve (function_resolver
&r
) const override
2673 unsigned int i
, nargs
;
2674 type_suffix_index type_suffix
= NUM_TYPE_SUFFIXES
;
2675 if (!r
.check_gp_argument (3, i
, nargs
))
2676 return error_mark_node
;
2678 type_suffix
= r
.type_suffix_ids
[0];
2679 /* With PRED_m, ther is no type suffix, so infer it from the first (inactive)
2681 if (type_suffix
== NUM_TYPE_SUFFIXES
)
2682 type_suffix
= r
.infer_vector_type (0);
2684 unsigned int last_arg
= i
- 2;
2685 /* Check that last_arg is either scalar or pointer. */
2686 if (!r
.scalar_argument_p (last_arg
))
2687 return error_mark_node
;
2689 if (!r
.scalar_argument_p (last_arg
+ 1))
2690 return error_mark_node
;
2692 if (!r
.require_integer_immediate (last_arg
+ 2))
2693 return error_mark_node
;
2695 /* With MODE_n we expect a scalar, with MODE_wb we expect a pointer. */
2696 mode_suffix_index mode_suffix
;
2697 if (POINTER_TYPE_P (r
.get_argument_type (last_arg
)))
2698 mode_suffix
= MODE_wb
;
2700 mode_suffix
= MODE_n
;
2702 return r
.resolve_to (mode_suffix
, type_suffix
);
2706 check (function_checker
&c
) const override
2708 return c
.require_immediate_one_of (2, 1, 2, 4, 8);
2713 /* <T0>_t vfoo[_t0](<T0>_t, <T0>_t, mve_pred16_t)
2715 i.e. a version of the standard ternary shape in which
2716 the final argument is always a set of predicates.
2719 int16x8_t [__arm_]vpselq[_s16](int16x8_t a, int16x8_t b, mve_pred16_t p) */
2720 struct vpsel_def
: public overloaded_base
<0>
2723 build (function_builder
&b
, const function_group_info
&group
,
2724 bool preserve_user_namespace
) const override
2726 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
2727 build_all (b
, "v0,v0,v0,p", group
, MODE_none
, preserve_user_namespace
);
2731 resolve (function_resolver
&r
) const override
2733 unsigned int i
, nargs
;
2734 type_suffix_index type
;
2735 if (!r
.check_gp_argument (3, i
, nargs
)
2736 || (type
= r
.infer_vector_type (0)) == NUM_TYPE_SUFFIXES
)
2737 return error_mark_node
;
2739 unsigned int last_arg
= i
;
2740 for (i
= 0; i
< last_arg
; i
++)
2741 if (!r
.require_matching_vector_type (i
, type
))
2742 return error_mark_node
;
2744 if (!r
.require_vector_type (2 , VECTOR_TYPE_mve_pred16_t
))
2745 return error_mark_node
;
2747 return r
.resolve_to (r
.mode_suffix_id
, type
);
2752 /* <T0>_t vfoo[_t0](T0, uint32_t* , const int)
2754 Check that 'imm' is in [1..32].
2757 uint8x16_t [__arm_]vshlcq[_u8](uint8x16_t a, uint32_t *b, const int imm)
2758 uint8x16_t [__arm_]vshlcq_m[_u8](uint8x16_t a, uint32_t *b, const int imm, mve_pred16_t p) */
2759 struct vshlc_def
: public overloaded_base
<0>
2762 build (function_builder
&b
, const function_group_info
&group
,
2763 bool preserve_user_namespace
) const override
2765 b
.add_overloaded_functions (group
, MODE_none
, preserve_user_namespace
);
2766 build_all (b
, "v0,v0,as,su64", group
, MODE_none
, preserve_user_namespace
);
2770 resolve (function_resolver
&r
) const override
2772 unsigned int i
, nargs
;
2773 type_suffix_index type
;
2774 if (!r
.check_gp_argument (3, i
, nargs
)
2775 || (type
= r
.infer_vector_type (0)) == NUM_TYPE_SUFFIXES
)
2776 return error_mark_node
;
2778 /* Check that arg #2 is a pointer. */
2779 if (!POINTER_TYPE_P (r
.get_argument_type (i
- 1)))
2780 return error_mark_node
;
2782 if (!r
.require_integer_immediate (i
))
2783 return error_mark_node
;
2785 return r
.resolve_to (r
.mode_suffix_id
, type
);
2789 check (function_checker
&c
) const override
2791 return c
.require_immediate_range (2, 1, 32);
2796 } /* end namespace arm_mve */