Daily bump.
[official-gcc.git] / gcc / config / arm / arm-mve-builtins-shapes.cc
blobaeb14530a0829b025d506c9d50d310c0709b09e9
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)
9 any later version.
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/>. */
20 #include "config.h"
21 #include "system.h"
22 #include "coretypes.h"
23 #include "tm.h"
24 #include "tree.h"
25 #include "rtl.h"
26 #include "memmodel.h"
27 #include "insn-codes.h"
28 #include "optabs.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. */
40 namespace arm_mve {
42 /* Return a representation of "const T *". */
43 static tree
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
51 function. */
52 static void
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
79 as the next argument.
81 Future intrinsics will extend this format. */
82 static type_suffix_index
83 parse_element_type (const function_instance &instance, const char *&format)
85 int ch = *format++;
88 if (ch == 's' || ch == 'u')
90 type_class_index tclass = (ch == 's' ? TYPE_signed
91 : TYPE_unsigned);
92 char *end;
93 unsigned int bits = strtol (format, &end, 10);
94 format = end;
95 if (bits == 0 || bits == 1)
96 bits = instance.type_suffix (bits).element_bits;
97 return find_type_suffix (tclass, bits);
100 if (ch == 'h')
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);
107 if (ch == 'w')
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);
114 if (ch == 'U')
116 type_suffix_index suffix = parse_element_type (instance, format);
117 return find_type_suffix (TYPE_unsigned,
118 type_suffixes[suffix].element_bits * 2);
121 if (ch == 'p')
123 type_suffix_index suffix = parse_element_type (instance, format);
124 return find_type_suffix (TYPE_poly,
125 type_suffixes[suffix].element_bits);
128 if (ch == 'x')
130 const char *next = format;
131 next = strstr (format, ",");
132 next+=2;
133 type_suffix_index suffix = parse_element_type (instance, next);
134 type_class_index tclass = type_suffixes[suffix].tclass;
135 char *end;
136 unsigned int bits = strtol (format, &end, 10);
137 format = end;
138 return find_type_suffix (tclass, bits);
141 if (ch == '0' || ch == '1')
142 return instance.type_suffix_ids[ch - '0'];
144 gcc_unreachable ();
147 /* Read and return a type from FORMAT for function INSTANCE. Advance
148 FORMAT beyond the type string. The format is:
150 _ - void
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. */
165 static tree
166 parse_type (const function_instance &instance, const char *&format)
168 int ch = *format++;
171 if (ch == '_')
172 return void_type_node;
174 if (ch == 'a')
176 ch = *format++;
177 if (ch == 'l')
178 return build_const_pointer (instance.memory_scalar_type ());
179 if (ch == 's') {
180 return build_pointer_type (instance.memory_scalar_type ());
182 gcc_unreachable ();
185 if (ch == 'b')
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);
194 if (ch == 'p')
195 return get_mve_pred16_t ();
197 if (ch == 's')
199 type_suffix_index suffix = parse_element_type (instance, format);
200 return scalar_types[type_suffixes[suffix].vector_type];
203 if (ch == 't')
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];
211 if (ch == 'v')
213 type_suffix_index suffix = parse_element_type (instance, format);
214 return acle_vector_types[0][type_suffixes[suffix].vector_type];
217 gcc_unreachable ();
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
226 argument types. */
227 static tree
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);
236 format += 1;
237 tree argument_type = parse_type (instance, format);
238 argument_types.quick_push (argument_type);
239 args += 1;
241 gcc_assert (format[0] == 0);
242 return return_type;
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. */
248 static void
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],
259 group.preds[pi]);
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
272 predicate. */
273 static void
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])
287 break;
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. */
303 static void
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])
317 break;
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
381 bool
382 explicit_type_suffix_p (unsigned int, enum predication_index,
383 enum mode_suffix_index, type_suffix_info) const override
385 return true;
388 bool
389 explicit_mode_suffix_p (enum predication_index, enum mode_suffix_index) const override
391 return true;
394 bool
395 skip_overload_p (enum predication_index, enum mode_suffix_index) const override
397 return false;
400 bool
401 mode_after_pred () const override
403 return true;
406 tree
407 resolve (function_resolver &) const override
409 gcc_unreachable ();
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
418 bool
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;
425 bool
426 explicit_mode_suffix_p (enum predication_index, enum mode_suffix_index) const override
428 return false;
431 bool
432 skip_overload_p (enum predication_index, enum mode_suffix_index) const override
434 return false;
437 bool
438 mode_after_pred () const override
440 return true;
444 /* <T0>_t vfoo[_t0](<T0>_t, <T0>_t)
446 i.e. the standard shape for binary operations that operate on
447 uniform types.
449 Example: vandq.
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>
455 void
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);
463 tree
464 resolve (function_resolver &r) const override
466 return r.resolve_uniform (2);
469 SHAPE (binary)
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.
477 Example: vmladavq.
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>
482 void
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);
490 tree
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)
500 Example: vmlaldavq.
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>
505 void
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);
513 tree
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)
523 Example: vmladavaq.
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>
528 void
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);
536 tree
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
548 ? "uint32_t"
549 : "int32_t");
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)
565 Example: vmlaldavaq.
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>
570 void
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);
578 tree
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
591 ? "uint64_t"
592 : "int64_t");
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.
611 Example: vbrsrq.
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>
617 void
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);
625 tree
626 resolve (function_resolver &r) const override
628 return r.resolve_uniform (1, 1);
631 SHAPE (binary_imm32)
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.
640 Example: vrshrq.
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>
646 void
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);
654 tree
655 resolve (function_resolver &r) const override
657 return r.resolve_uniform (1, 1);
660 bool
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.
678 Example: vqshluq.
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>
683 void
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);
691 tree
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);
715 bool
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.
730 Example: vminaq.
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>
735 void
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);
743 tree
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
753 type. */
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)
766 Example: vmaxavq.
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>
771 void
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);
779 tree
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)
796 Example: vmaxvq.
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>
801 void
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);
809 tree
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)
826 Example: vmovnbq.
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>
831 void
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);
839 tree
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)
860 Example: vqmovunbq.
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>
865 void
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);
873 tree
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
896 uniform types.
898 Example: vaddq.
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>
907 void
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);
916 tree
917 resolve (function_resolver &r) const override
919 return r.resolve_uniform_opt_n (2);
922 SHAPE (binary_opt_n)
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.
929 Example: 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>
942 bool
943 explicit_mode_suffix_p (enum predication_index pred, enum mode_suffix_index mode) const override
945 return (mode == MODE_n
946 && pred == PRED_m);
949 bool
950 skip_overload_p (enum predication_index pred, enum mode_suffix_index mode) const override
952 switch (mode)
954 case MODE_none:
955 return false;
957 /* For MODE_n, share the overloaded instance with MODE_none, except for PRED_m. */
958 case MODE_n:
959 return pred != PRED_m;
961 default:
962 gcc_unreachable ();
966 void
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);
976 tree
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);
988 SHAPE (binary_orrq)
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.
995 Example: vrshlq.
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>
1003 bool
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));
1010 bool
1011 skip_overload_p (enum predication_index pred, enum mode_suffix_index mode) const override
1013 switch (mode)
1015 case MODE_none:
1016 return false;
1018 /* For MODE_n, share the overloaded instance with MODE_none, except for PRED_m. */
1019 case MODE_n:
1020 return pred != PRED_m;
1022 default:
1023 gcc_unreachable ();
1027 void
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);
1037 tree
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
1055 vector types.
1057 For the MODE_n versions, check that 'imm' is in the [0..#bits-1] range.
1059 Example: vshlq.
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>
1068 bool
1069 explicit_mode_suffix_p (enum predication_index, enum mode_suffix_index) const override
1071 return true;
1074 void
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);
1084 tree
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);
1096 bool
1097 check (function_checker &c) const override
1099 if (c.mode_suffix_id != MODE_n)
1100 return true;
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
1115 vector types.
1116 Example: vshlq.
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>
1121 bool
1122 explicit_mode_suffix_p (enum predication_index, enum mode_suffix_index) const override
1124 return true;
1127 void
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);
1135 tree
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.
1154 Example: vqrshrnbq.
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>
1159 void
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);
1167 tree
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);
1185 bool
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.
1199 Example: vqshrunbq.
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>
1204 void
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);
1212 tree
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);
1230 bool
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)
1242 Example: vmullbq.
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>
1248 void
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);
1256 tree
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>
1288 void
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);
1296 tree
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
1307 width. */
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.
1333 Example: vshllbq.
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>
1339 void
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);
1347 tree
1348 resolve (function_resolver &r) const override
1350 unsigned int i, nargs;
1351 type_suffix_index type, wide_suffix;
1352 tree res;
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)))
1365 return res;
1367 return r.report_no_such_form (type);
1370 bool
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)
1383 Example: vqdmullbq.
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>
1390 void
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);
1399 tree
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--;
1413 for (; i > 0; 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
1428 uniform types.
1430 Examples: vcmpq.
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>
1437 void
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);
1446 tree
1447 resolve (function_resolver &r) const override
1449 return r.resolve_uniform_opt_n (2);
1452 SHAPE (cmp)
1454 /* <T0>xN_t vfoo[_t0](uint64_t, uint64_t)
1456 where there are N arguments in total.
1457 Example: vcreateq.
1458 int16x8_t [__arm_]vcreateq_s16(uint64_t a, uint64_t b) */
1459 struct create_def : public nonoverloaded_base
1461 void
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);
1468 SHAPE (create)
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
1477 void
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);
1484 SHAPE (inherent)
1486 /* <T0>_t vfoo[_t0](const <s0>_t *)
1488 where <s0> is the scalar name of <T0>.
1490 Example: vld1q.
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>
1495 void
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. */
1504 tree
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);
1518 SHAPE (load)
1520 /* <T0>_t foo_t0 (const <X>_t *)
1522 where <X> is determined by the function base name.
1524 Example: vldrq.
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
1529 void
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);
1536 SHAPE (load_ext)
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>
1542 bool
1543 explicit_mode_suffix_p (enum predication_index, enum mode_suffix_index) const override
1545 return true;
1548 bool
1549 mode_after_pred () const override
1551 return false;
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
1565 bool
1566 explicit_mode_suffix_p (enum predication_index, enum mode_suffix_index) const override
1568 return true;
1571 bool
1572 mode_after_pred () const override
1574 return false;
1577 void
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);
1585 bool
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
1606 void
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);
1614 tree
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
1627 argument. */
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.
1641 Example: vmvnq.
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>
1650 void
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);
1661 tree
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;
1677 if (last_arg == 0)
1678 return r.resolve_to (r.mode_suffix_id, type);
1680 return r.finish_opt_n_resolution (last_arg, 0, type);
1683 SHAPE (mvn)
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).
1690 Example: vst1q.
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)
1694 Example: vstrb.
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>
1699 void
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);
1707 tree
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);
1722 SHAPE (store)
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>
1729 bool
1730 explicit_mode_suffix_p (enum predication_index, enum mode_suffix_index) const override
1732 return true;
1735 bool
1736 mode_after_pred () const override
1738 return false;
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
1753 void
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
1762 displacement.
1764 The stored data is the final argument, and it determines the
1765 type suffix. */
1766 tree
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
1777 (arg 2). */
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
1799 void
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);
1809 tree
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
1828 (arg 2). */
1829 if (!r.require_matching_vector_type (0, base_type))
1830 return error_mark_node;
1832 else
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);
1843 bool
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
1856 uniform types.
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>
1863 void
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);
1871 tree
1872 resolve (function_resolver &r) const override
1874 return r.resolve_uniform_opt_n (3);
1877 SHAPE (ternary)
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.
1886 Example: vsliq.
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>
1891 void
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);
1899 tree
1900 resolve (function_resolver &r) const override
1902 return r.resolve_uniform (2, 1);
1905 bool
1906 check (function_checker &c) const override
1908 if (c.mode_suffix_id != MODE_n)
1909 return true;
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.
1923 Example: vmlaq.
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>
1928 void
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);
1936 tree
1937 resolve (function_resolver &r) const override
1939 return r.resolve_uniform (2, 1);
1942 SHAPE (ternary_n)
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
1948 uniform types.
1950 Example: vfmaq.
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>
1957 void
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);
1966 tree
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.
1981 Example: vsriq.
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>
1986 void
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);
1994 tree
1995 resolve (function_resolver &r) const override
1997 return r.resolve_uniform (2, 1);
2000 bool
2001 check (function_checker &c) const override
2003 if (c.mode_suffix_id != MODE_n)
2004 return true;
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
2015 uniform types.
2017 Example: vabsq.
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>
2023 void
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);
2031 tree
2032 resolve (function_resolver &r) const override
2034 return r.resolve_unary ();
2037 SHAPE (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.
2044 Example: vaddlvq.
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>
2049 void
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);
2057 tree
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 ();
2065 SHAPE (unary_acc)
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>
2079 void
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);
2087 tree
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
2099 vector.
2101 Example: vaddvq
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>
2106 void
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);
2114 tree
2115 resolve (function_resolver &r) const override
2117 return r.resolve_uniform (1);
2120 SHAPE (unary_int32)
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
2126 of input vector.
2128 Example: vaddvaq.
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>
2133 void
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);
2141 tree
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
2153 ? "uint32_t"
2154 : "int32_t");
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)
2165 Example: vdupq.
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>
2171 bool
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;
2178 bool
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));
2186 bool
2187 skip_overload_p (enum predication_index pred, enum mode_suffix_index mode)
2188 const override
2190 switch (mode)
2192 case MODE_n:
2193 return pred != PRED_m;
2195 default:
2196 gcc_unreachable ();
2200 void
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);
2208 tree
2209 resolve (function_resolver &r) const override
2211 return r.resolve_unary_n ();
2214 SHAPE (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.
2221 Example: vmovlbq.
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>
2227 void
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);
2235 tree
2236 resolve (function_resolver &r) const override
2238 unsigned int i, nargs;
2239 type_suffix_index type, wide_suffix;
2240 tree res;
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)))
2253 return res;
2255 return r.report_no_such_form (type);
2258 SHAPE (unary_widen)
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
2264 type class.
2266 Example: vaddlvaq.
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>
2271 void
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);
2279 tree
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*)
2296 Example: vadcq.
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>
2301 void
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);
2309 tree
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);
2328 SHAPE (vadc_vsbc)
2330 /* mve_pred16_t foo_t0(uint32_t)
2332 Example: vctp16q.
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
2337 void
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);
2344 SHAPE (vctp)
2346 /* <T0>_t foo_t0[_t1](<T1>_t)
2347 <T0>_t foo_t0_n[_t1](<T1>_t, const int)
2349 Example: vcvtq.
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>
2364 bool
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
2369 if (pred != PRED_m
2370 && ((i == 0 && type_info.integer_p)
2371 || (i == 1 && type_info.float_p)))
2372 return true;
2373 return false;
2376 bool
2377 explicit_mode_suffix_p (enum predication_index,
2378 enum mode_suffix_index) const override
2380 return true;
2383 void
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);
2393 tree
2394 resolve (function_resolver &r) const override
2396 unsigned int i, nargs;
2397 type_suffix_index from_type;
2398 tree res;
2399 unsigned int nimm = (r.mode_suffix_id == MODE_none) ? 0 : 1;
2401 if (!r.check_gp_argument (1 + nimm, i, nargs)
2402 || (from_type
2403 = r.infer_vector_type (i - nimm)) == NUM_TYPE_SUFFIXES)
2404 return error_mark_node;
2406 if (nimm > 0
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);
2417 else
2419 /* This should not happen: when 'from_type' is float, the type
2420 suffixes are not overloaded (except for "m" predication,
2421 handled above). */
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)))
2429 return res;
2431 return r.report_no_such_form (from_type);
2434 bool
2435 check (function_checker &c) const override
2437 if (c.mode_suffix_id == MODE_none)
2438 return true;
2440 unsigned int bits = c.type_suffix (0).element_bits;
2441 return c.require_immediate_range (1, 1, bits);
2444 SHAPE (vcvt)
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
2454 void
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
2472 void
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)
2483 Example: vcvtaq.
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>
2490 bool
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;
2498 bool
2499 skip_overload_p (enum predication_index pred, enum mode_suffix_index)
2500 const override
2502 return pred != PRED_m;
2505 void
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);
2513 tree
2514 resolve (function_resolver &r) const override
2516 unsigned int i, nargs;
2517 type_suffix_index from_type;
2518 tree res;
2520 if (!r.check_gp_argument (1, i, nargs)
2521 || (from_type
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)))
2533 return res;
2535 return r.report_no_such_form (from_type);
2538 SHAPE (vcvtx)
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
2545 produce a vector.
2547 Check that 'imm' is one of 1, 2, 4 or 8.
2549 Example: vddupq.
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>
2558 bool
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));
2566 bool
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)
2571 return true;
2573 return false;
2576 void
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);
2585 tree
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)
2595 argument. */
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;
2611 else
2612 mode_suffix = MODE_n;
2614 return r.resolve_to (mode_suffix, type_suffix);
2617 bool
2618 check (function_checker &c) const override
2620 return c.require_immediate_one_of (1, 1, 2, 4, 8);
2623 SHAPE (viddup)
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.
2634 Example: vdwdupq.
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>
2643 bool
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));
2651 bool
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)
2656 return true;
2658 return false;
2661 void
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);
2670 tree
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)
2680 argument. */
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;
2699 else
2700 mode_suffix = MODE_n;
2702 return r.resolve_to (mode_suffix, type_suffix);
2705 bool
2706 check (function_checker &c) const override
2708 return c.require_immediate_one_of (2, 1, 2, 4, 8);
2711 SHAPE (vidwdup)
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.
2718 Example: vpselq.
2719 int16x8_t [__arm_]vpselq[_s16](int16x8_t a, int16x8_t b, mve_pred16_t p) */
2720 struct vpsel_def : public overloaded_base<0>
2722 void
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);
2730 tree
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);
2750 SHAPE (vpsel)
2752 /* <T0>_t vfoo[_t0](T0, uint32_t* , const int)
2754 Check that 'imm' is in [1..32].
2756 Example: vshlcq.
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>
2761 void
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);
2769 tree
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);
2788 bool
2789 check (function_checker &c) const override
2791 return c.require_immediate_range (2, 1, 32);
2794 SHAPE (vshlc)
2796 } /* end namespace arm_mve */
2798 #undef SHAPE