RISC-V: Add testcases for unsigned .SAT_ADD vector form 8
[official-gcc.git] / gcc / config / aarch64 / aarch64-sve-builtins-shapes.cc
blobf190770250fecb0f42b441019d1a4f26fcc0cbdb
1 /* ACLE support for AArch64 SVE (function shapes)
2 Copyright (C) 2018-2024 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 "tm_p.h"
27 #include "memmodel.h"
28 #include "insn-codes.h"
29 #include "optabs.h"
30 #include "aarch64-sve-builtins.h"
31 #include "aarch64-sve-builtins-shapes.h"
32 #include "aarch64-builtins.h"
34 /* In the comments below, _t0 represents the first type suffix and _t1
35 represents the second. Square brackets enclose characters that are
36 present in only the full name, not the overloaded name. Governing
37 predicate arguments and predicate suffixes are not shown, since they
38 depend on the predication type, which is a separate piece of
39 information from the shape.
41 Non-overloaded functions may have additional suffixes beyond the
42 ones shown, if those suffixes don't affect the types in the type
43 signature. E.g. the predicate form of svtrn1 has a _b<bits> suffix,
44 but this does not affect the prototype, which is always
45 "svbool_t(svbool_t, svbool_t)". */
47 namespace aarch64_sve {
49 /* Return a representation of "const T *". */
50 static tree
51 build_const_pointer (tree t)
53 return build_pointer_type (build_qualified_type (t, TYPE_QUAL_CONST));
56 /* GROUP's first type suffix is a ZA-related one. Return true if the
57 group exists only for the purpose of defining C overloads. This is
58 useful if some forms of an instruction require one feature and other
59 forms require another feature, and neither feature implies the other. */
60 static bool
61 za_group_is_pure_overload (const function_group_info &group)
63 gcc_checking_assert (type_suffixes[group.types[0][0]].za_p);
64 return group.types[0][1] == NUM_TYPE_SUFFIXES;
67 /* If INSTANCE has a governing predicate, add it to the list of argument
68 types in ARGUMENT_TYPES. RETURN_TYPE is the type returned by the
69 function. */
70 static void
71 apply_predication (const function_instance &instance, tree return_type,
72 vec<tree> &argument_types)
74 /* There are currently no SME ZA instructions that have both merging and
75 unpredicated forms, so for simplicity, the predicates are always included
76 in the original format string. */
77 if (instance.pred != PRED_none && instance.pred != PRED_za_m)
79 argument_types.quick_insert (0, instance.gp_type ());
80 /* For unary merge operations, the first argument is a vector with
81 the same type as the result. For unary_convert_narrowt it also
82 provides the "bottom" half of active elements, and is present
83 for all types of predication. */
84 auto nargs = argument_types.length () - 1;
85 if (instance.shape->has_merge_argument_p (instance, nargs))
86 argument_types.quick_insert (0, return_type);
90 /* Parse and move past an element type in FORMAT and return it as a type
91 suffix. The format is:
93 [01] - the element type in type suffix 0 or 1 of INSTANCE
94 f<bits> - a floating-point type with the given number of bits
95 f[01] - a floating-point type with the same width as type suffix 0 or 1
96 B - bfloat16_t
97 c - a predicate-as-counter
98 h<elt> - a half-sized version of <elt>
99 p - a predicate (represented as TYPE_SUFFIX_b)
100 q<elt> - a quarter-sized version of <elt>
101 s<bits> - a signed type with the given number of bits
102 s[01] - a signed type with the same width as type suffix 0 or 1
103 u<bits> - an unsigned type with the given number of bits
104 u[01] - an unsigned type with the same width as type suffix 0 or 1
105 w<elt> - a 64-bit version of <elt> if <elt> is integral, otherwise <elt>
107 where <elt> is another element type. */
108 static type_suffix_index
109 parse_element_type (const function_instance &instance, const char *&format)
111 int ch = *format++;
113 if (ch == 'f' || ch == 's' || ch == 'u')
115 type_class_index tclass = (ch == 'f' ? TYPE_float
116 : ch == 's' ? TYPE_signed
117 : TYPE_unsigned);
118 char *end;
119 unsigned int bits = strtol (format, &end, 10);
120 format = end;
121 if (bits == 0 || bits == 1)
122 bits = instance.type_suffix (bits).element_bits;
123 return find_type_suffix (tclass, bits);
126 if (ch == 'w')
128 type_suffix_index suffix = parse_element_type (instance, format);
129 if (type_suffixes[suffix].integer_p)
130 return find_type_suffix (type_suffixes[suffix].tclass, 64);
131 return suffix;
134 if (ch == 'c')
135 return TYPE_SUFFIX_c;
137 if (ch == 'p')
138 return TYPE_SUFFIX_b;
140 if (ch == 'B')
141 return TYPE_SUFFIX_bf16;
143 if (ch == 'q')
145 type_suffix_index suffix = parse_element_type (instance, format);
146 return find_type_suffix (type_suffixes[suffix].tclass,
147 type_suffixes[suffix].element_bits / 4);
150 if (ch == 'h')
152 type_suffix_index suffix = parse_element_type (instance, format);
153 /* Widening and narrowing doesn't change the type for predicates;
154 everything's still an svbool_t. */
155 if (suffix == TYPE_SUFFIX_b)
156 return suffix;
157 return find_type_suffix (type_suffixes[suffix].tclass,
158 type_suffixes[suffix].element_bits / 2);
161 if (ch == '0' || ch == '1')
162 return instance.type_suffix_ids[ch - '0'];
164 gcc_unreachable ();
167 /* Read and return a type from FORMAT for function INSTANCE. Advance
168 FORMAT beyond the type string. The format is:
170 _ - void
171 al - array pointer for loads
172 ap - array pointer for prefetches
173 as - array pointer for stores
174 b - base vector type (from a _<m0>base suffix)
175 c0 - the result of a conversion, based on type and group suffixes
176 c1 - the source of a conversion, based on type and group suffixes
177 d - displacement vector type (from a _<m1>index or _<m1>offset suffix)
178 e<name> - an enum with the given name
179 s<elt> - a scalar type with the given element suffix
180 t<elt> - a vector or tuple type with given element suffix [*1]
181 v<elt> - a vector with the given element suffix
182 D<elt> - a 64 bit neon vector
183 Q<elt> - a 128 bit neon vector
185 where <elt> has the format described above parse_element_type
187 [*1] the vectors_per_tuple function indicates whether the type should
188 be a tuple, and if so, how many vectors it should contain. */
189 static tree
190 parse_type (const function_instance &instance, const char *&format)
192 int ch = *format++;
194 if (ch == '_')
195 return void_type_node;
197 if (ch == 'a')
199 ch = *format++;
200 if (ch == 'l')
201 return build_const_pointer (instance.memory_scalar_type ());
202 if (ch == 'p')
203 return const_ptr_type_node;
204 if (ch == 's')
205 return build_pointer_type (instance.memory_scalar_type ());
206 gcc_unreachable ();
209 if (ch == 'b')
210 return instance.base_vector_type ();
212 if (ch == 'c')
214 int ch = *format++;
215 gcc_assert (ch == '0' || ch == '1');
216 unsigned int id = (ch == '0' ? 0 : 1);
217 auto vector_type = instance.type_suffix (id).vector_type;
218 unsigned int num_vectors = instance.group_suffix ().vectors_per_tuple;
219 if (num_vectors != 1)
221 unsigned int bits = instance.type_suffix (id).element_bits;
222 unsigned int other_bits = instance.type_suffix (1 - id).element_bits;
223 if (other_bits > bits)
224 num_vectors /= other_bits / bits;
226 return acle_vector_types[num_vectors - 1][vector_type];
229 if (ch == 'd')
230 return instance.displacement_vector_type ();
232 if (ch == 'e')
234 if (startswith (format, "pattern"))
236 format += 7;
237 return acle_svpattern;
239 if (startswith (format, "prfop"))
241 format += 5;
242 return acle_svprfop;
244 gcc_unreachable ();
247 if (ch == 's')
249 type_suffix_index suffix = parse_element_type (instance, format);
250 return scalar_types[type_suffixes[suffix].vector_type];
253 if (ch == 't')
255 type_suffix_index suffix = parse_element_type (instance, format);
256 vector_type_index vector_type = type_suffixes[suffix].vector_type;
257 unsigned int num_vectors = instance.vectors_per_tuple ();
258 return acle_vector_types[num_vectors - 1][vector_type];
261 if (ch == 'v')
263 type_suffix_index suffix = parse_element_type (instance, format);
264 return acle_vector_types[0][type_suffixes[suffix].vector_type];
267 if (ch == 'D')
269 type_suffix_index suffix = parse_element_type (instance, format);
270 int neon_index = type_suffixes[suffix].neon64_type;
271 return aarch64_simd_types[neon_index].itype;
274 if (ch == 'Q')
276 type_suffix_index suffix = parse_element_type (instance, format);
277 int neon_index = type_suffixes[suffix].neon128_type;
278 return aarch64_simd_types[neon_index].itype;
281 gcc_unreachable ();
284 /* Read and move past any argument count at FORMAT for the function
285 signature of INSTANCE. The counts are:
287 *q: one argument per element in a 128-bit quadword (as for svdupq)
288 *t: one argument per vector in a tuple (as for svcreate)
290 Otherwise the count is 1. */
291 static unsigned int
292 parse_count (const function_instance &instance, const char *&format)
294 if (format[0] == '*' && format[1] == 'q')
296 format += 2;
297 return instance.elements_per_vq (0);
299 if (format[0] == '*' && format[1] == 't')
301 format += 2;
302 return instance.vectors_per_tuple ();
304 return 1;
307 /* Read a type signature for INSTANCE from FORMAT. Add the argument types
308 to ARGUMENT_TYPES and return the return type.
310 The format is a comma-separated list of types (as for parse_type),
311 with the first type being the return type and the rest being the
312 argument types. Each argument type can be followed by an optional
313 count (as for parse_count). */
314 static tree
315 parse_signature (const function_instance &instance, const char *format,
316 vec<tree> &argument_types)
318 tree return_type = parse_type (instance, format);
319 while (format[0] == ',')
321 format += 1;
322 tree argument_type = parse_type (instance, format);
323 unsigned int count = parse_count (instance, format);
324 for (unsigned int i = 0; i < count; ++i)
325 argument_types.quick_push (argument_type);
327 gcc_assert (format[0] == 0);
328 return return_type;
331 /* Add one function instance for GROUP, using mode suffix MODE_SUFFIX_ID,
332 the type suffixes at index TI, the group suffixes at index GI, and the
333 predication suffix at index PI. The other arguments are as for
334 build_all. */
335 static void
336 build_one (function_builder &b, const char *signature,
337 const function_group_info &group, mode_suffix_index mode_suffix_id,
338 unsigned int ti, unsigned int gi, unsigned int pi,
339 bool force_direct_overloads)
341 /* For simplicity, function definitions are allowed to use the group
342 suffix lists vg2 and vg4 for shapes that have _single forms,
343 even though the _single form applies only to vgNx2 and vgNx4,
344 not to vgNx1. */
345 if (mode_suffix_id == MODE_single
346 && group_suffixes[group.groups[gi]].vectors_per_tuple == 1)
347 return;
349 /* Byte forms of svdupq take 16 arguments. */
350 auto_vec<tree, 16> argument_types;
351 function_instance instance (group.base_name, *group.base, *group.shape,
352 mode_suffix_id, group.types[ti],
353 group.groups[gi], group.preds[pi]);
354 tree return_type = parse_signature (instance, signature, argument_types);
355 apply_predication (instance, return_type, argument_types);
356 b.add_unique_function (instance, return_type, argument_types,
357 group.required_extensions, force_direct_overloads);
360 /* GROUP describes some sort of gather or scatter operation. There are
361 two cases:
363 - If the function has any type suffixes (as for loads and stores), the
364 first function type suffix specifies either a 32-bit or a 64-bit type,
365 which in turn selects either MODE32 or MODE64 as the addressing mode.
366 Add a function instance for every type and predicate combination
367 in GROUP for which the associated addressing mode is not MODE_none.
369 - If the function has no type suffixes (as for prefetches), add one
370 MODE32 form and one MODE64 form for each predication type.
372 The other arguments are as for build_all. */
373 static void
374 build_32_64 (function_builder &b, const char *signature,
375 const function_group_info &group, mode_suffix_index mode32,
376 mode_suffix_index mode64, bool force_direct_overloads = false)
378 for (unsigned int pi = 0; group.preds[pi] != NUM_PREDS; ++pi)
379 for (unsigned int gi = 0; group.groups[gi] != NUM_GROUP_SUFFIXES; ++gi)
380 if (group.types[0][0] == NUM_TYPE_SUFFIXES)
382 gcc_assert (mode32 != MODE_none && mode64 != MODE_none);
383 build_one (b, signature, group, mode32, 0, gi, pi,
384 force_direct_overloads);
385 build_one (b, signature, group, mode64, 0, gi, pi,
386 force_direct_overloads);
388 else
389 for (unsigned int ti = 0; group.types[ti][0] != NUM_TYPE_SUFFIXES;
390 ++ti)
392 unsigned int bits = type_suffixes[group.types[ti][0]].element_bits;
393 gcc_assert (bits == 32 || bits == 64);
394 mode_suffix_index mode = bits == 32 ? mode32 : mode64;
395 if (mode != MODE_none)
396 build_one (b, signature, group, mode, ti, gi, pi,
397 force_direct_overloads);
401 /* For every type and predicate combination in GROUP, add one function
402 that takes a scalar (pointer) base and a signed vector array index,
403 and another that instead takes an unsigned vector array index.
404 The vector array index has the same element size as the first
405 function type suffix. SIGNATURE is as for build_all. */
406 static void
407 build_sv_index (function_builder &b, const char *signature,
408 const function_group_info &group)
410 build_32_64 (b, signature, group, MODE_s32index, MODE_s64index);
411 build_32_64 (b, signature, group, MODE_u32index, MODE_u64index);
414 /* Like build_sv_index, but only handle 64-bit types. */
415 static void
416 build_sv_index64 (function_builder &b, const char *signature,
417 const function_group_info &group)
419 build_32_64 (b, signature, group, MODE_none, MODE_s64index);
420 build_32_64 (b, signature, group, MODE_none, MODE_u64index);
423 /* Like build_sv_index, but taking vector byte offsets instead of vector
424 array indices. */
425 static void
426 build_sv_offset (function_builder &b, const char *signature,
427 const function_group_info &group)
429 build_32_64 (b, signature, group, MODE_s32offset, MODE_s64offset);
430 build_32_64 (b, signature, group, MODE_u32offset, MODE_u64offset);
433 /* Like build_sv_offset, but exclude offsets that must be interpreted
434 as signed (i.e. s32offset). */
435 static void
436 build_sv_uint_offset (function_builder &b, const char *signature,
437 const function_group_info &group)
439 build_32_64 (b, signature, group, MODE_none, MODE_s64offset);
440 build_32_64 (b, signature, group, MODE_u32offset, MODE_u64offset);
443 /* For every type and predicate combination in GROUP, add a function
444 that takes a vector base address and no displacement. The vector
445 base has the same element size as the first type suffix.
447 The other arguments are as for build_all. */
448 static void
449 build_v_base (function_builder &b, const char *signature,
450 const function_group_info &group,
451 bool force_direct_overloads = false)
453 build_32_64 (b, signature, group, MODE_u32base, MODE_u64base,
454 force_direct_overloads);
457 /* Like build_v_base, but for functions that also take a scalar array
458 index. */
459 static void
460 build_vs_index (function_builder &b, const char *signature,
461 const function_group_info &group,
462 bool force_direct_overloads = false)
464 build_32_64 (b, signature, group, MODE_u32base_index, MODE_u64base_index,
465 force_direct_overloads);
468 /* Like build_v_base, but for functions that also take a scalar byte
469 offset. */
470 static void
471 build_vs_offset (function_builder &b, const char *signature,
472 const function_group_info &group,
473 bool force_direct_overloads = false)
475 build_32_64 (b, signature, group, MODE_u32base_offset, MODE_u64base_offset,
476 force_direct_overloads);
479 /* Add a function instance for every type and predicate combination
480 in GROUP. Take the function base name from GROUP and the mode suffix
481 from MODE_SUFFIX_ID. Use SIGNATURE to construct the function signature
482 without a governing predicate, then use apply_predication to add in the
483 predicate. FORCE_DIRECT_OVERLOADS is true if there is a one-to-one
484 mapping between "short" and "full" names, and if standard overload
485 resolution therefore isn't necessary. */
486 static void
487 build_all (function_builder &b, const char *signature,
488 const function_group_info &group, mode_suffix_index mode_suffix_id,
489 bool force_direct_overloads = false)
491 for (unsigned int pi = 0; group.preds[pi] != NUM_PREDS; ++pi)
492 for (unsigned int gi = 0; group.groups[gi] != NUM_GROUP_SUFFIXES; ++gi)
493 for (unsigned int ti = 0;
494 ti == 0 || group.types[ti][0] != NUM_TYPE_SUFFIXES; ++ti)
495 build_one (b, signature, group, mode_suffix_id, ti, gi, pi,
496 force_direct_overloads);
499 /* TYPE is the largest type suffix associated with the arguments of R,
500 but the result is twice as wide. Return the associated type suffix
501 if it exists, otherwise report an appropriate error and return
502 NUM_TYPE_SUFFIXES. */
503 static type_suffix_index
504 long_type_suffix (function_resolver &r, type_suffix_index type)
506 unsigned int element_bits = type_suffixes[type].element_bits;
507 if (type_suffixes[type].integer_p && element_bits < 64)
508 return find_type_suffix (type_suffixes[type].tclass, element_bits * 2);
510 r.report_no_such_form (type);
511 return NUM_TYPE_SUFFIXES;
514 /* Declare the function shape NAME, pointing it to an instance
515 of class <NAME>_def. */
516 #define SHAPE(NAME) \
517 static CONSTEXPR const NAME##_def NAME##_obj; \
518 namespace shapes { const function_shape *const NAME = &NAME##_obj; }
520 /* Base class for functions that are not overloaded. */
521 struct nonoverloaded_base : public function_shape
523 bool
524 explicit_type_suffix_p (unsigned int) const override
526 return true;
529 tree
530 resolve (function_resolver &) const override
532 gcc_unreachable ();
536 /* Base class for overloaded functions. Bit N of EXPLICIT_MASK is true
537 if type suffix N appears in the overloaded name. */
538 template<unsigned int EXPLICIT_MASK>
539 struct overloaded_base : public function_shape
541 bool
542 explicit_type_suffix_p (unsigned int i) const override
544 return (EXPLICIT_MASK >> i) & 1;
548 /* Base class for adr_index and adr_offset. */
549 struct adr_base : public overloaded_base<0>
551 /* The function takes two arguments: a vector base and a vector displacement
552 (either an index or an offset). Resolve based on them both. */
553 tree
554 resolve (function_resolver &r) const override
556 unsigned int i, nargs;
557 mode_suffix_index mode;
558 if (!r.check_gp_argument (2, i, nargs)
559 || (mode = r.resolve_adr_address (0)) == MODE_none)
560 return error_mark_node;
562 return r.resolve_to (mode);
566 /* Base class for narrowing bottom binary functions that take an
567 immediate second operand. The result is half the size of input
568 and has class CLASS. */
569 template<type_class_index CLASS = function_resolver::SAME_TYPE_CLASS>
570 struct binary_imm_narrowb_base : public overloaded_base<0>
572 void
573 build (function_builder &b, const function_group_info &group) const override
575 b.add_overloaded_functions (group, MODE_n);
576 STATIC_ASSERT (CLASS == function_resolver::SAME_TYPE_CLASS
577 || CLASS == TYPE_unsigned);
578 if (CLASS == TYPE_unsigned)
579 build_all (b, "vhu0,v0,su64", group, MODE_n);
580 else
581 build_all (b, "vh0,v0,su64", group, MODE_n);
584 tree
585 resolve (function_resolver &r) const override
587 return r.resolve_uniform (1, 1);
591 /* The top equivalent of binary_imm_narrowb_base. It takes three arguments,
592 with the first being the values of the even elements, which are typically
593 the result of the narrowb operation. */
594 template<type_class_index CLASS = function_resolver::SAME_TYPE_CLASS>
595 struct binary_imm_narrowt_base : public overloaded_base<0>
597 void
598 build (function_builder &b, const function_group_info &group) const override
600 b.add_overloaded_functions (group, MODE_n);
601 STATIC_ASSERT (CLASS == function_resolver::SAME_TYPE_CLASS
602 || CLASS == TYPE_unsigned);
603 if (CLASS == TYPE_unsigned)
604 build_all (b, "vhu0,vhu0,v0,su64", group, MODE_n);
605 else
606 build_all (b, "vh0,vh0,v0,su64", group, MODE_n);
609 tree
610 resolve (function_resolver &r) const override
612 unsigned int i, nargs;
613 type_suffix_index type;
614 if (!r.check_gp_argument (3, i, nargs)
615 || (type = r.infer_vector_type (i + 1)) == NUM_TYPE_SUFFIXES
616 || !r.require_derived_vector_type (i, i + 1, type, CLASS, r.HALF_SIZE)
617 || !r.require_integer_immediate (i + 2))
618 return error_mark_node;
620 return r.resolve_to (r.mode_suffix_id, type);
624 /* Base class for long (i.e. narrow op narrow -> wide) binary functions
625 that take an immediate second operand. The type suffix specifies
626 the wider type. */
627 struct binary_imm_long_base : public overloaded_base<0>
629 void
630 build (function_builder &b, const function_group_info &group) const override
632 b.add_overloaded_functions (group, MODE_n);
633 build_all (b, "v0,vh0,su64", group, MODE_n);
636 tree
637 resolve (function_resolver &r) const override
639 unsigned int i, nargs;
640 type_suffix_index type, result_type;
641 if (!r.check_gp_argument (2, i, nargs)
642 || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
643 || !r.require_integer_immediate (i + 1)
644 || (result_type = long_type_suffix (r, type)) == NUM_TYPE_SUFFIXES)
645 return error_mark_node;
647 if (tree res = r.lookup_form (r.mode_suffix_id, result_type))
648 return res;
650 return r.report_no_such_form (type);
654 /* Base class for binary_za_m and similar shapes. */
655 template<type_class_index TCLASS = function_resolver::SAME_TYPE_CLASS,
656 unsigned int BITS = function_resolver::SAME_SIZE>
657 struct binary_za_m_base : public overloaded_base<1>
659 tree
660 resolve (function_resolver &r) const override
662 type_suffix_index type;
663 if (!r.check_num_arguments (5)
664 || !r.require_integer_immediate (0)
665 || !r.require_vector_type (1, VECTOR_TYPE_svbool_t)
666 || !r.require_vector_type (2, VECTOR_TYPE_svbool_t)
667 || (type = r.infer_vector_type (3)) == NUM_TYPE_SUFFIXES
668 || !r.require_derived_vector_type (4, 3, type, TCLASS, BITS))
669 return error_mark_node;
671 return r.resolve_to (r.mode_suffix_id, r.type_suffix_ids[0], type);
674 bool
675 check (function_checker &c) const override
677 return c.require_immediate_range (0, 0, c.num_za_tiles () - 1);
681 /* Base class for shapes like binary_za_slice_lane. TCLASS is the type
682 class of the final vector argument. */
683 template<type_class_index TCLASS = function_resolver::SAME_TYPE_CLASS>
684 struct binary_za_slice_lane_base : public overloaded_base<1>
686 constexpr binary_za_slice_lane_base (unsigned int lane_type_suffix)
687 : m_lane_type_suffix (lane_type_suffix) {}
689 void
690 build (function_builder &b, const function_group_info &group) const override
692 b.add_overloaded_functions (group, MODE_none);
693 build_all (b, "_,su32,t1,v1,su64", group, MODE_none);
696 tree
697 resolve (function_resolver &r) const override
699 sve_type type;
700 if (!r.check_num_arguments (4)
701 || !r.require_scalar_type (0, "uint32_t")
702 || !(type = r.infer_tuple_type (1))
703 || !r.require_derived_vector_type (2, 1, type, TCLASS)
704 || !r.require_integer_immediate (3))
705 return error_mark_node;
707 return r.resolve_to (r.mode_suffix_id, type);
710 bool
711 check (function_checker &c) const override
713 unsigned int bytes = c.type_suffix (m_lane_type_suffix).element_bytes;
714 return c.require_immediate_range (3, 0, 16 / bytes - 1);
717 unsigned int m_lane_type_suffix;
720 /* Base class for shapes like binary_za_slice_opt_single. TCLASS is the
721 type class of the final argument. */
722 template<type_class_index TCLASS = function_resolver::SAME_TYPE_CLASS>
723 struct binary_za_slice_opt_single_base : public overloaded_base<1>
725 tree
726 resolve (function_resolver &r) const override
728 sve_type type;
729 if (!r.check_num_arguments (3)
730 || !r.require_scalar_type (0, "uint32_t")
731 || !(type = r.infer_tuple_type (1)))
732 return error_mark_node;
734 return r.finish_opt_single_resolution (2, 1, type, TCLASS);
738 /* Base class for inc_dec and inc_dec_pat. */
739 struct inc_dec_base : public overloaded_base<0>
741 CONSTEXPR inc_dec_base (bool pat_p) : m_pat_p (pat_p) {}
743 /* Resolve based on the first argument only, which must be either a
744 scalar or a vector. If it's a scalar, it must be a 32-bit or
745 64-bit integer. */
746 tree
747 resolve (function_resolver &r) const
749 unsigned int i, nargs;
750 if (!r.check_gp_argument (m_pat_p ? 3 : 2, i, nargs)
751 || !r.require_vector_or_scalar_type (i))
752 return error_mark_node;
754 mode_suffix_index mode;
755 type_suffix_index type;
756 if (r.scalar_argument_p (i))
758 mode = MODE_n;
759 type = r.infer_integer_scalar_type (i);
761 else
763 mode = MODE_none;
764 type = r.infer_vector_type (i);
766 if (type == NUM_TYPE_SUFFIXES)
767 return error_mark_node;
769 for (++i; i < nargs; ++i)
770 if (!r.require_integer_immediate (i))
771 return error_mark_node;
773 return r.resolve_to (mode, type);
776 bool
777 check (function_checker &c) const override
779 return c.require_immediate_range (m_pat_p ? 2 : 1, 1, 16);
782 bool m_pat_p;
785 /* Base class for load and load_replicate. */
786 struct load_contiguous_base : public overloaded_base<0>
788 /* Resolve a call based purely on a pointer argument. The other arguments
789 are a governing predicate and (for MODE_vnum) a vnum offset. */
790 tree
791 resolve (function_resolver &r) const override
793 bool vnum_p = r.mode_suffix_id == MODE_vnum;
794 gcc_assert (r.mode_suffix_id == MODE_none || vnum_p);
796 unsigned int i, nargs;
797 type_suffix_index type;
798 if (!r.check_gp_argument (vnum_p ? 2 : 1, i, nargs)
799 || (type = r.infer_pointer_type (i)) == NUM_TYPE_SUFFIXES
800 || (vnum_p && !r.require_scalar_type (i + 1, "int64_t")))
801 return error_mark_node;
803 return r.resolve_to (r.mode_suffix_id, type, NUM_TYPE_SUFFIXES,
804 r.group_suffix_id);
808 /* Base class for gather loads that take a scalar base and a vector
809 displacement (either an offset or an index). */
810 struct load_gather_sv_base : public overloaded_base<0>
812 tree
813 resolve (function_resolver &r) const override
815 unsigned int i, nargs;
816 mode_suffix_index mode;
817 type_suffix_index type;
818 if (!r.check_gp_argument (2, i, nargs)
819 || (type = r.infer_pointer_type (i, true)) == NUM_TYPE_SUFFIXES
820 || (mode = r.resolve_sv_displacement (i + 1, type, true),
821 mode == MODE_none))
822 return error_mark_node;
824 return r.resolve_to (mode, type);
828 /* Base class for load_ext_gather_index and load_ext_gather_offset,
829 which differ only in the units of the displacement. */
830 struct load_ext_gather_base : public overloaded_base<1>
832 /* Resolve a gather load that takes one of:
834 - a scalar pointer base and a vector displacement
835 - a vector base with no displacement or
836 - a vector base and a scalar displacement
838 The function has an explicit type suffix that determines the type
839 of the loaded data. */
840 tree
841 resolve (function_resolver &r) const override
843 /* No resolution is needed for a vector base with no displacement;
844 there's a one-to-one mapping between short and long names. */
845 gcc_assert (r.displacement_units () != UNITS_none);
847 type_suffix_index type = r.type_suffix_ids[0];
849 unsigned int i, nargs;
850 mode_suffix_index mode;
851 if (!r.check_gp_argument (2, i, nargs)
852 || (mode = r.resolve_gather_address (i, type, true)) == MODE_none)
853 return error_mark_node;
855 return r.resolve_to (mode, type);
859 /* sv<t0>x<g>_t svfoo_t0_g(uint64_t, svuint8_t, uint64_t)
861 where the first argument is the ZT register number (currently always 0)
862 and the final argument is a constant index. The instruction divides
863 the vector argument in BITS-bit quantities. */
864 template<unsigned int BITS>
865 struct luti_lane_zt_base : public nonoverloaded_base
867 void
868 build (function_builder &b, const function_group_info &group) const override
870 build_all (b, "t0,su64,vu8,su64", group, MODE_none);
873 bool
874 check (function_checker &c) const override
876 auto nvectors = c.vectors_per_tuple ();
877 return (c.require_immediate_range (0, 0, 0)
878 && c.require_immediate_range (2, 0, 32 / BITS / nvectors - 1));
882 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:quarter>_t,
883 sv<t0:quarter>_t) (for integer t0)
884 sv<t0>_t svmmla[_t0](sv<t0>_t, sv<t0>_t, sv<t0>_t) (for floating-point t0)
886 The functions act like the equivalent of "ternary_qq" for integer elements
887 and normal vector-only ternary functions for floating-point elements. */
888 struct mmla_def : public overloaded_base<0>
890 void
891 build (function_builder &b, const function_group_info &group) const override
893 b.add_overloaded_functions (group, MODE_none);
894 /* svmmla is distributed over several extensions. Allow the common
895 denominator to define the overloaded svmmla function without
896 defining any specific versions. */
897 if (group.types[0][0] != NUM_TYPE_SUFFIXES)
899 if (type_suffixes[group.types[0][0]].float_p)
900 build_all (b, "v0,v0,v0,v0", group, MODE_none);
901 else
902 build_all (b, "v0,v0,vq0,vq0", group, MODE_none);
906 tree
907 resolve (function_resolver &r) const override
909 unsigned int i, nargs;
910 type_suffix_index type;
911 if (!r.check_gp_argument (3, i, nargs)
912 || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES)
913 return error_mark_node;
915 /* Make sure that the function exists now, since not all forms
916 follow a set pattern after this point. */
917 tree res = r.resolve_to (r.mode_suffix_id, type);
918 if (res == error_mark_node)
919 return res;
921 bool float_p = type_suffixes[type].float_p;
922 unsigned int modifier = float_p ? r.SAME_SIZE : r.QUARTER_SIZE;
923 if (!r.require_derived_vector_type (i + 1, i, type, r.SAME_TYPE_CLASS,
924 modifier)
925 || !r.require_derived_vector_type (i + 2, i, type, r.SAME_TYPE_CLASS,
926 modifier))
927 return error_mark_node;
929 return res;
932 SHAPE (mmla)
934 /* Base class for prefetch_gather_index and prefetch_gather_offset,
935 which differ only in the units of the displacement. */
936 struct prefetch_gather_base : public overloaded_base<0>
938 /* Resolve a gather prefetch that takes one of:
940 - a scalar pointer base (const void *) and a vector displacement
941 - a vector base with no displacement or
942 - a vector base and a scalar displacement
944 The prefetch operation is the final argument. This is purely a
945 mode-based resolution; there are no type suffixes. */
946 tree
947 resolve (function_resolver &r) const override
949 bool has_displacement_p = r.displacement_units () != UNITS_none;
951 unsigned int i, nargs;
952 mode_suffix_index mode;
953 if (!r.check_gp_argument (has_displacement_p ? 3 : 2, i, nargs)
954 || (mode = r.resolve_gather_address (i, NUM_TYPE_SUFFIXES,
955 false)) == MODE_none
956 || !r.require_integer_immediate (nargs - 1))
957 return error_mark_node;
959 return r.resolve_to (mode);
963 /* Wraps BASE to provide a narrowing shift right function. Argument N
964 is an immediate shift amount in the range [1, sizeof(<t0>_t) * 4]. */
965 template<typename BASE, unsigned int N>
966 struct shift_right_imm_narrow_wrapper : public BASE
968 bool
969 check (function_checker &c) const override
971 unsigned int bits = c.type_suffix (0).element_bits / 2;
972 return c.require_immediate_range (N, 1, bits);
976 /* Base class for store_scatter_index and store_scatter_offset,
977 which differ only in the units of the displacement. */
978 struct store_scatter_base : public overloaded_base<0>
980 /* Resolve a scatter store that takes one of:
982 - a scalar pointer base and a vector displacement
983 - a vector base with no displacement or
984 - a vector base and a scalar displacement
986 The stored data is the final argument, and it determines the
987 type suffix. */
988 tree
989 resolve (function_resolver &r) const override
991 bool has_displacement_p = r.displacement_units () != UNITS_none;
993 unsigned int i, nargs;
994 mode_suffix_index mode;
995 type_suffix_index type;
996 if (!r.check_gp_argument (has_displacement_p ? 3 : 2, i, nargs)
997 || (type = r.infer_sd_vector_type (nargs - 1)) == NUM_TYPE_SUFFIXES
998 || (mode = r.resolve_gather_address (i, type, false)) == MODE_none)
999 return error_mark_node;
1001 return r.resolve_to (mode, type);
1005 /* Base class for ternary operations in which the final argument is an
1006 immediate shift amount. The derived class should check the range. */
1007 struct ternary_shift_imm_base : public overloaded_base<0>
1009 void
1010 build (function_builder &b, const function_group_info &group) const override
1012 b.add_overloaded_functions (group, MODE_n);
1013 build_all (b, "v0,v0,v0,su64", group, MODE_n);
1016 tree
1017 resolve (function_resolver &r) const override
1019 return r.resolve_uniform (2, 1);
1023 /* Base class for ternary operations in which the first argument has the
1024 same element type as the result, and in which the second and third
1025 arguments have an element type that is derived the first.
1027 MODIFIER is the number of element bits in the second and third
1028 arguments, or a function_resolver modifier that says how this
1029 precision is derived from the first argument's elements.
1031 TYPE_CLASS2 and TYPE_CLASS3 are the type classes of the second and
1032 third arguments, or function_resolver::SAME_TYPE_CLASS if the type
1033 class is the same as the first argument. */
1034 template<unsigned int MODIFIER,
1035 type_class_index TYPE_CLASS2 = function_resolver::SAME_TYPE_CLASS,
1036 type_class_index TYPE_CLASS3 = function_resolver::SAME_TYPE_CLASS>
1037 struct ternary_resize2_opt_n_base : public overloaded_base<0>
1039 tree
1040 resolve (function_resolver &r) const override
1042 unsigned int i, nargs;
1043 type_suffix_index type;
1044 if (!r.check_gp_argument (3, i, nargs)
1045 || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
1046 || !r.require_derived_vector_type (i + 1, i, type, TYPE_CLASS2,
1047 MODIFIER))
1048 return error_mark_node;
1050 return r.finish_opt_n_resolution (i + 2, i, type, TYPE_CLASS3, MODIFIER);
1054 /* Like ternary_resize2_opt_n_base, but for functions that don't take
1055 a final scalar argument. */
1056 template<unsigned int MODIFIER,
1057 type_class_index TYPE_CLASS2 = function_resolver::SAME_TYPE_CLASS,
1058 type_class_index TYPE_CLASS3 = function_resolver::SAME_TYPE_CLASS>
1059 struct ternary_resize2_base : public overloaded_base<0>
1061 tree
1062 resolve (function_resolver &r) const override
1064 unsigned int i, nargs;
1065 type_suffix_index type;
1066 if (!r.check_gp_argument (3, i, nargs)
1067 || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
1068 || !r.require_derived_vector_type (i + 1, i, type, TYPE_CLASS2,
1069 MODIFIER)
1070 || !r.require_derived_vector_type (i + 2, i, type, TYPE_CLASS3,
1071 MODIFIER))
1072 return error_mark_node;
1074 return r.resolve_to (r.mode_suffix_id, type);
1078 /* Like ternary_resize2_opt_n_base, but for functions that take a final
1079 lane argument. */
1080 template<unsigned int MODIFIER,
1081 type_class_index TYPE_CLASS2 = function_resolver::SAME_TYPE_CLASS,
1082 type_class_index TYPE_CLASS3 = function_resolver::SAME_TYPE_CLASS>
1083 struct ternary_resize2_lane_base : public overloaded_base<0>
1085 tree
1086 resolve (function_resolver &r) const override
1088 unsigned int i, nargs;
1089 type_suffix_index type;
1090 if (!r.check_gp_argument (4, i, nargs)
1091 || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
1092 || !r.require_derived_vector_type (i + 1, i, type, TYPE_CLASS2,
1093 MODIFIER)
1094 || !r.require_derived_vector_type (i + 2, i, type, TYPE_CLASS3,
1095 MODIFIER)
1096 || !r.require_integer_immediate (i + 3))
1097 return error_mark_node;
1099 return r.resolve_to (r.mode_suffix_id, type);
1103 /* A specialization of ternary_resize2_lane_base for bfloat16 elements,
1104 indexed in groups of N elements. */
1105 template<unsigned int N>
1106 struct ternary_bfloat_lane_base
1107 : public ternary_resize2_lane_base<16, TYPE_bfloat, TYPE_bfloat>
1109 void
1110 build (function_builder &b, const function_group_info &group) const override
1112 b.add_overloaded_functions (group, MODE_none);
1113 build_all (b, "v0,v0,vB,vB,su64", group, MODE_none);
1116 bool
1117 check (function_checker &c) const override
1119 return c.require_immediate_lane_index (3, 2, N);
1123 /* A specialization of ternary_resize2_lane_base for quarter-sized
1124 elements. */
1125 template<type_class_index TYPE_CLASS2 = function_resolver::SAME_TYPE_CLASS,
1126 type_class_index TYPE_CLASS3 = function_resolver::SAME_TYPE_CLASS>
1127 struct ternary_qq_lane_base
1128 : public ternary_resize2_lane_base<function_resolver::QUARTER_SIZE,
1129 TYPE_CLASS2, TYPE_CLASS3>
1131 bool
1132 check (function_checker &c) const override
1134 return c.require_immediate_lane_index (3, 0);
1138 /* Base class for narrowing bottom unary functions. The result is half
1139 the size of input and has class CLASS. */
1140 template<type_class_index CLASS = function_resolver::SAME_TYPE_CLASS>
1141 struct unary_narrowb_base : public overloaded_base<0>
1143 void
1144 build (function_builder &b, const function_group_info &group) const override
1146 b.add_overloaded_functions (group, MODE_none);
1147 STATIC_ASSERT (CLASS == function_resolver::SAME_TYPE_CLASS
1148 || CLASS == TYPE_unsigned);
1149 if (CLASS == TYPE_unsigned)
1150 build_all (b, "vhu0,v0", group, MODE_none);
1151 else
1152 build_all (b, "vh0,v0", group, MODE_none);
1155 tree
1156 resolve (function_resolver &r) const override
1158 return r.resolve_unary (CLASS, r.HALF_SIZE);
1162 /* The top equivalent of unary_imm_narrowb_base. All forms take the values
1163 of the even elements as an extra argument, before any governing predicate.
1164 These even elements are typically the result of the narrowb operation. */
1165 template<type_class_index CLASS = function_resolver::SAME_TYPE_CLASS>
1166 struct unary_narrowt_base : public overloaded_base<0>
1168 void
1169 build (function_builder &b, const function_group_info &group) const override
1171 b.add_overloaded_functions (group, MODE_none);
1172 STATIC_ASSERT (CLASS == function_resolver::SAME_TYPE_CLASS
1173 || CLASS == TYPE_unsigned);
1174 if (CLASS == TYPE_unsigned)
1175 build_all (b, "vhu0,vhu0,v0", group, MODE_none);
1176 else
1177 build_all (b, "vh0,vh0,v0", group, MODE_none);
1180 tree
1181 resolve (function_resolver &r) const override
1183 unsigned int i, nargs;
1184 type_suffix_index type;
1185 if (!r.check_gp_argument (2, i, nargs)
1186 || (type = r.infer_vector_type (i + 1)) == NUM_TYPE_SUFFIXES
1187 || !r.require_derived_vector_type (i, i + 1, type, CLASS, r.HALF_SIZE))
1188 return error_mark_node;
1190 return r.resolve_to (r.mode_suffix_id, type);
1194 /* sv<m0>_t svfoo[_m0base]_[m1]index(sv<m0>_t, sv<m1>_t)
1196 for all valid combinations of vector base type <m0> and vector
1197 displacement type <m1>. */
1198 struct adr_index_def : public adr_base
1200 void
1201 build (function_builder &b, const function_group_info &group) const override
1203 b.add_overloaded_functions (group, MODE_index);
1204 build_all (b, "b,b,d", group, MODE_u32base_s32index);
1205 build_all (b, "b,b,d", group, MODE_u32base_u32index);
1206 build_all (b, "b,b,d", group, MODE_u64base_s64index);
1207 build_all (b, "b,b,d", group, MODE_u64base_u64index);
1210 SHAPE (adr_index)
1212 /* sv<m0>_t svfoo[_m0base]_[m1]offset(sv<m0>_t, sv<m1>_t).
1214 for all valid combinations of vector base type <m0> and vector
1215 displacement type <m1>. */
1216 struct adr_offset_def : public adr_base
1218 void
1219 build (function_builder &b, const function_group_info &group) const override
1221 b.add_overloaded_functions (group, MODE_offset);
1222 build_all (b, "b,b,d", group, MODE_u32base_s32offset);
1223 build_all (b, "b,b,d", group, MODE_u32base_u32offset);
1224 build_all (b, "b,b,d", group, MODE_u64base_s64offset);
1225 build_all (b, "b,b,d", group, MODE_u64base_u64offset);
1228 SHAPE (adr_offset)
1230 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0>_t)
1232 i.e. a binary operation with uniform types, but with no scalar form. */
1233 struct binary_def : public overloaded_base<0>
1235 void
1236 build (function_builder &b, const function_group_info &group) const override
1238 b.add_overloaded_functions (group, MODE_none);
1239 build_all (b, "v0,v0,v0", group, MODE_none);
1242 tree
1243 resolve (function_resolver &r) const override
1245 return r.resolve_uniform (2);
1248 SHAPE (binary)
1250 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:int>_t)
1251 sv<t0>_t svfoo[_n_t0](sv<t0>_t, <t0:int>_t).
1253 i.e. a version of the standard binary shape binary_opt_n in which
1254 the final argument is always a signed integer. */
1255 struct binary_int_opt_n_def : public overloaded_base<0>
1257 void
1258 build (function_builder &b, const function_group_info &group) const override
1260 b.add_overloaded_functions (group, MODE_none);
1261 build_all (b, "v0,v0,vs0", group, MODE_none);
1262 build_all (b, "v0,v0,ss0", group, MODE_n);
1265 tree
1266 resolve (function_resolver &r) const override
1268 unsigned int i, nargs;
1269 type_suffix_index type;
1270 if (!r.check_gp_argument (2, i, nargs)
1271 || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES)
1272 return error_mark_node;
1274 return r.finish_opt_n_resolution (i + 1, i, type, TYPE_signed);
1277 SHAPE (binary_int_opt_n)
1279 /* Like binary_int_opt_n for single vectors. For tuples:
1281 sv<t0>x<g>_t svfoo[_t0_g](sv<t0>x<g>_t, sv<t0:int>x<g>_t)
1282 sv<t0>x<g>_t svfoo[_single_t0_g](sv<t0>x<g>_t, sv<t0:int>_t). */
1283 struct binary_int_opt_single_n_def : public overloaded_base<0>
1285 bool explicit_group_suffix_p () const override { return false; }
1287 void
1288 build (function_builder &b, const function_group_info &group) const override
1290 b.add_overloaded_functions (group, MODE_none);
1291 build_all (b, "t0,t0,ts0", group, MODE_none);
1292 if (group.groups[0] == GROUP_none)
1293 build_all (b, "v0,v0,ss0", group, MODE_n);
1294 else
1295 build_all (b, "t0,t0,vs0", group, MODE_single);
1298 tree
1299 resolve (function_resolver &r) const override
1301 unsigned int i, nargs;
1302 sve_type type;
1303 if (!r.check_gp_argument (2, i, nargs)
1304 || !(type = r.infer_sve_type (i)))
1305 return error_mark_node;
1307 return (type.num_vectors == 1 && r.scalar_argument_p (i + 1)
1308 ? r.finish_opt_n_resolution (i + 1, i, type.type, TYPE_signed)
1309 : r.finish_opt_single_resolution (i + 1, i, type, TYPE_signed));
1312 SHAPE (binary_int_opt_single_n)
1314 /* sv<t0>_t svfoo_<t0>(sv<t0>_t, sv<t0>_t, uint64_t)
1316 where the final argument is an integer constant expression in the
1317 range [0, 16 / sizeof (<t0>_t) - 1]. */
1318 struct binary_lane_def : public overloaded_base<0>
1320 void
1321 build (function_builder &b, const function_group_info &group) const override
1323 b.add_overloaded_functions (group, MODE_none);
1324 build_all (b, "v0,v0,v0,su64", group, MODE_none);
1327 tree
1328 resolve (function_resolver &r) const override
1330 return r.resolve_uniform (2, 1);
1333 bool
1334 check (function_checker &c) const override
1336 return c.require_immediate_lane_index (2, 1);
1339 SHAPE (binary_lane)
1341 /* sv<t0>_t svfoo[_t0](sv<t0:half>_t, sv<t0:half>_t, uint64_t).
1343 where the final argument is an integer constant expression in the
1344 range [0, 32 / sizeof (<t0>_t) - 1]. */
1345 struct binary_long_lane_def : public overloaded_base<0>
1347 void
1348 build (function_builder &b, const function_group_info &group) const override
1350 b.add_overloaded_functions (group, MODE_none);
1351 build_all (b, "v0,vh0,vh0,su64", group, MODE_none);
1354 tree
1355 resolve (function_resolver &r) const override
1357 unsigned int i, nargs;
1358 type_suffix_index type, result_type;
1359 if (!r.check_gp_argument (3, i, nargs)
1360 || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
1361 || !r.require_matching_vector_type (i + 1, i, type)
1362 || !r.require_integer_immediate (i + 2)
1363 || (result_type = long_type_suffix (r, type)) == NUM_TYPE_SUFFIXES)
1364 return error_mark_node;
1366 if (tree res = r.lookup_form (r.mode_suffix_id, result_type))
1367 return res;
1369 return r.report_no_such_form (type);
1372 bool
1373 check (function_checker &c) const override
1375 return c.require_immediate_lane_index (2, 1);
1378 SHAPE (binary_long_lane)
1380 /* sv<t0>_t svfoo[_t0](sv<t0:half>_t, sv<t0:half>_t)
1381 sv<t0>_t svfoo[_n_t0](sv<t0:half>_t, <t0:half>_t). */
1382 struct binary_long_opt_n_def : public overloaded_base<0>
1384 void
1385 build (function_builder &b, const function_group_info &group) const override
1387 b.add_overloaded_functions (group, MODE_none);
1388 build_all (b, "v0,vh0,vh0", group, MODE_none);
1389 build_all (b, "v0,vh0,sh0", group, MODE_n);
1392 tree
1393 resolve (function_resolver &r) const override
1395 unsigned int i, nargs;
1396 type_suffix_index type, result_type;
1397 if (!r.check_gp_argument (2, i, nargs)
1398 || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
1399 || (result_type = long_type_suffix (r, type)) == NUM_TYPE_SUFFIXES)
1400 return error_mark_node;
1402 return r.finish_opt_n_resolution (i + 1, i, type, r.SAME_TYPE_CLASS,
1403 r.SAME_SIZE, result_type);
1406 SHAPE (binary_long_opt_n)
1408 /* sv<t0>_t svfoo[_n_t0](sv<t0>_t, <t0>_t).
1410 i.e. a binary operation in which the final argument is always a scalar
1411 rather than a vector. */
1412 struct binary_n_def : public overloaded_base<0>
1414 void
1415 build (function_builder &b, const function_group_info &group) const override
1417 b.add_overloaded_functions (group, MODE_n);
1418 build_all (b, "v0,v0,s0", group, MODE_n);
1421 tree
1422 resolve (function_resolver &r) const override
1424 unsigned int i, nargs;
1425 type_suffix_index type;
1426 if (!r.check_gp_argument (2, i, nargs)
1427 || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
1428 || !r.require_derived_scalar_type (i + 1, r.SAME_TYPE_CLASS))
1429 return error_mark_node;
1431 return r.resolve_to (r.mode_suffix_id, type);
1434 SHAPE (binary_n)
1436 /* sv<t0:half>_t svfoo[_t0](sv<t0>_t, sv<t0>_t)
1437 sv<t0:half>_t svfoo[_n_t0](sv<t0>_t, <t0>_t)
1439 i.e. a version of binary_opt_n in which the output elements are half the
1440 width of the input elements. */
1441 struct binary_narrowb_opt_n_def : public overloaded_base<0>
1443 void
1444 build (function_builder &b, const function_group_info &group) const override
1446 b.add_overloaded_functions (group, MODE_none);
1447 build_all (b, "vh0,v0,v0", group, MODE_none);
1448 build_all (b, "vh0,v0,s0", group, MODE_n);
1451 tree
1452 resolve (function_resolver &r) const override
1454 return r.resolve_uniform_opt_n (2);
1457 SHAPE (binary_narrowb_opt_n)
1459 /* sv<t0:half>_t svfoo[_t0](sv<t0:half>_t, sv<t0>_t, sv<t0>_t)
1460 sv<t0:half>_t svfoo[_n_t0](sv<t0:half>_t, sv<t0>_t, <t0>_t)
1462 This is the "top" counterpart to binary_narrowb_opt_n. */
1463 struct binary_narrowt_opt_n_def : public overloaded_base<0>
1465 void
1466 build (function_builder &b, const function_group_info &group) const override
1468 b.add_overloaded_functions (group, MODE_none);
1469 build_all (b, "vh0,vh0,v0,v0", group, MODE_none);
1470 build_all (b, "vh0,vh0,v0,s0", group, MODE_n);
1473 tree
1474 resolve (function_resolver &r) const override
1476 unsigned int i, nargs;
1477 type_suffix_index type;
1478 if (!r.check_gp_argument (3, i, nargs)
1479 || (type = r.infer_vector_type (i + 1)) == NUM_TYPE_SUFFIXES
1480 || !r.require_derived_vector_type (i, i + 1, type, r.SAME_TYPE_CLASS,
1481 r.HALF_SIZE))
1482 return error_mark_node;
1484 return r.finish_opt_n_resolution (i + 2, i + 1, type);
1487 SHAPE (binary_narrowt_opt_n)
1489 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0>_t)
1490 sv<t0>_t svfoo[_n_t0](sv<t0>_t, <t0>_t)
1492 i.e. the standard shape for binary operations that operate on
1493 uniform types. */
1494 struct binary_opt_n_def : public overloaded_base<0>
1496 void
1497 build (function_builder &b, const function_group_info &group) const override
1499 b.add_overloaded_functions (group, MODE_none);
1500 build_all (b, "v0,v0,v0", group, MODE_none);
1501 /* _b functions do not have an _n form, but are classified as
1502 binary_opt_n so that they can be overloaded with vector
1503 functions. */
1504 if (group.types[0][0] == TYPE_SUFFIX_b)
1505 gcc_assert (group.types[0][1] == NUM_TYPE_SUFFIXES);
1506 else
1507 build_all (b, "v0,v0,s0", group, MODE_n);
1510 tree
1511 resolve (function_resolver &r) const override
1513 return r.resolve_uniform_opt_n (2);
1516 SHAPE (binary_opt_n)
1518 /* Like binary_opt_n for single vectors. For tuples:
1520 sv<t0>x<g>_t svfoo[_t0_g](sv<t0>x<g>_t, sv<t0>x<g>_t)
1521 sv<t0>x<g>_t svfoo[_single_t0_g](sv<t0>x<g>_t, sv<t0>_t). */
1522 struct binary_opt_single_n_def : public overloaded_base<0>
1524 bool explicit_group_suffix_p () const override { return false; }
1526 void
1527 build (function_builder &b, const function_group_info &group) const override
1529 b.add_overloaded_functions (group, MODE_none);
1530 build_all (b, "t0,t0,t0", group, MODE_none);
1531 if (group.groups[0] == GROUP_none)
1532 build_all (b, "v0,v0,s0", group, MODE_n);
1533 else
1534 build_all (b, "t0,t0,v0", group, MODE_single);
1537 tree
1538 resolve (function_resolver &r) const override
1540 unsigned int i, nargs;
1541 sve_type type;
1542 if (!r.check_gp_argument (2, i, nargs)
1543 || !(type = r.infer_sve_type (i)))
1544 return error_mark_node;
1546 return (type.num_vectors == 1 && r.scalar_argument_p (i + 1)
1547 ? r.finish_opt_n_resolution (i + 1, i, type.type)
1548 : r.finish_opt_single_resolution (i + 1, i, type));
1551 SHAPE (binary_opt_single_n)
1553 /* svbool_t svfoo(svbool_t, svbool_t). */
1554 struct binary_pred_def : public nonoverloaded_base
1556 void
1557 build (function_builder &b, const function_group_info &group) const override
1559 build_all (b, "v0,v0,v0", group, MODE_none);
1562 SHAPE (binary_pred)
1564 /* sv<t0>_t svfoo[_<t0>](sv<t0>_t, sv<t0>_t, uint64_t)
1566 where the final argument must be 90 or 270. */
1567 struct binary_rotate_def : public overloaded_base<0>
1569 void
1570 build (function_builder &b, const function_group_info &group) const override
1572 b.add_overloaded_functions (group, MODE_none);
1573 build_all (b, "v0,v0,v0,su64", group, MODE_none);
1576 tree
1577 resolve (function_resolver &r) const override
1579 return r.resolve_uniform (2, 1);
1582 bool
1583 check (function_checker &c) const override
1585 return c.require_immediate_either_or (2, 90, 270);
1588 SHAPE (binary_rotate)
1590 /* sv<t0>_t svfoo_t0(<t0>_t, <t0>_t)
1592 i.e. a binary function that takes two scalars and returns a vector.
1593 An explicit type suffix is required. */
1594 struct binary_scalar_def : public nonoverloaded_base
1596 void
1597 build (function_builder &b, const function_group_info &group) const override
1599 build_all (b, "v0,s0,s0", group, MODE_none);
1602 SHAPE (binary_scalar)
1604 /* sv<t0>x<g>_t svfoo[_single_t0_g](sv<t0>x<g>_t, sv<t0>_t). */
1605 struct binary_single_def : public overloaded_base<0>
1607 bool explicit_group_suffix_p () const override { return false; }
1609 void
1610 build (function_builder &b, const function_group_info &group) const override
1612 b.add_overloaded_functions (group, MODE_none);
1613 build_all (b, "t0,t0,v0", group, MODE_single);
1616 tree
1617 resolve (function_resolver &r) const override
1619 sve_type type;
1620 if (!r.check_num_arguments (2)
1621 || !(type = r.infer_sve_type (0))
1622 || !r.require_derived_vector_type (1, 0, type, r.SAME_TYPE_CLASS,
1623 r.SAME_SIZE, 1))
1624 return error_mark_node;
1626 return r.resolve_to (MODE_single, type);
1629 SHAPE (binary_single)
1631 /* sv<t0:uint>_t svfoo[_t0](sv<t0>_t, sv<t0>_t).
1633 i.e. a version of "binary" that returns unsigned integers. */
1634 struct binary_to_uint_def : public overloaded_base<0>
1636 void
1637 build (function_builder &b, const function_group_info &group) const override
1639 b.add_overloaded_functions (group, MODE_none);
1640 build_all (b, "vu0,v0,v0", group, MODE_none);
1643 tree
1644 resolve (function_resolver &r) const override
1646 return r.resolve_uniform (2);
1649 SHAPE (binary_to_uint)
1651 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:uint>_t)
1653 i.e. a version of "binary" in which the final argument is always an
1654 unsigned integer. */
1655 struct binary_uint_def : public overloaded_base<0>
1657 void
1658 build (function_builder &b, const function_group_info &group) const override
1660 b.add_overloaded_functions (group, MODE_none);
1661 build_all (b, "v0,v0,vu0", group, MODE_none);
1664 tree
1665 resolve (function_resolver &r) const override
1667 unsigned int i, nargs;
1668 type_suffix_index type;
1669 if (!r.check_gp_argument (2, i, nargs)
1670 || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
1671 || !r.require_derived_vector_type (i + 1, i, type, TYPE_unsigned))
1672 return error_mark_node;
1674 return r.resolve_to (r.mode_suffix_id, type);
1677 SHAPE (binary_uint)
1679 /* sv<t0>_t svfoo[_t0](sv<t0>_t, <t0:uint>_t)
1681 i.e. a version of binary_n in which the final argument is always an
1682 unsigned integer. */
1683 struct binary_uint_n_def : public overloaded_base<0>
1685 void
1686 build (function_builder &b, const function_group_info &group) const override
1688 b.add_overloaded_functions (group, MODE_none);
1689 build_all (b, "v0,v0,su0", group, MODE_none);
1692 tree
1693 resolve (function_resolver &r) const override
1695 unsigned int i, nargs;
1696 type_suffix_index type;
1697 if (!r.check_gp_argument (2, i, nargs)
1698 || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
1699 || !r.require_derived_scalar_type (i + 1, TYPE_unsigned))
1700 return error_mark_node;
1702 return r.resolve_to (r.mode_suffix_id, type);
1705 SHAPE (binary_uint_n)
1707 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:uint>_t)
1708 sv<t0>_t svfoo[_n_t0](sv<t0>_t, <t0:uint>_t)
1710 i.e. a version of the standard binary shape binary_opt_n in which
1711 the final argument is always an unsigned integer. */
1712 struct binary_uint_opt_n_def : public overloaded_base<0>
1714 void
1715 build (function_builder &b, const function_group_info &group) const override
1717 b.add_overloaded_functions (group, MODE_none);
1718 build_all (b, "v0,v0,vu0", group, MODE_none);
1719 build_all (b, "v0,v0,su0", group, MODE_n);
1722 tree
1723 resolve (function_resolver &r) const override
1725 unsigned int i, nargs;
1726 type_suffix_index type;
1727 if (!r.check_gp_argument (2, i, nargs)
1728 || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES)
1729 return error_mark_node;
1731 return r.finish_opt_n_resolution (i + 1, i, type, TYPE_unsigned);
1734 SHAPE (binary_uint_opt_n)
1736 /* sv<t0>_t svfoo[_t0](sv<t0>_t, uint64_t).
1738 i.e. a version of binary_n in which the final argument is always
1739 a 64-bit unsigned integer. */
1740 struct binary_uint64_n_def : public overloaded_base<0>
1742 void
1743 build (function_builder &b, const function_group_info &group) const override
1745 b.add_overloaded_functions (group, MODE_none);
1746 build_all (b, "v0,v0,su64", group, MODE_none);
1749 tree
1750 resolve (function_resolver &r) const override
1752 unsigned int i, nargs;
1753 type_suffix_index type;
1754 if (!r.check_gp_argument (2, i, nargs)
1755 || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
1756 || !r.require_scalar_type (i + 1, "uint64_t"))
1757 return error_mark_node;
1759 return r.resolve_to (r.mode_suffix_id, type);
1762 SHAPE (binary_uint64_n)
1764 /* sv<t0>_t svfoo[_t0](sv<t0>_t, svuint64_t)
1765 sv<t0>_t svfoo[_n_t0](sv<t0>_t, uint64_t)
1767 i.e. a version of the standard binary shape binary_opt_n in which
1768 the final argument is always a uint64_t. */
1769 struct binary_uint64_opt_n_def : public overloaded_base<0>
1771 void
1772 build (function_builder &b, const function_group_info &group) const override
1774 b.add_overloaded_functions (group, MODE_none);
1775 build_all (b, "v0,v0,vu64", group, MODE_none);
1776 build_all (b, "v0,v0,su64", group, MODE_n);
1779 tree
1780 resolve (function_resolver &r) const override
1782 unsigned int i, nargs;
1783 type_suffix_index type;
1784 if (!r.check_gp_argument (2, i, nargs)
1785 || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES)
1786 return error_mark_node;
1788 return r.finish_opt_n_resolution (i + 1, i, type, TYPE_unsigned, 64);
1791 SHAPE (binary_uint64_opt_n)
1793 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:half>_t). */
1794 struct binary_wide_def : public overloaded_base<0>
1796 void
1797 build (function_builder &b, const function_group_info &group) const override
1799 b.add_overloaded_functions (group, MODE_none);
1800 build_all (b, "v0,v0,vh0", group, MODE_none);
1803 tree
1804 resolve (function_resolver &r) const override
1806 unsigned int i, nargs;
1807 type_suffix_index type;
1808 if (!r.check_gp_argument (2, i, nargs)
1809 || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
1810 || !r.require_derived_vector_type (i + 1, i, type, r.SAME_TYPE_CLASS,
1811 r.HALF_SIZE))
1812 return error_mark_node;
1814 return r.resolve_to (r.mode_suffix_id, type);
1817 SHAPE (binary_wide)
1819 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:half>_t)
1820 sv<t0>_t svfoo[_n_t0](sv<t0>_t, <t0:half>_t). */
1821 struct binary_wide_opt_n_def : public overloaded_base<0>
1823 void
1824 build (function_builder &b, const function_group_info &group) const override
1826 b.add_overloaded_functions (group, MODE_none);
1827 build_all (b, "v0,v0,vh0", group, MODE_none);
1828 build_all (b, "v0,v0,sh0", group, MODE_n);
1831 tree
1832 resolve (function_resolver &r) const override
1834 unsigned int i, nargs;
1835 type_suffix_index type;
1836 if (!r.check_gp_argument (2, i, nargs)
1837 || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES)
1838 return error_mark_node;
1840 return r.finish_opt_n_resolution (i + 1, i, type, r.SAME_TYPE_CLASS,
1841 r.HALF_SIZE);
1844 SHAPE (binary_wide_opt_n)
1846 /* void svfoo_t0[_t1]_g(uint64_t, svbool_t, svbool_t, sv<t1>x<g>_t,
1847 sv<t1:int>x<g>_t)
1849 where the first argument is a ZA tile. */
1850 struct binary_za_int_m_def : public binary_za_m_base<TYPE_signed>
1852 void
1853 build (function_builder &b, const function_group_info &group) const override
1855 b.add_overloaded_functions (group, MODE_none);
1856 build_all (b, "_,su64,vp,vp,t1,ts1", group, MODE_none);
1859 SHAPE (binary_za_int_m)
1861 /* void svfoo_t0[_t1]_g(uint64_t, svbool_t, svbool_t, sv<t1>x<g>_t,
1862 sv<t1>x<g>_t)
1864 where the first argument is a ZA tile. */
1865 struct binary_za_m_def : public binary_za_m_base<>
1867 void
1868 build (function_builder &b, const function_group_info &group) const override
1870 b.add_overloaded_functions (group, MODE_none);
1871 /* Allow the overloaded form to be specified seperately, with just
1872 a single suffix. This is necessary for the 64-bit SME MOP intrinsics,
1873 which have some forms dependent on FEAT_SME_I16I64 and some forms
1874 dependent on FEAT_SME_F64F64. The resolver needs to be defined
1875 for base SME. */
1876 if (group.types[0][1] != NUM_TYPE_SUFFIXES)
1877 build_all (b, "_,su64,vp,vp,t1,t1", group, MODE_none);
1880 SHAPE (binary_za_m)
1882 /* void svfoo_lane_t0[_t1]_g(uint32_t, sv<t1>x<g>_t, sv<t1>_t, uint64_t)
1884 where the first argument is a variable ZA slice and the final argument
1885 indexes a single element in the preceding vector argument. */
1886 struct binary_za_slice_lane_def : public binary_za_slice_lane_base<>
1888 constexpr binary_za_slice_lane_def () : binary_za_slice_lane_base<> (1) {}
1890 SHAPE (binary_za_slice_lane)
1892 /* void svfoo_t0[_t1]_g(uint32_t, sv<t1>x<g>_t, sv<t1:int>x<g>_t)
1893 void svfoo[_single]_t0[_t1]_g(uint32_t, sv<t1>x<g>_t, sv<t1:int>_t).
1895 where the first argument is a variable ZA slice. */
1896 struct binary_za_slice_int_opt_single_def
1897 : public binary_za_slice_opt_single_base<TYPE_signed>
1899 void
1900 build (function_builder &b, const function_group_info &group) const override
1902 b.add_overloaded_functions (group, MODE_none);
1903 build_all (b, "_,su32,t1,ts1", group, MODE_none);
1904 build_all (b, "_,su32,t1,vs1", group, MODE_single);
1907 SHAPE (binary_za_slice_int_opt_single)
1909 /* void svfoo_t0[_t1]_g(uint32_t, sv<t1>x<g>_t, sv<t1>x<g>_t)
1910 void svfoo[_single]_t0[_t1]_g(uint32_t, sv<t1>x<g>_t, sv<t1>_t)
1912 where the first argument is a variable ZA slice. */
1913 struct binary_za_slice_opt_single_def
1914 : public binary_za_slice_opt_single_base<>
1916 void
1917 build (function_builder &b, const function_group_info &group) const override
1919 b.add_overloaded_functions (group, MODE_none);
1920 build_all (b, "_,su32,t1,t1", group, MODE_none);
1921 build_all (b, "_,su32,t1,v1", group, MODE_single);
1924 SHAPE (binary_za_slice_opt_single)
1926 /* void svfoo_t0[_t1]_g(uint32_t, sv<t1>x<g>_t, sv<t1:uint>x<g>_t)
1927 void svfoo[_single]_t0[_t1]_g(uint32_t, sv<t1>x<g>_t, sv<t1:uint>_t)
1929 where the first argument is a variable ZA slice. */
1930 struct binary_za_slice_uint_opt_single_def
1931 : public binary_za_slice_opt_single_base<TYPE_unsigned>
1933 void
1934 build (function_builder &b, const function_group_info &group) const override
1936 b.add_overloaded_functions (group, MODE_none);
1937 build_all (b, "_,su32,t1,tu1", group, MODE_none);
1938 build_all (b, "_,su32,t1,vu1", group, MODE_single);
1941 SHAPE (binary_za_slice_uint_opt_single)
1943 /* void svfoo_t0[_t1]_g(uint64_t, svbool_t, svbool_t, sv<t1>x<g>_t,
1944 sv<t1:uint>x<g>_t)
1946 where the first argument is a ZA tile. */
1947 struct binary_za_uint_m_def : public binary_za_m_base<TYPE_unsigned>
1949 void
1950 build (function_builder &b, const function_group_info &group) const override
1952 b.add_overloaded_functions (group, MODE_none);
1953 build_all (b, "_,su64,vp,vp,t1,tu1", group, MODE_none);
1956 SHAPE (binary_za_uint_m)
1958 /* sv<t0>x<g>_t svfoo[_t0_t1_g](sv<t0>x<g>_t, sv<t0>x<g>_t). */
1959 struct binaryxn_def : public overloaded_base<0>
1961 bool explicit_group_suffix_p () const override { return false; }
1963 void
1964 build (function_builder &b, const function_group_info &group) const override
1966 b.add_overloaded_functions (group, MODE_none);
1967 build_all (b, "t0,t0,t0", group, MODE_none);
1970 tree
1971 resolve (function_resolver &r) const override
1973 vector_type_index pred_type;
1974 sve_type type;
1975 if (!r.check_num_arguments (3)
1976 || (pred_type = r.infer_predicate_type (0)) == NUM_VECTOR_TYPES
1977 || !(type = r.infer_sve_type (1))
1978 || !r.require_matching_predicate_type (pred_type, type)
1979 || !r.require_matching_vector_type (2, 1, type))
1980 return error_mark_node;
1982 return r.resolve_to (r.mode_suffix_id, type);
1985 SHAPE (binaryxn)
1987 /* bool svfoo(). */
1988 struct bool_inherent_def : public nonoverloaded_base
1990 void
1991 build (function_builder &b, const function_group_info &group) const override
1993 build_all (b, "sp", group, MODE_none);
1996 SHAPE (bool_inherent)
1998 /* Either:
2000 sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0>_t, sv<t0>_t)
2002 for single vectors or:
2004 sv<t0>x<g>_t svfoo[_single_t0_g](sv<t0>x<g>_t, sv<t0>_t, sv<t0>_t)
2006 for tuples. */
2007 struct clamp_def : public overloaded_base<0>
2009 bool explicit_group_suffix_p () const override { return false; }
2011 void
2012 build (function_builder &b, const function_group_info &group) const override
2014 b.add_overloaded_functions (group, MODE_none);
2015 build_all (b, "t0,t0,v0,v0", group,
2016 group.groups[0] == GROUP_none ? MODE_none : MODE_single);
2019 tree
2020 resolve (function_resolver &r) const override
2022 sve_type type;
2023 if (!r.check_num_arguments (3)
2024 || !(type = r.infer_sve_type (0))
2025 || !r.require_derived_vector_type (1, 0, type, r.SAME_TYPE_CLASS,
2026 r.SAME_SIZE, 1)
2027 || !r.require_derived_vector_type (2, 0, type, r.SAME_TYPE_CLASS,
2028 r.SAME_SIZE, 1))
2029 return error_mark_node;
2031 auto mode = type.num_vectors == 1 ? MODE_none : MODE_single;
2032 return r.resolve_to (mode, type);
2035 SHAPE (clamp)
2037 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0>_t)
2038 <t0>_t svfoo[_n_t0](<t0>_t, sv<t0>_t). */
2039 struct clast_def : public overloaded_base<0>
2041 void
2042 build (function_builder &b, const function_group_info &group) const override
2044 b.add_overloaded_functions (group, MODE_none);
2045 build_all (b, "v0,v0,v0", group, MODE_none);
2046 build_all (b, "s0,s0,v0", group, MODE_n);
2049 tree
2050 resolve (function_resolver &r) const override
2052 unsigned int i, nargs;
2053 if (!r.check_gp_argument (2, i, nargs)
2054 || !r.require_vector_or_scalar_type (i))
2055 return error_mark_node;
2057 if (r.scalar_argument_p (i))
2059 type_suffix_index type;
2060 if (!r.require_derived_scalar_type (i, r.SAME_TYPE_CLASS)
2061 || (type = r.infer_vector_type (i + 1)) == NUM_TYPE_SUFFIXES)
2062 return error_mark_node;
2063 return r.resolve_to (MODE_n, type);
2065 else
2067 type_suffix_index type;
2068 if ((type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
2069 || !r.require_matching_vector_type (i + 1, i, type))
2070 return error_mark_node;
2071 return r.resolve_to (MODE_none, type);
2075 SHAPE (clast)
2077 /* svbool_t svfoo[_t0](sv<t0>_t, sv<t0>_t). */
2078 struct compare_def : public overloaded_base<0>
2080 void
2081 build (function_builder &b, const function_group_info &group) const override
2083 b.add_overloaded_functions (group, MODE_none);
2084 build_all (b, "vp,v0,v0", group, MODE_none);
2087 tree
2088 resolve (function_resolver &r) const override
2090 return r.resolve_uniform (2);
2093 SHAPE (compare)
2095 /* svbool_t svfoo[_t0](sv<t0>_t, sv<t0>_t)
2096 svbool_t svfoo[_n_t0](sv<t0>_t, <t0>_t)
2098 i.e. a comparison between two vectors, or between a vector and a scalar. */
2099 struct compare_opt_n_def : public overloaded_base<0>
2101 void
2102 build (function_builder &b, const function_group_info &group) const override
2104 b.add_overloaded_functions (group, MODE_none);
2105 build_all (b, "vp,v0,v0", group, MODE_none);
2106 build_all (b, "vp,v0,s0", group, MODE_n);
2109 tree
2110 resolve (function_resolver &r) const override
2112 return r.resolve_uniform_opt_n (2);
2115 SHAPE (compare_opt_n)
2117 /* svbool_t svfoo[_t0](const <t0>_t *, const <t0>_t *). */
2118 struct compare_ptr_def : public overloaded_base<0>
2120 void
2121 build (function_builder &b, const function_group_info &group) const override
2123 b.add_overloaded_functions (group, MODE_none);
2124 build_all (b, "vp,al,al", group, MODE_none);
2127 tree
2128 resolve (function_resolver &r) const override
2130 unsigned int i, nargs;
2131 type_suffix_index type;
2132 if (!r.check_gp_argument (2, i, nargs)
2133 || (type = r.infer_pointer_type (i)) == NUM_TYPE_SUFFIXES
2134 || !r.require_matching_pointer_type (i + 1, i, type))
2135 return error_mark_node;
2137 return r.resolve_to (r.mode_suffix_id, type);
2140 SHAPE (compare_ptr)
2142 /* svboolx<g>_t svfoo_t0[_t1]_g(<t1>_t, <t1>_t)
2144 where _t0 is a _b<bits> suffix that describes the predicate result.
2145 There is no direct relationship between the element sizes of _t0
2146 and _t1. */
2147 struct compare_scalar_def : public overloaded_base<1>
2149 void
2150 build (function_builder &b, const function_group_info &group) const override
2152 b.add_overloaded_functions (group, MODE_none);
2153 build_all (b, "tp,s1,s1", group, MODE_none);
2156 tree
2157 resolve (function_resolver &r) const override
2159 unsigned int i, nargs;
2160 type_suffix_index type;
2161 if (!r.check_gp_argument (2, i, nargs)
2162 || (type = r.infer_integer_scalar_type (i)) == NUM_TYPE_SUFFIXES
2163 || !r.require_matching_integer_scalar_type (i + 1, i, type))
2164 return error_mark_node;
2166 return r.resolve_to (r.mode_suffix_id, r.type_suffix_ids[0], type,
2167 r.group_suffix_id);
2170 SHAPE (compare_scalar)
2172 /* svcount_t svfoo_t0[_t1](<t1>_t, <t1>_t, uint64_t)
2174 where _t0 is a _c<bits> suffix that describes the predicate-as-counter
2175 result. The final argument is an integer constant that specifies the
2176 number of vectors (2 or 4). */
2177 struct compare_scalar_count_def : public overloaded_base<1>
2179 void
2180 build (function_builder &b, const function_group_info &group) const override
2182 b.add_overloaded_functions (group, MODE_none);
2183 build_all (b, "v0,s1,s1,su64", group, MODE_none);
2186 tree
2187 resolve (function_resolver &r) const override
2189 unsigned int i, nargs;
2190 type_suffix_index type;
2191 if (!r.check_gp_argument (3, i, nargs)
2192 || (type = r.infer_64bit_scalar_integer_pair (i)) == NUM_TYPE_SUFFIXES
2193 || !r.require_integer_immediate (i + 2))
2194 return error_mark_node;
2196 return r.resolve_to (r.mode_suffix_id, r.type_suffix_ids[0], type);
2199 bool
2200 check (function_checker &c) const override
2202 return c.require_immediate_either_or (2, 2, 4);
2205 SHAPE (compare_scalar_count)
2207 /* svbool_t svfoo[_t0](sv<t0>_t, svint64_t) (for signed t0)
2208 svbool_t svfoo[_n_t0](sv<t0>_t, int64_t) (for signed t0)
2209 svbool_t svfoo[_t0](sv<t0>_t, svuint64_t) (for unsigned t0)
2210 svbool_t svfoo[_n_t0](sv<t0>_t, uint64_t) (for unsigned t0)
2212 i.e. a comparison in which the second argument is 64 bits. */
2213 struct compare_wide_opt_n_def : public overloaded_base<0>
2215 void
2216 build (function_builder &b, const function_group_info &group) const override
2218 b.add_overloaded_functions (group, MODE_none);
2219 build_all (b, "vp,v0,vw0", group, MODE_none);
2220 build_all (b, "vp,v0,sw0", group, MODE_n);
2223 tree
2224 resolve (function_resolver &r) const override
2226 unsigned int i, nargs;
2227 type_suffix_index type;
2228 if (!r.check_gp_argument (2, i, nargs)
2229 || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES)
2230 return error_mark_node;
2232 return r.finish_opt_n_resolution (i + 1, i, type, r.SAME_TYPE_CLASS, 64);
2235 SHAPE (compare_wide_opt_n)
2237 /* uint64_t svfoo(). */
2238 struct count_inherent_def : public nonoverloaded_base
2240 void
2241 build (function_builder &b, const function_group_info &group) const override
2243 build_all (b, "su64", group, MODE_none);
2246 SHAPE (count_inherent)
2248 /* uint64_t svfoo(enum svpattern). */
2249 struct count_pat_def : public nonoverloaded_base
2251 void
2252 build (function_builder &b, const function_group_info &group) const override
2254 build_all (b, "su64,epattern", group, MODE_none);
2257 SHAPE (count_pat)
2259 /* uint64_t svfoo(svbool_t). */
2260 struct count_pred_def : public nonoverloaded_base
2262 void
2263 build (function_builder &b, const function_group_info &group) const override
2265 build_all (b, "su64,vp", group, MODE_none);
2268 SHAPE (count_pred)
2270 /* uint64_t svfoo_t0(sv<t0>_t, uint64_t)
2272 where the final argument must be 2 or 4. */
2273 struct count_pred_c_def : public nonoverloaded_base
2275 void
2276 build (function_builder &b, const function_group_info &group) const override
2278 build_all (b, "su64,v0,su64", group, MODE_none);
2281 bool
2282 check (function_checker &c) const override
2284 return c.require_immediate_either_or (1, 2, 4);
2287 SHAPE (count_pred_c)
2289 /* uint64_t svfoo[_t0](sv<t0>_t). */
2290 struct count_vector_def : public overloaded_base<0>
2292 void
2293 build (function_builder &b, const function_group_info &group) const override
2295 b.add_overloaded_functions (group, MODE_none);
2296 build_all (b, "su64,v0", group, MODE_none);
2299 tree
2300 resolve (function_resolver &r) const override
2302 return r.resolve_uniform (1);
2305 SHAPE (count_vector)
2307 /* sv<t0>xN_t svfoo[_t0](sv<t0>_t, ..., sv<t0>_t)
2309 where there are N arguments in total. */
2310 struct create_def : public overloaded_base<0>
2312 void
2313 build (function_builder &b, const function_group_info &group) const override
2315 b.add_overloaded_functions (group, MODE_none);
2316 build_all (b, "t0,v0*t", group, MODE_none);
2319 tree
2320 resolve (function_resolver &r) const override
2322 return r.resolve_uniform (r.vectors_per_tuple ());
2325 SHAPE (create)
2327 /* void svfoo_lane_t0[_t1]_g(uint32_t, sv<t1>x<g>_t, sv<t1:int>_t, uint64_t)
2329 where the final argument indexes a <t0>-sized group of elements in the
2330 preceding vector argument. */
2331 struct dot_za_slice_int_lane_def
2332 : public binary_za_slice_lane_base<TYPE_signed>
2334 constexpr dot_za_slice_int_lane_def ()
2335 : binary_za_slice_lane_base<TYPE_signed> (0) {}
2337 void
2338 build (function_builder &b, const function_group_info &group) const override
2340 b.add_overloaded_functions (group, MODE_none);
2341 build_all (b, "_,su32,t1,vs1,su64", group, MODE_none);
2344 SHAPE (dot_za_slice_int_lane)
2346 /* void svfoo_lane_t0[_t1]_g(uint32_t, sv<t1>x<g>_t, sv<t1>_t, uint64_t)
2348 where the final argument indexes a <t0>-sized group of elements in the
2349 preceding vector argument. */
2350 struct dot_za_slice_lane_def : public binary_za_slice_lane_base<>
2352 constexpr dot_za_slice_lane_def () : binary_za_slice_lane_base<> (0) {}
2354 SHAPE (dot_za_slice_lane)
2356 /* void svfoo_lane_t0[_t1]_g(uint32_t, sv<t1>x<g>_t, sv<t1:uint>_t, uint64_t)
2358 where the final argument indexes a <t0>-sized group of elements in the
2359 preceding vector argument. */
2360 struct dot_za_slice_uint_lane_def
2361 : public binary_za_slice_lane_base<TYPE_unsigned>
2363 constexpr dot_za_slice_uint_lane_def ()
2364 : binary_za_slice_lane_base<TYPE_unsigned> (0) {}
2366 void
2367 build (function_builder &b, const function_group_info &group) const override
2369 b.add_overloaded_functions (group, MODE_none);
2370 build_all (b, "_,su32,t1,vu1,su64", group, MODE_none);
2373 SHAPE (dot_za_slice_uint_lane)
2375 /* sv<t0>_t svfoo[_n]_t0(<t0>_t, ..., <t0>_t)
2377 where there are enough arguments to fill 128 bits of data (or to
2378 control 128 bits of data in the case of predicates). */
2379 struct dupq_def : public overloaded_base<1>
2381 void
2382 build (function_builder &b, const function_group_info &group) const override
2384 /* The "_n" suffix is optional; the full name has it, but the short
2385 name doesn't. */
2386 build_all (b, "v0,s0*q", group, MODE_n, true);
2389 tree
2390 resolve (function_resolver &) const override
2392 /* The short forms just make "_n" implicit, so no resolution is needed. */
2393 gcc_unreachable ();
2396 SHAPE (dupq)
2398 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0>_t, uint64_t)
2400 where the final argument is an integer constant expression that when
2401 multiplied by the number of bytes in t0 is in the range [0, 255]. */
2402 struct ext_def : public overloaded_base<0>
2404 void
2405 build (function_builder &b, const function_group_info &group) const override
2407 b.add_overloaded_functions (group, MODE_none);
2408 build_all (b, "v0,v0,v0,su64", group, MODE_none);
2411 tree
2412 resolve (function_resolver &r) const override
2414 return r.resolve_uniform (2, 1);
2417 bool
2418 check (function_checker &c) const override
2420 unsigned int bytes = c.type_suffix (0).element_bytes;
2421 return c.require_immediate_range (2, 0, 256 / bytes - 1);
2424 SHAPE (ext)
2426 /* svboolx<g>_t svfoo_t0_g(sv<t0>_t, sv<t0>_t, uint32_t). */
2427 struct extract_pred_def : public nonoverloaded_base
2429 void
2430 build (function_builder &b, const function_group_info &group) const override
2432 build_all (b, "tp,vc,su64", group, MODE_none);
2435 bool
2436 check (function_checker &c) const override
2438 unsigned int size = c.vectors_per_tuple ();
2439 return c.require_immediate_range (1, 0, 4 / size - 1);
2442 SHAPE (extract_pred)
2444 /* <t0>_t svfoo[_t0](<t0>_t, sv<t0>_t). */
2445 struct fold_left_def : public overloaded_base<0>
2447 void
2448 build (function_builder &b, const function_group_info &group) const override
2450 b.add_overloaded_functions (group, MODE_none);
2451 build_all (b, "s0,s0,v0", group, MODE_none);
2454 tree
2455 resolve (function_resolver &r) const override
2457 unsigned int i, nargs;
2458 type_suffix_index type;
2459 if (!r.check_gp_argument (2, i, nargs)
2460 || !r.require_derived_scalar_type (i, r.SAME_TYPE_CLASS)
2461 || (type = r.infer_vector_type (i + 1)) == NUM_TYPE_SUFFIXES)
2462 return error_mark_node;
2464 return r.resolve_to (r.mode_suffix_id, type);
2467 SHAPE (fold_left)
2469 /* sv<t0>_t svfoo[_t0](sv<t0>xN_t, uint64_t)
2471 where the final argument is an integer constant expression in
2472 the range [0, N - 1]. */
2473 struct get_def : public overloaded_base<0>
2475 void
2476 build (function_builder &b, const function_group_info &group) const override
2478 b.add_overloaded_functions (group, MODE_none);
2479 build_all (b, "v0,t0,su64", group, MODE_none);
2482 tree
2483 resolve (function_resolver &r) const override
2485 unsigned int i, nargs;
2486 sve_type type;
2487 if (!r.check_gp_argument (2, i, nargs)
2488 || !(type = r.infer_tuple_type (i))
2489 || !r.require_integer_immediate (i + 1))
2490 return error_mark_node;
2492 return r.resolve_to (r.mode_suffix_id, type);
2495 bool
2496 check (function_checker &c) const override
2498 unsigned int nvectors = c.vectors_per_tuple ();
2499 return c.require_immediate_range (1, 0, nvectors - 1);
2502 SHAPE (get)
2504 /* <t0>xN_t svfoo[_t0](sv<t0>_t). */
2505 struct get_neonq_def : public overloaded_base<0>
2507 void
2508 build (function_builder &b, const function_group_info &group) const override
2510 b.add_overloaded_functions (group, MODE_none);
2511 build_all (b, "Q0,v0", group, MODE_none);
2513 tree
2514 resolve (function_resolver &r) const override
2516 return r.resolve_unary ();
2519 SHAPE (get_neonq)
2521 /* sv<t0>_t svfoo[_t0](sv<t0>_t, <t0>xN_t). */
2522 struct set_neonq_def : public overloaded_base<0>
2524 void
2525 build (function_builder &b, const function_group_info &group) const override
2527 b.add_overloaded_functions (group, MODE_none);
2528 build_all (b, "v0,v0,Q0", group, MODE_none);
2530 tree
2531 resolve (function_resolver &r) const override
2533 unsigned int i, nargs;
2534 type_suffix_index type;
2535 if (!r.check_gp_argument (2, i, nargs)
2536 || (type = r.infer_neon128_vector_type (i + 1)) == NUM_TYPE_SUFFIXES)
2537 return error_mark_node;
2538 return r.resolve_to (r.mode_suffix_id, type);
2541 SHAPE (set_neonq)
2543 /* sv<t0>_t svfoo[_t0](<t0>xN_t). */
2544 struct dup_neonq_def : public overloaded_base<0>
2546 void
2547 build (function_builder &b, const function_group_info &group) const override
2549 b.add_overloaded_functions (group, MODE_none);
2550 build_all (b, "v0,Q0", group, MODE_none);
2552 tree
2553 resolve (function_resolver &r) const override
2555 unsigned int i, nargs;
2556 type_suffix_index type;
2557 if (!r.check_gp_argument (1, i, nargs)
2558 || (type = r.infer_neon128_vector_type (i)) == NUM_TYPE_SUFFIXES)
2559 return error_mark_node;
2560 return r.resolve_to (r.mode_suffix_id, type);
2563 SHAPE (dup_neonq)
2565 /* sv<t0>_t svfoo[_t0](sv<t0>_t, uint64_t)
2566 <t0>_t svfoo[_n_t0](<t0>_t, uint64_t)
2568 where the t0 in the vector form is a signed or unsigned integer
2569 whose size is tied to the [bhwd] suffix of "svfoo". */
2570 struct inc_dec_def : public inc_dec_base
2572 CONSTEXPR inc_dec_def () : inc_dec_base (false) {}
2574 void
2575 build (function_builder &b, const function_group_info &group) const override
2577 b.add_overloaded_functions (group, MODE_none);
2578 /* These functions are unusual in that the type suffixes for
2579 the scalar and vector forms are not related. The vector
2580 form always has exactly two potential suffixes while the
2581 scalar form always has four. */
2582 if (group.types[2][0] == NUM_TYPE_SUFFIXES)
2583 build_all (b, "v0,v0,su64", group, MODE_none);
2584 else
2585 build_all (b, "s0,s0,su64", group, MODE_n);
2588 SHAPE (inc_dec)
2590 /* sv<t0>_t svfoo[_t0](sv<t0>_t, enum svpattern, uint64_t)
2591 <t0>_t svfoo[_n_t0](<t0>_t, enum svpattern, uint64_t)
2593 where the t0 in the vector form is a signed or unsigned integer
2594 whose size is tied to the [bhwd] suffix of "svfoo". */
2595 struct inc_dec_pat_def : public inc_dec_base
2597 CONSTEXPR inc_dec_pat_def () : inc_dec_base (true) {}
2599 void
2600 build (function_builder &b, const function_group_info &group) const override
2602 b.add_overloaded_functions (group, MODE_none);
2603 /* These functions are unusual in that the type suffixes for
2604 the scalar and vector forms are not related. The vector
2605 form always has exactly two potential suffixes while the
2606 scalar form always has four. */
2607 if (group.types[2][0] == NUM_TYPE_SUFFIXES)
2608 build_all (b, "v0,v0,epattern,su64", group, MODE_none);
2609 else
2610 build_all (b, "s0,s0,epattern,su64", group, MODE_n);
2613 SHAPE (inc_dec_pat)
2615 /* sv<t0>_t svfoo[_t0](sv<t0>_t, svbool_t). */
2616 struct inc_dec_pred_def : public overloaded_base<0>
2618 void
2619 build (function_builder &b, const function_group_info &group) const override
2621 b.add_overloaded_functions (group, MODE_none);
2622 build_all (b, "v0,v0,vp", group, MODE_none);
2625 tree
2626 resolve (function_resolver &r) const override
2628 unsigned int i, nargs;
2629 type_suffix_index type;
2630 if (!r.check_gp_argument (2, i, nargs)
2631 || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
2632 || !r.require_vector_type (i + 1, VECTOR_TYPE_svbool_t))
2633 return error_mark_node;
2635 return r.resolve_to (r.mode_suffix_id, type);
2638 SHAPE (inc_dec_pred)
2640 /* <t0>_t svfoo[_n_t0]_t1(<t0>_t, svbool_t)
2642 where _t1 is a _b<bits> suffix that describes the svbool_t argument. */
2643 struct inc_dec_pred_scalar_def : public overloaded_base<2>
2645 void
2646 build (function_builder &b, const function_group_info &group) const override
2648 b.add_overloaded_functions (group, MODE_n);
2649 build_all (b, "s0,s0,vp", group, MODE_n);
2652 tree
2653 resolve (function_resolver &r) const override
2655 unsigned int i, nargs;
2656 type_suffix_index type;
2657 if (!r.check_gp_argument (2, i, nargs)
2658 || (type = r.infer_integer_scalar_type (i)) == NUM_TYPE_SUFFIXES
2659 || !r.require_vector_type (i + 1, VECTOR_TYPE_svbool_t))
2660 return error_mark_node;
2662 return r.resolve_to (r.mode_suffix_id, type, r.type_suffix_ids[1]);
2665 SHAPE (inc_dec_pred_scalar)
2667 /* sv<t0>[xN]_t svfoo_t0(). */
2668 struct inherent_def : public nonoverloaded_base
2670 void
2671 build (function_builder &b, const function_group_info &group) const override
2673 build_all (b, "t0", group, MODE_none);
2676 SHAPE (inherent)
2678 /* svbool_t svfoo[_b](). */
2679 struct inherent_b_def : public overloaded_base<0>
2681 void
2682 build (function_builder &b, const function_group_info &group) const override
2684 /* The "_b" suffix is optional; the full name has it, but the short
2685 name doesn't. */
2686 build_all (b, "v0", group, MODE_none, true);
2689 tree
2690 resolve (function_resolver &) const override
2692 /* The short forms just make "_b" implicit, so no resolution is needed. */
2693 gcc_unreachable ();
2696 SHAPE (inherent_b)
2698 /* void svfoo_t0(). */
2699 struct inherent_za_def : public nonoverloaded_base
2701 void
2702 build (function_builder &b, const function_group_info &group) const override
2704 build_all (b, "_", group, MODE_none);
2707 SHAPE (inherent_za)
2709 /* void svfoo_zt(uint64_t)
2711 where the argument must be zero. */
2712 struct inherent_zt_def : public nonoverloaded_base
2714 void
2715 build (function_builder &b, const function_group_info &group) const override
2717 build_all (b, "_,su64", group, MODE_none);
2720 bool
2721 check (function_checker &c) const override
2723 return c.require_immediate_range (0, 0, 0);
2726 SHAPE (inherent_zt)
2728 /* void svfoo_t0(uint64_t)
2730 where the argument is an integer constant that specifies an 8-bit mask. */
2731 struct inherent_mask_za_def : public nonoverloaded_base
2733 void
2734 build (function_builder &b, const function_group_info &group) const override
2736 build_all (b, "_,su64", group, MODE_none);
2739 bool
2740 check (function_checker &c) const override
2742 return c.require_immediate_range (0, 0, 255);
2745 SHAPE (inherent_mask_za)
2747 /* void svfoo_t0(uint32_t, const void *)
2748 void svfoo_vnum_t0(uint32_t, const void *, int64_t)
2750 where the first argument is a variable ZA slice. */
2751 struct ldr_za_def : public nonoverloaded_base
2753 void
2754 build (function_builder &b, const function_group_info &group) const override
2756 build_all (b, "_,su32,al", group, MODE_none);
2757 build_all (b, "_,su32,al,ss64", group, MODE_vnum);
2760 SHAPE (ldr_za)
2762 /* void svfoo_zt(uint64_t, const void *)
2764 where the first argument must be zero. */
2765 struct ldr_zt_def : public nonoverloaded_base
2767 void
2768 build (function_builder &b, const function_group_info &group) const override
2770 build_all (b, "_,su64,al", group, MODE_none);
2773 bool
2774 check (function_checker &c) const override
2776 return c.require_immediate_range (0, 0, 0);
2779 SHAPE (ldr_zt)
2781 /* sv<t0>[xN]_t svfoo[_t0]_g(const <t0>_t *)
2782 sv<t0>[xN]_t svfoo_vnum[_t0]_g(const <t0>_t *, int64_t). */
2783 struct load_def : public load_contiguous_base
2785 void
2786 build (function_builder &b, const function_group_info &group) const override
2788 b.add_overloaded_functions (group, MODE_none);
2789 b.add_overloaded_functions (group, MODE_vnum);
2790 build_all (b, "t0,al", group, MODE_none);
2791 build_all (b, "t0,al,ss64", group, MODE_vnum);
2794 SHAPE (load)
2796 /* sv<t0>_t svfoo_t0(const <X>_t *)
2797 sv<t0>_t svfoo_vnum_t0(const <X>_t *, int64_t)
2799 where <X> is determined by the function base name. */
2800 struct load_ext_def : public nonoverloaded_base
2802 void
2803 build (function_builder &b, const function_group_info &group) const override
2805 build_all (b, "t0,al", group, MODE_none);
2806 build_all (b, "t0,al,ss64", group, MODE_vnum);
2809 SHAPE (load_ext)
2811 /* sv<t0>_t svfoo_[s32]index_t0(const <X>_t *, svint32_t)
2812 sv<t0>_t svfoo_[s64]index_t0(const <X>_t *, svint64_t)
2813 sv<t0>_t svfoo_[u32]index_t0(const <X>_t *, svuint32_t)
2814 sv<t0>_t svfoo_[u64]index_t0(const <X>_t *, svuint64_t)
2816 sv<t0>_t svfoo[_u32base]_index_t0(svuint32_t, int64_t)
2817 sv<t0>_t svfoo[_u64base]_index_t0(svuint64_t, int64_t)
2819 where <X> is determined by the function base name. */
2820 struct load_ext_gather_index_def : public load_ext_gather_base
2822 void
2823 build (function_builder &b, const function_group_info &group) const override
2825 b.add_overloaded_functions (group, MODE_index);
2826 build_sv_index (b, "t0,al,d", group);
2827 build_vs_index (b, "t0,b,ss64", group);
2830 SHAPE (load_ext_gather_index)
2832 /* sv<t0>_t svfoo_[s64]index_t0(const <X>_t *, svint64_t)
2833 sv<t0>_t svfoo_[u64]index_t0(const <X>_t *, svuint64_t)
2835 sv<t0>_t svfoo[_u32base]_index_t0(svuint32_t, int64_t)
2836 sv<t0>_t svfoo[_u64base]_index_t0(svuint64_t, int64_t)
2838 where <X> is determined by the function base name. This is
2839 load_ext_gather_index that doesn't support 32-bit vector indices. */
2840 struct load_ext_gather_index_restricted_def : public load_ext_gather_base
2842 void
2843 build (function_builder &b, const function_group_info &group) const override
2845 b.add_overloaded_functions (group, MODE_index);
2846 build_sv_index64 (b, "t0,al,d", group);
2847 build_vs_index (b, "t0,b,ss64", group);
2850 SHAPE (load_ext_gather_index_restricted)
2852 /* sv<t0>_t svfoo_[s32]offset_t0(const <X>_t *, svint32_t)
2853 sv<t0>_t svfoo_[s64]offset_t0(const <X>_t *, svint64_t)
2854 sv<t0>_t svfoo_[u32]offset_t0(const <X>_t *, svuint32_t)
2855 sv<t0>_t svfoo_[u64]offset_t0(const <X>_t *, svuint64_t)
2857 sv<t0>_t svfoo[_u32base]_t0(svuint32_t)
2858 sv<t0>_t svfoo[_u64base]_t0(svuint64_t)
2860 sv<t0>_t svfoo[_u32base]_offset_t0(svuint32_t, int64_t)
2861 sv<t0>_t svfoo[_u64base]_offset_t0(svuint64_t, int64_t)
2863 where <X> is determined by the function base name. */
2864 struct load_ext_gather_offset_def : public load_ext_gather_base
2866 void
2867 build (function_builder &b, const function_group_info &group) const override
2869 b.add_overloaded_functions (group, MODE_offset);
2870 build_sv_offset (b, "t0,al,d", group);
2871 build_v_base (b, "t0,b", group, true);
2872 build_vs_offset (b, "t0,b,ss64", group);
2875 SHAPE (load_ext_gather_offset)
2877 /* sv<t0>_t svfoo_[s64]offset_t0(const <X>_t *, svint64_t)
2878 sv<t0>_t svfoo_[u32]offset_t0(const <X>_t *, svuint32_t)
2879 sv<t0>_t svfoo_[u64]offset_t0(const <X>_t *, svuint64_t)
2881 sv<t0>_t svfoo[_u32base]_t0(svuint32_t)
2882 sv<t0>_t svfoo[_u64base]_t0(svuint64_t)
2884 sv<t0>_t svfoo[_u32base]_offset_t0(svuint32_t, int64_t)
2885 sv<t0>_t svfoo[_u64base]_offset_t0(svuint64_t, int64_t)
2887 where <X> is determined by the function base name. This is
2888 load_ext_gather_offset without the s32 vector offset form. */
2889 struct load_ext_gather_offset_restricted_def : public load_ext_gather_base
2891 void
2892 build (function_builder &b, const function_group_info &group) const override
2894 b.add_overloaded_functions (group, MODE_offset);
2895 build_sv_uint_offset (b, "t0,al,d", group);
2896 build_v_base (b, "t0,b", group, true);
2897 build_vs_offset (b, "t0,b,ss64", group);
2900 SHAPE (load_ext_gather_offset_restricted)
2902 /* sv<t0>_t svfoo_[s32]index[_t0](const <t0>_t *, svint32_t)
2903 sv<t0>_t svfoo_[s64]index[_t0](const <t0>_t *, svint64_t)
2904 sv<t0>_t svfoo_[u32]index[_t0](const <t0>_t *, svuint32_t)
2905 sv<t0>_t svfoo_[u64]index[_t0](const <t0>_t *, svuint64_t)
2907 sv<t0>_t svfoo_[s32]offset[_t0](const <t0>_t *, svint32_t)
2908 sv<t0>_t svfoo_[s64]offset[_t0](const <t0>_t *, svint64_t)
2909 sv<t0>_t svfoo_[u32]offset[_t0](const <t0>_t *, svuint32_t)
2910 sv<t0>_t svfoo_[u64]offset[_t0](const <t0>_t *, svuint64_t). */
2911 struct load_gather_sv_def : public load_gather_sv_base
2913 void
2914 build (function_builder &b, const function_group_info &group) const override
2916 b.add_overloaded_functions (group, MODE_index);
2917 b.add_overloaded_functions (group, MODE_offset);
2918 build_sv_index (b, "t0,al,d", group);
2919 build_sv_offset (b, "t0,al,d", group);
2922 SHAPE (load_gather_sv)
2924 /* sv<t0>_t svfoo_[u32]index[_t0](const <t0>_t *, svuint32_t)
2925 sv<t0>_t svfoo_[u64]index[_t0](const <t0>_t *, svuint64_t)
2927 sv<t0>_t svfoo_[s64]offset[_t0](const <t0>_t *, svint64_t)
2928 sv<t0>_t svfoo_[u32]offset[_t0](const <t0>_t *, svuint32_t)
2929 sv<t0>_t svfoo_[u64]offset[_t0](const <t0>_t *, svuint64_t)
2931 This is load_gather_sv without the 32-bit vector index forms and
2932 without the s32 vector offset form. */
2933 struct load_gather_sv_restricted_def : public load_gather_sv_base
2935 void
2936 build (function_builder &b, const function_group_info &group) const override
2938 b.add_overloaded_functions (group, MODE_index);
2939 b.add_overloaded_functions (group, MODE_offset);
2940 build_sv_index64 (b, "t0,al,d", group);
2941 build_sv_uint_offset (b, "t0,al,d", group);
2944 SHAPE (load_gather_sv_restricted)
2946 /* sv<t0>_t svfoo[_u32base]_t0(svuint32_t)
2947 sv<t0>_t svfoo[_u64base]_t0(svuint64_t)
2949 sv<t0>_t svfoo[_u32base]_index_t0(svuint32_t, int64_t)
2950 sv<t0>_t svfoo[_u64base]_index_t0(svuint64_t, int64_t)
2952 sv<t0>_t svfoo[_u32base]_offset_t0(svuint32_t, int64_t)
2953 sv<t0>_t svfoo[_u64base]_offset_t0(svuint64_t, int64_t). */
2954 struct load_gather_vs_def : public overloaded_base<1>
2956 void
2957 build (function_builder &b, const function_group_info &group) const override
2959 /* The base vector mode is optional; the full name has it but the
2960 short name doesn't. There is no ambiguity with SHAPE_load_gather_sv
2961 because the latter uses an implicit type suffix. */
2962 build_v_base (b, "t0,b", group, true);
2963 build_vs_index (b, "t0,b,ss64", group, true);
2964 build_vs_offset (b, "t0,b,ss64", group, true);
2967 tree
2968 resolve (function_resolver &) const override
2970 /* The short name just makes the base vector mode implicit;
2971 no resolution is needed. */
2972 gcc_unreachable ();
2975 SHAPE (load_gather_vs)
2977 /* sv<t0>_t svfoo[_t0](const <t0>_t *)
2979 The only difference from "load" is that this shape has no vnum form. */
2980 struct load_replicate_def : public load_contiguous_base
2982 void
2983 build (function_builder &b, const function_group_info &group) const override
2985 b.add_overloaded_functions (group, MODE_none);
2986 build_all (b, "t0,al", group, MODE_none);
2989 SHAPE (load_replicate)
2991 /* void svfoo_t0(uint64_t, uint32_t, svbool_t, const void *)
2992 void svfoo_vnum_t0(uint64_t, uint32_t, svbool_t, const void *, int64_t)
2994 where the first two fields form a (ZA tile, slice) pair. */
2995 struct load_za_def : public nonoverloaded_base
2997 void
2998 build (function_builder &b, const function_group_info &group) const override
3000 build_all (b, "_,su64,su32,vp,al", group, MODE_none);
3001 build_all (b, "_,su64,su32,vp,al,ss64", group, MODE_vnum);
3004 bool
3005 check (function_checker &c) const override
3007 return c.require_immediate_range (0, 0, c.num_za_tiles () - 1);
3010 SHAPE (load_za)
3012 using luti2_lane_zt_def = luti_lane_zt_base<2>;
3013 SHAPE (luti2_lane_zt)
3015 using luti4_lane_zt_def = luti_lane_zt_base<4>;
3016 SHAPE (luti4_lane_zt)
3018 /* svbool_t svfoo(enum svpattern). */
3019 struct pattern_pred_def : public nonoverloaded_base
3021 void
3022 build (function_builder &b, const function_group_info &group) const override
3024 build_all (b, "vp,epattern", group, MODE_none);
3027 SHAPE (pattern_pred)
3029 /* void svfoo(const void *, svprfop)
3030 void svfoo_vnum(const void *, int64_t, svprfop). */
3031 struct prefetch_def : public nonoverloaded_base
3033 void
3034 build (function_builder &b, const function_group_info &group) const override
3036 build_all (b, "_,ap,eprfop", group, MODE_none);
3037 build_all (b, "_,ap,ss64,eprfop", group, MODE_vnum);
3040 SHAPE (prefetch)
3042 /* void svfoo_[s32]index(const void *, svint32_t, svprfop)
3043 void svfoo_[s64]index(const void *, svint64_t, svprfop)
3044 void svfoo_[u32]index(const void *, svuint32_t, svprfop)
3045 void svfoo_[u64]index(const void *, svuint64_t, svprfop)
3047 void svfoo[_u32base](svuint32_t, svprfop)
3048 void svfoo[_u64base](svuint64_t, svprfop)
3050 void svfoo[_u32base]_index(svuint32_t, int64_t, svprfop)
3051 void svfoo[_u64base]_index(svuint64_t, int64_t, svprfop). */
3052 struct prefetch_gather_index_def : public prefetch_gather_base
3054 void
3055 build (function_builder &b, const function_group_info &group) const override
3057 b.add_overloaded_functions (group, MODE_none);
3058 b.add_overloaded_functions (group, MODE_index);
3059 build_sv_index (b, "_,ap,d,eprfop", group);
3060 build_v_base (b, "_,b,eprfop", group);
3061 build_vs_index (b, "_,b,ss64,eprfop", group);
3064 SHAPE (prefetch_gather_index)
3066 /* void svfoo_[s32]offset(const void *, svint32_t, svprfop)
3067 void svfoo_[s64]offset(const void *, svint64_t, svprfop)
3068 void svfoo_[u32]offset(const void *, svuint32_t, svprfop)
3069 void svfoo_[u64]offset(const void *, svuint64_t, svprfop)
3071 void svfoo[_u32base](svuint32_t, svprfop)
3072 void svfoo[_u64base](svuint64_t, svprfop)
3074 void svfoo[_u32base]_offset(svuint32_t, int64_t, svprfop)
3075 void svfoo[_u64base]_offset(svuint64_t, int64_t, svprfop). */
3076 struct prefetch_gather_offset_def : public prefetch_gather_base
3078 void
3079 build (function_builder &b, const function_group_info &group) const override
3081 b.add_overloaded_functions (group, MODE_none);
3082 b.add_overloaded_functions (group, MODE_offset);
3083 build_sv_offset (b, "_,ap,d,eprfop", group);
3084 build_v_base (b, "_,b,eprfop", group);
3085 build_vs_offset (b, "_,b,ss64,eprfop", group);
3088 SHAPE (prefetch_gather_offset)
3090 /* bool svfoo(svbool_t). */
3091 struct ptest_def : public nonoverloaded_base
3093 void
3094 build (function_builder &b, const function_group_info &group) const override
3096 build_all (b, "sp,vp", group, MODE_none);
3099 SHAPE (ptest)
3101 /* svbool_t svfoo(). */
3102 struct rdffr_def : public nonoverloaded_base
3104 void
3105 build (function_builder &b, const function_group_info &group) const override
3107 build_all (b, "vp", group, MODE_none);
3110 SHAPE (rdffr)
3112 /* sv<t1>x<g>_t svfoo_t0_t1_g(uint64_t, uint32_t). */
3113 struct read_za_def : public nonoverloaded_base
3115 void
3116 build (function_builder &b, const function_group_info &group) const override
3118 build_all (b, "t1,su64,su32", group, MODE_none);
3121 bool
3122 check (function_checker &c) const override
3124 return c.require_immediate_range (0, 0, c.num_za_tiles () - 1);
3127 SHAPE (read_za)
3129 /* sv<t1>_t svfoo_t0[_t1](uint64_t, uint32_t)
3131 where the first two fields form a (ZA tile, slice) pair. */
3132 struct read_za_m_def : public overloaded_base<1>
3134 bool
3135 has_merge_argument_p (const function_instance &, unsigned int) const override
3137 return true;
3140 void
3141 build (function_builder &b, const function_group_info &group) const override
3143 b.add_overloaded_functions (group, MODE_none);
3144 build_all (b, "t1,su64,su32", group, MODE_none);
3147 tree
3148 resolve (function_resolver &r) const override
3150 gcc_assert (r.pred == PRED_m);
3151 type_suffix_index type;
3152 if (!r.check_num_arguments (4)
3153 || (type = r.infer_vector_type (0)) == NUM_TYPE_SUFFIXES
3154 || !r.require_vector_type (1, VECTOR_TYPE_svbool_t)
3155 || !r.require_integer_immediate (2)
3156 || !r.require_scalar_type (3, "uint32_t"))
3157 return error_mark_node;
3159 return r.resolve_to (r.mode_suffix_id, r.type_suffix_ids[0], type);
3162 bool
3163 check (function_checker &c) const override
3165 gcc_assert (c.pred == PRED_m);
3166 return c.require_immediate_range (1, 0, c.num_za_tiles () - 1);
3169 SHAPE (read_za_m)
3171 /* sv<t1>x<g>_t svfoo_t0_t1_g(uint32_t). */
3172 struct read_za_slice_def : public nonoverloaded_base
3174 void
3175 build (function_builder &b, const function_group_info &group) const override
3177 build_all (b, "t1,su32", group, MODE_none);
3180 SHAPE (read_za_slice)
3182 /* <t0>_t svfoo[_t0](sv<t0>_t). */
3183 struct reduction_def : public overloaded_base<0>
3185 void
3186 build (function_builder &b, const function_group_info &group) const override
3188 b.add_overloaded_functions (group, MODE_none);
3189 build_all (b, "s0,v0", group, MODE_none);
3192 tree
3193 resolve (function_resolver &r) const override
3195 return r.resolve_uniform (1);
3198 SHAPE (reduction)
3200 /* int64_t svfoo[_t0](sv<t0>_t) (for signed t0)
3201 uint64_t svfoo[_t0](sv<t0>_t) (for unsigned t0)
3202 <t0>_t svfoo[_t0](sv<t0>_t) (for floating-point t0)
3204 i.e. a version of "reduction" in which the return type for integers
3205 always has 64 bits. */
3206 struct reduction_wide_def : public overloaded_base<0>
3208 void
3209 build (function_builder &b, const function_group_info &group) const override
3211 b.add_overloaded_functions (group, MODE_none);
3212 build_all (b, "sw0,v0", group, MODE_none);
3215 tree
3216 resolve (function_resolver &r) const override
3218 return r.resolve_uniform (1);
3221 SHAPE (reduction_wide)
3223 /* sv<t0>x<g>_t svfoo_t0[_t1_g](sv<t1>x<g>_t)
3225 where the target type <t0> must be specified explicitly but the source
3226 type <t1> can be inferred. */
3227 struct reinterpret_def : public overloaded_base<1>
3229 bool explicit_group_suffix_p () const override { return false; }
3231 void
3232 build (function_builder &b, const function_group_info &group) const override
3234 b.add_overloaded_functions (group, MODE_none);
3235 build_all (b, "t0,t1", group, MODE_none);
3238 tree
3239 resolve (function_resolver &r) const override
3241 sve_type type;
3242 if (!r.check_num_arguments (1)
3243 || !(type = r.infer_sve_type (0)))
3244 return error_mark_node;
3246 return r.resolve_to (r.mode_suffix_id, type);
3249 SHAPE (reinterpret)
3251 /* sv<t0>_t svfoo_t0(sv<t0>_t, sv<t0>_t, uint32_t). */
3252 struct select_pred_def : public nonoverloaded_base
3254 void
3255 build (function_builder &b, const function_group_info &group) const override
3257 build_all (b, "v0,v0,vp,su32", group, MODE_none);
3260 SHAPE (select_pred)
3262 /* sv<t0>xN_t svfoo[_t0](sv<t0>xN_t, uint64_t, sv<t0>_t)
3264 where the second argument is an integer constant expression in the
3265 range [0, N - 1]. */
3266 struct set_def : public overloaded_base<0>
3268 void
3269 build (function_builder &b, const function_group_info &group) const override
3271 b.add_overloaded_functions (group, MODE_none);
3272 build_all (b, "t0,t0,su64,v0", group, MODE_none);
3275 tree
3276 resolve (function_resolver &r) const override
3278 unsigned int i, nargs;
3279 sve_type type;
3280 if (!r.check_gp_argument (3, i, nargs)
3281 || !(type = r.infer_tuple_type (i))
3282 || !r.require_integer_immediate (i + 1)
3283 || !r.require_derived_vector_type (i + 2, i, type))
3284 return error_mark_node;
3286 return r.resolve_to (r.mode_suffix_id, type);
3289 bool
3290 check (function_checker &c) const override
3292 unsigned int nvectors = c.vectors_per_tuple ();
3293 return c.require_immediate_range (1, 0, nvectors - 1);
3296 SHAPE (set)
3298 /* void svfoo(). */
3299 struct setffr_def : public nonoverloaded_base
3301 void
3302 build (function_builder &b, const function_group_info &group) const override
3304 build_all (b, "_", group, MODE_none);
3307 SHAPE (setffr)
3309 /* sv<t0>_t svfoo[_n_t0])(sv<t0>_t, uint64_t)
3311 where the final argument must be an integer constant expression in the
3312 range [0, sizeof (<t0>_t) * 8 - 1]. */
3313 struct shift_left_imm_def : public overloaded_base<0>
3315 void
3316 build (function_builder &b, const function_group_info &group) const override
3318 b.add_overloaded_functions (group, MODE_n);
3319 build_all (b, "v0,v0,su64", group, MODE_n);
3322 tree
3323 resolve (function_resolver &r) const override
3325 return r.resolve_uniform (1, 1);
3328 bool
3329 check (function_checker &c) const override
3331 unsigned int bits = c.type_suffix (0).element_bits;
3332 return c.require_immediate_range (1, 0, bits - 1);
3335 SHAPE (shift_left_imm)
3337 /* sv<t0>_t svfoo[_n_t0])(sv<t0:half>_t, uint64_t)
3339 where the final argument must be an integer constant expression in the
3340 range [0, sizeof (<t0>_t) * 4 - 1]. */
3341 struct shift_left_imm_long_def : public binary_imm_long_base
3343 bool
3344 check (function_checker &c) const override
3346 unsigned int bits = c.type_suffix (0).element_bits / 2;
3347 return c.require_immediate_range (1, 0, bits - 1);
3350 SHAPE (shift_left_imm_long)
3352 /* sv<t0:uint>_t svfoo[_n_t0])(sv<t0>_t, uint64_t)
3354 where the final argument must be an integer constant expression in the
3355 range [0, sizeof (<t0>_t) * 8 - 1]. */
3356 struct shift_left_imm_to_uint_def : public shift_left_imm_def
3358 void
3359 build (function_builder &b, const function_group_info &group) const override
3361 b.add_overloaded_functions (group, MODE_n);
3362 build_all (b, "vu0,v0,su64", group, MODE_n);
3365 SHAPE (shift_left_imm_to_uint)
3367 /* sv<t0>_t svfoo[_n_t0])(sv<t0>_t, uint64_t)
3369 where the final argument must be an integer constant expression in the
3370 range [1, sizeof (<t0>_t) * 8]. */
3371 struct shift_right_imm_def : public overloaded_base<0>
3373 void
3374 build (function_builder &b, const function_group_info &group) const override
3376 b.add_overloaded_functions (group, MODE_n);
3377 build_all (b, "v0,v0,su64", group, MODE_n);
3380 tree
3381 resolve (function_resolver &r) const override
3383 return r.resolve_uniform (1, 1);
3386 bool
3387 check (function_checker &c) const override
3389 unsigned int bits = c.type_suffix (0).element_bits;
3390 return c.require_immediate_range (1, 1, bits);
3393 SHAPE (shift_right_imm)
3395 /* sv<t0:half>_t svfoo[_n_t0])(sv<t0>_t, uint64_t)
3397 where the final argument must be an integer constant expression in the
3398 range [1, sizeof (<t0>_t) * 4]. */
3399 typedef shift_right_imm_narrow_wrapper<binary_imm_narrowb_base<>, 1>
3400 shift_right_imm_narrowb_def;
3401 SHAPE (shift_right_imm_narrowb)
3403 /* sv<t0:half>_t svfoo[_n_t0])(sv<t0:half>_t, sv<t0>_t, uint64_t)
3405 where the final argument must be an integer constant expression in the
3406 range [1, sizeof (<t0>_t) * 4]. */
3407 typedef shift_right_imm_narrow_wrapper<binary_imm_narrowt_base<>, 2>
3408 shift_right_imm_narrowt_def;
3409 SHAPE (shift_right_imm_narrowt)
3411 /* sv<t0:uint:half>_t svfoo[_n_t0])(sv<t0>_t, uint64_t)
3413 where the final argument must be an integer constant expression in the
3414 range [1, sizeof (<t0>_t) * 4]. */
3415 typedef binary_imm_narrowb_base<TYPE_unsigned>
3416 binary_imm_narrowb_base_unsigned;
3417 typedef shift_right_imm_narrow_wrapper<binary_imm_narrowb_base_unsigned, 1>
3418 shift_right_imm_narrowb_to_uint_def;
3419 SHAPE (shift_right_imm_narrowb_to_uint)
3421 /* sv<t0:uint:half>_t svfoo[_n_t0])(sv<t0:uint:half>_t, sv<t0>_t, uint64_t)
3423 where the final argument must be an integer constant expression in the
3424 range [1, sizeof (<t0>_t) * 4]. */
3425 typedef binary_imm_narrowt_base<TYPE_unsigned>
3426 binary_imm_narrowt_base_unsigned;
3427 typedef shift_right_imm_narrow_wrapper<binary_imm_narrowt_base_unsigned, 2>
3428 shift_right_imm_narrowt_to_uint_def;
3429 SHAPE (shift_right_imm_narrowt_to_uint)
3431 /* sv<t0>_t svfoo[_n_t0])(sv<t0>_t, uint64_t)
3433 where the final argument must be an integer constant expression in the
3434 range [1, sizeof (<t0>_t) * 8]. */
3435 struct shift_right_imm_narrowxn_def : public overloaded_base<1>
3437 bool explicit_group_suffix_p () const override { return false; }
3439 void
3440 build (function_builder &b, const function_group_info &group) const override
3442 b.add_overloaded_functions (group, MODE_n);
3443 build_all (b, "c0,c1,su64", group, MODE_n);
3446 tree
3447 resolve (function_resolver &r) const override
3449 sve_type type;
3450 if (!r.check_num_arguments (2)
3451 || !(type = r.infer_sve_type (0))
3452 || !r.require_integer_immediate (1))
3453 return error_mark_node;
3454 return r.resolve_to (r.mode_suffix_id, type);
3457 bool
3458 check (function_checker &c) const override
3460 unsigned int suffix = c.group_suffix_id == GROUP_x4 ? 1 : 0;
3461 unsigned int bits = c.type_suffix (suffix).element_bits;
3462 return c.require_immediate_range (1, 1, bits);
3465 SHAPE (shift_right_imm_narrowxn)
3467 /* void svfoo[_t0](<X>_t *, sv<t0>[xN]_t)
3468 void svfoo_vnum[_t0](<X>_t *, int64_t, sv<t0>[xN]_t)
3470 where <X> might be tied to <t0> (for non-truncating stores) or might
3471 depend on the function base name (for truncating stores). */
3472 struct store_def : public overloaded_base<0>
3474 void
3475 build (function_builder &b, const function_group_info &group) const override
3477 b.add_overloaded_functions (group, MODE_none);
3478 b.add_overloaded_functions (group, MODE_vnum);
3479 build_all (b, "_,as,t0", group, MODE_none);
3480 build_all (b, "_,as,ss64,t0", group, MODE_vnum);
3483 tree
3484 resolve (function_resolver &r) const override
3486 bool vnum_p = r.mode_suffix_id == MODE_vnum;
3487 gcc_assert (r.mode_suffix_id == MODE_none || vnum_p);
3489 unsigned int i, nargs;
3490 sve_type type;
3491 if (!r.check_gp_argument (vnum_p ? 3 : 2, i, nargs)
3492 || !r.require_pointer_type (i)
3493 || (vnum_p && !r.require_scalar_type (i + 1, "int64_t"))
3494 || !(type = r.infer_tuple_type (nargs - 1)))
3495 return error_mark_node;
3497 return r.resolve_to (r.mode_suffix_id, type);
3500 SHAPE (store)
3502 /* void svfoo_[s32]index[_t0](<X>_t *, svint32_t, sv<t0>_t)
3503 void svfoo_[s64]index[_t0](<X>_t *, svint64_t, sv<t0>_t)
3504 void svfoo_[u32]index[_t0](<X>_t *, svuint32_t, sv<t0>_t)
3505 void svfoo_[u64]index[_t0](<X>_t *, svuint64_t, sv<t0>_t)
3507 void svfoo[_u32base]_index[_t0](svuint32_t, int64_t, sv<t0>_t)
3508 void svfoo[_u64base]_index[_t0](svuint64_t, int64_t, sv<t0>_t)
3510 where <X> might be tied to <t0> (for non-truncating stores) or might
3511 depend on the function base name (for truncating stores). */
3512 struct store_scatter_index_def : public store_scatter_base
3514 void
3515 build (function_builder &b, const function_group_info &group) const override
3517 b.add_overloaded_functions (group, MODE_index);
3518 build_sv_index (b, "_,as,d,t0", group);
3519 build_vs_index (b, "_,b,ss64,t0", group);
3522 SHAPE (store_scatter_index)
3524 /* void svfoo_[s64]index[_t0](<X>_t *, svint64_t, sv<t0>_t)
3525 void svfoo_[u64]index[_t0](<X>_t *, svuint64_t, sv<t0>_t)
3527 void svfoo[_u32base]_index[_t0](svuint32_t, int64_t, sv<t0>_t)
3528 void svfoo[_u64base]_index[_t0](svuint64_t, int64_t, sv<t0>_t)
3530 i.e. a version of store_scatter_index that doesn't support 32-bit
3531 vector indices. */
3532 struct store_scatter_index_restricted_def : public store_scatter_base
3534 void
3535 build (function_builder &b, const function_group_info &group) const override
3537 b.add_overloaded_functions (group, MODE_index);
3538 build_sv_index64 (b, "_,as,d,t0", group);
3539 build_vs_index (b, "_,b,ss64,t0", group);
3542 SHAPE (store_scatter_index_restricted)
3544 /* void svfoo_[s32]offset[_t0](<X>_t *, svint32_t, sv<t0>_t)
3545 void svfoo_[s64]offset[_t0](<X>_t *, svint64_t, sv<t0>_t)
3546 void svfoo_[u32]offset[_t0](<X>_t *, svuint32_t, sv<t0>_t)
3547 void svfoo_[u64]offset[_t0](<X>_t *, svuint64_t, sv<t0>_t)
3549 void svfoo[_u32base_t0](svuint32_t, sv<t0>_t)
3550 void svfoo[_u64base_t0](svuint64_t, sv<t0>_t)
3552 void svfoo[_u32base]_offset[_t0](svuint32_t, int64_t, sv<t0>_t)
3553 void svfoo[_u64base]_offset[_t0](svuint64_t, int64_t, sv<t0>_t)
3555 where <X> might be tied to <t0> (for non-truncating stores) or might
3556 depend on the function base name (for truncating stores). */
3557 struct store_scatter_offset_def : public store_scatter_base
3559 void
3560 build (function_builder &b, const function_group_info &group) const override
3562 b.add_overloaded_functions (group, MODE_none);
3563 b.add_overloaded_functions (group, MODE_offset);
3564 build_sv_offset (b, "_,as,d,t0", group);
3565 build_v_base (b, "_,b,t0", group);
3566 build_vs_offset (b, "_,b,ss64,t0", group);
3569 SHAPE (store_scatter_offset)
3571 /* void svfoo_[s64]offset[_t0](<X>_t *, svint64_t, sv<t0>_t)
3572 void svfoo_[u32]offset[_t0](<X>_t *, svuint32_t, sv<t0>_t)
3573 void svfoo_[u64]offset[_t0](<X>_t *, svuint64_t, sv<t0>_t)
3575 void svfoo[_u32base_t0](svuint32_t, sv<t0>_t)
3576 void svfoo[_u64base_t0](svuint64_t, sv<t0>_t)
3578 void svfoo[_u32base]_offset[_t0](svuint32_t, int64_t, sv<t0>_t)
3579 void svfoo[_u64base]_offset[_t0](svuint64_t, int64_t, sv<t0>_t)
3581 i.e. a version of store_scatter_offset that doesn't support svint32_t
3582 offsets. */
3583 struct store_scatter_offset_restricted_def : public store_scatter_base
3585 void
3586 build (function_builder &b, const function_group_info &group) const override
3588 b.add_overloaded_functions (group, MODE_none);
3589 b.add_overloaded_functions (group, MODE_offset);
3590 build_sv_uint_offset (b, "_,as,d,t0", group);
3591 build_v_base (b, "_,b,t0", group);
3592 build_vs_offset (b, "_,b,ss64,t0", group);
3595 SHAPE (store_scatter_offset_restricted)
3597 /* void svfoo_t0(uint64_t, uint32_t, svbool_t, void *)
3598 void svfoo_vnum_t0(uint64_t, uint32_t, svbool_t, void *, int64_t)
3600 where the first two fields form a (ZA tile, slice) pair. */
3601 struct store_za_def : public nonoverloaded_base
3603 void
3604 build (function_builder &b, const function_group_info &group) const override
3606 build_all (b, "_,su64,su32,vp,as", group, MODE_none);
3607 build_all (b, "_,su64,su32,vp,as,ss64", group, MODE_vnum);
3610 bool
3611 check (function_checker &c) const override
3613 return c.require_immediate_range (0, 0, c.num_za_tiles () - 1);
3616 SHAPE (store_za)
3618 /* void svfoo[_t0_g](<X>_t *, sv<t0>x<g>_t)
3619 void svfoo_vnum[_t0_g](<X>_t *, int64_t, sv<t0>x<g>_t)
3621 where <X> might be tied to <t0> (for non-truncating stores) or might
3622 depend on the function base name (for truncating stores). */
3623 struct storexn_def : public store_def
3625 bool explicit_group_suffix_p () const override { return false; }
3627 tree
3628 resolve (function_resolver &r) const override
3630 bool vnum_p = r.mode_suffix_id == MODE_vnum;
3631 gcc_assert (r.mode_suffix_id == MODE_none || vnum_p);
3633 unsigned int nargs = vnum_p ? 4 : 3;
3634 vector_type_index pred_type;
3635 sve_type type;
3636 if (!r.check_num_arguments (nargs)
3637 || (pred_type = r.infer_predicate_type (0)) == NUM_VECTOR_TYPES
3638 || !r.require_pointer_type (1)
3639 || (vnum_p && !r.require_scalar_type (2, "int64_t"))
3640 || !(type = r.infer_sve_type (nargs - 1))
3641 || !r.require_matching_predicate_type (pred_type, type))
3642 return error_mark_node;
3644 return r.resolve_to (r.mode_suffix_id, type);
3647 SHAPE (storexn)
3649 /* void svfoo_t0(uint32_t, void *)
3650 void svfoo_vnum_t0(uint32_t, void *, int64_t)
3652 where the first argument is a variable ZA slice. */
3653 struct str_za_def : public nonoverloaded_base
3655 void
3656 build (function_builder &b, const function_group_info &group) const override
3658 build_all (b, "_,su32,as", group, MODE_none);
3659 build_all (b, "_,su32,as,ss64", group, MODE_vnum);
3662 SHAPE (str_za)
3664 /* void svfoo_zt(uint64_t, void *)
3666 where the first argument must be zero. */
3667 struct str_zt_def : public nonoverloaded_base
3669 void
3670 build (function_builder &b, const function_group_info &group) const override
3672 build_all (b, "_,su64,as", group, MODE_none);
3675 bool
3676 check (function_checker &c) const override
3678 return c.require_immediate_range (0, 0, 0);
3681 SHAPE (str_zt)
3683 /* sv<t0>_t svfoo[_t0](sv<t0>xN_t, sv<t0:uint>_t). */
3684 struct tbl_tuple_def : public overloaded_base<0>
3686 void
3687 build (function_builder &b, const function_group_info &group) const override
3689 b.add_overloaded_functions (group, MODE_none);
3690 build_all (b, "v0,t0,vu0", group, MODE_none);
3693 tree
3694 resolve (function_resolver &r) const override
3696 unsigned int i, nargs;
3697 sve_type type;
3698 if (!r.check_gp_argument (2, i, nargs)
3699 || !(type = r.infer_tuple_type (i))
3700 || !r.require_derived_vector_type (i + 1, i, type, TYPE_unsigned))
3701 return error_mark_node;
3703 return r.resolve_to (r.mode_suffix_id, type);
3706 SHAPE (tbl_tuple)
3708 /* sv<t0>_t svfoo[_t0](sv<t0>_t, svbfloatt16_t, svbfloat16_t). */
3709 struct ternary_bfloat_def
3710 : public ternary_resize2_base<16, TYPE_bfloat, TYPE_bfloat>
3712 void
3713 build (function_builder &b, const function_group_info &group) const override
3715 b.add_overloaded_functions (group, MODE_none);
3716 build_all (b, "v0,v0,vB,vB", group, MODE_none);
3719 SHAPE (ternary_bfloat)
3721 /* sv<t0>_t svfoo[_t0](sv<t0>_t, svbfloat16_t, svbfloat16_t, uint64_t)
3723 where the final argument is an integer constant expression in the range
3724 [0, 7]. */
3725 typedef ternary_bfloat_lane_base<1> ternary_bfloat_lane_def;
3726 SHAPE (ternary_bfloat_lane)
3728 /* sv<t0>_t svfoo[_t0](sv<t0>_t, svbfloat16_t, svbfloat16_t, uint64_t)
3730 where the final argument is an integer constant expression in the range
3731 [0, 3]. */
3732 typedef ternary_bfloat_lane_base<2> ternary_bfloat_lanex2_def;
3733 SHAPE (ternary_bfloat_lanex2)
3735 /* sv<t0>_t svfoo[_t0](sv<t0>_t, svbfloatt16_t, svbfloat16_t)
3736 sv<t0>_t svfoo[_n_t0](sv<t0>_t, svbfloat16_t, bfloat16_t). */
3737 struct ternary_bfloat_opt_n_def
3738 : public ternary_resize2_opt_n_base<16, TYPE_bfloat, TYPE_bfloat>
3740 void
3741 build (function_builder &b, const function_group_info &group) const override
3743 b.add_overloaded_functions (group, MODE_none);
3744 build_all (b, "v0,v0,vB,vB", group, MODE_none);
3745 build_all (b, "v0,v0,vB,sB", group, MODE_n);
3748 SHAPE (ternary_bfloat_opt_n)
3750 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:int:quarter>_t, sv<t0:uint:quarter>_t,
3751 uint64_t)
3753 where the final argument is an integer constant expression in the range
3754 [0, 16 / sizeof (<t0>_t) - 1]. */
3755 struct ternary_intq_uintq_lane_def
3756 : public ternary_qq_lane_base<TYPE_signed, TYPE_unsigned>
3758 void
3759 build (function_builder &b, const function_group_info &group) const override
3761 b.add_overloaded_functions (group, MODE_none);
3762 build_all (b, "v0,v0,vqs0,vqu0,su64", group, MODE_none);
3765 SHAPE (ternary_intq_uintq_lane)
3767 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:int:quarter>_t, sv<t0:uint:quarter>_t)
3768 sv<t0>_t svfoo[_n_t0](sv<t0>_t, sv<t0:int:quarter>_t,
3769 <t0:uint:quarter>_t). */
3770 struct ternary_intq_uintq_opt_n_def
3771 : public ternary_resize2_opt_n_base<function_resolver::QUARTER_SIZE,
3772 TYPE_signed, TYPE_unsigned>
3774 void
3775 build (function_builder &b, const function_group_info &group) const override
3777 b.add_overloaded_functions (group, MODE_none);
3778 build_all (b, "v0,v0,vqs0,vqu0", group, MODE_none);
3779 build_all (b, "v0,v0,vqs0,squ0", group, MODE_n);
3782 SHAPE (ternary_intq_uintq_opt_n)
3784 /* svbool_t svfoo[_<t0>](sv<t0>_t, sv<t0>_t, sv<t0>_t, uint64_t)
3786 where the final argument is an integer constant expression in the
3787 range [0, 16 / sizeof (<t0>_t) - 1]. */
3788 struct ternary_lane_def : public overloaded_base<0>
3790 void
3791 build (function_builder &b, const function_group_info &group) const override
3793 b.add_overloaded_functions (group, MODE_none);
3794 build_all (b, "v0,v0,v0,v0,su64", group, MODE_none);
3797 tree
3798 resolve (function_resolver &r) const override
3800 return r.resolve_uniform (3, 1);
3803 bool
3804 check (function_checker &c) const override
3806 return c.require_immediate_lane_index (3, 2);
3809 SHAPE (ternary_lane)
3811 /* svbool_t svfoo[_<t0>](sv<t0>_t, sv<t0>_t, sv<t0>_t, uint64_t, uint64_t)
3813 where the penultimate argument is an integer constant expression in
3814 the range [0, 8 / sizeof (<t0>_t) - 1] and where the final argument
3815 is an integer constant expression in {0, 90, 180, 270}. */
3816 struct ternary_lane_rotate_def : public overloaded_base<0>
3818 void
3819 build (function_builder &b, const function_group_info &group) const override
3821 b.add_overloaded_functions (group, MODE_none);
3822 build_all (b, "v0,v0,v0,v0,su64,su64", group, MODE_none);
3825 tree
3826 resolve (function_resolver &r) const override
3828 return r.resolve_uniform (3, 2);
3831 bool
3832 check (function_checker &c) const override
3834 return (c.require_immediate_lane_index (3, 2, 2)
3835 && c.require_immediate_one_of (4, 0, 90, 180, 270));
3838 SHAPE (ternary_lane_rotate)
3840 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:half>_t, sv<t0:half>_t, uint64_t)
3842 where the final argument is an integer constant expression in the range
3843 [0, 32 / sizeof (<t0>_t) - 1]. */
3844 struct ternary_long_lane_def
3845 : public ternary_resize2_lane_base<function_resolver::HALF_SIZE>
3847 void
3848 build (function_builder &b, const function_group_info &group) const override
3850 b.add_overloaded_functions (group, MODE_none);
3851 build_all (b, "v0,v0,vh0,vh0,su64", group, MODE_none);
3854 bool
3855 check (function_checker &c) const override
3857 return c.require_immediate_lane_index (3, 2);
3860 SHAPE (ternary_long_lane)
3862 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:half>_t, sv<t0:half>_t)
3863 sv<t0>_t svfoo[_n_t0](sv<t0>_t, sv<t0:half>_t, <t0:half>_t)
3865 i.e. a version of the standard ternary shape ternary_opt_n in which
3866 the element type of the last two arguments is the half-sized
3867 equivalent of <t0>. */
3868 struct ternary_long_opt_n_def
3869 : public ternary_resize2_opt_n_base<function_resolver::HALF_SIZE>
3871 void
3872 build (function_builder &b, const function_group_info &group) const override
3874 b.add_overloaded_functions (group, MODE_none);
3875 build_all (b, "v0,v0,vh0,vh0", group, MODE_none);
3876 build_all (b, "v0,v0,vh0,sh0", group, MODE_n);
3879 SHAPE (ternary_long_opt_n)
3881 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0>_t, sv<t0>_t)
3882 sv<t0>_t svfoo[_n_t0](sv<t0>_t, sv<t0>_t, <t0>_t)
3884 i.e. the standard shape for ternary operations that operate on
3885 uniform types. */
3886 struct ternary_opt_n_def : public overloaded_base<0>
3888 void
3889 build (function_builder &b, const function_group_info &group) const override
3891 b.add_overloaded_functions (group, MODE_none);
3892 build_all (b, "v0,v0,v0,v0", group, MODE_none);
3893 build_all (b, "v0,v0,v0,s0", group, MODE_n);
3896 tree
3897 resolve (function_resolver &r) const override
3899 return r.resolve_uniform_opt_n (3);
3902 SHAPE (ternary_opt_n)
3904 /* A choice between:
3906 (1) sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:quarter>_t, sv<t0:quarter>_t,
3907 uint64_t)
3909 (2) sv<t0>_t svfoo[_t0_t1](sv<t0>_t, sv<t1>_t, sv<t1>_t, uint64_t)
3911 where the final argument is an integer constant expression in the range
3912 [0, 16 / sizeof (<t0>_t) - 1]. */
3913 struct ternary_qq_or_011_lane_def : public ternary_qq_lane_base<>
3915 void
3916 build (function_builder &b, const function_group_info &group) const override
3918 b.add_overloaded_functions (group, MODE_none);
3919 if (group.types[0][1] == NUM_TYPE_SUFFIXES)
3920 build_all (b, "v0,v0,vq0,vq0,su64", group, MODE_none);
3921 else
3922 build_all (b, "v0,v0,v1,v1,su64", group, MODE_none);
3925 tree
3926 resolve (function_resolver &r) const override
3928 unsigned int i, nargs;
3929 type_suffix_index type0, type1;
3930 if (!r.check_gp_argument (4, i, nargs)
3931 || (type0 = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
3932 || (type1 = r.infer_vector_type (i + 1)) == NUM_TYPE_SUFFIXES
3933 || !r.require_matching_vector_type (i + 2, i + 1, type1)
3934 || !r.require_integer_immediate (i + 3))
3935 return error_mark_node;
3937 if ((type_suffixes[type0].element_bits
3938 == 4 * type_suffixes[type1].element_bits)
3939 && type_suffixes[type0].tclass == type_suffixes[type1].tclass)
3940 if (tree res = r.lookup_form (MODE_none, type0))
3941 return res;
3943 return r.resolve_to (r.mode_suffix_id, type0, type1);
3946 SHAPE (ternary_qq_or_011_lane)
3948 /* svbool_t svfoo[_<t0>](sv<t0>_t, sv<t0:quarter>_t, sv<t0:quarter>_t,
3949 uint64_t)
3951 where the final argument is an integer constant expression in
3952 {0, 90, 180, 270}. */
3953 struct ternary_qq_lane_rotate_def : public overloaded_base<0>
3955 void
3956 build (function_builder &b, const function_group_info &group) const override
3958 b.add_overloaded_functions (group, MODE_none);
3959 build_all (b, "v0,v0,vq0,vq0,su64,su64", group, MODE_none);
3962 tree
3963 resolve (function_resolver &r) const override
3965 unsigned int i, nargs;
3966 type_suffix_index type;
3967 if (!r.check_gp_argument (5, i, nargs)
3968 || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
3969 || !r.require_derived_vector_type (i + 1, i, type, r.SAME_TYPE_CLASS,
3970 r.QUARTER_SIZE)
3971 || !r.require_derived_vector_type (i + 2, i, type, r.SAME_TYPE_CLASS,
3972 r.QUARTER_SIZE)
3973 || !r.require_integer_immediate (i + 3)
3974 || !r.require_integer_immediate (i + 4))
3975 return error_mark_node;
3977 return r.resolve_to (r.mode_suffix_id, type);
3980 bool
3981 check (function_checker &c) const override
3983 return (c.require_immediate_lane_index (3, 0)
3984 && c.require_immediate_one_of (4, 0, 90, 180, 270));
3987 SHAPE (ternary_qq_lane_rotate)
3989 /* A choice between:
3991 (1) sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:quarter>_t, sv<t0:quarter>_t)
3992 sv<t0>_t svfoo[_n_t0](sv<t0>_t, sv<t0:quarter>_t, <t0:quarter>_t)
3994 i.e. a version of the standard ternary shape ternary_opt_n in which
3995 the element type of the last two arguments is the quarter-sized
3996 equivalent of <t0>.
3998 (2) sv<t0>_t svfoo[_t0_t1](sv<t0>_t, sv<t1>_t, sv<t1>_t)
4000 where the element type of the last two arguments is specified
4001 explicitly. */
4002 struct ternary_qq_opt_n_or_011_def
4003 : public ternary_resize2_opt_n_base<function_resolver::QUARTER_SIZE>
4005 void
4006 build (function_builder &b, const function_group_info &group) const override
4008 b.add_overloaded_functions (group, MODE_none);
4009 if (group.types[0][1] == NUM_TYPE_SUFFIXES)
4011 build_all (b, "v0,v0,vq0,vq0", group, MODE_none);
4012 build_all (b, "v0,v0,vq0,sq0", group, MODE_n);
4014 else
4015 build_all (b, "v0,v0,v1,v1", group, MODE_none);
4018 tree
4019 resolve (function_resolver &r) const override
4021 unsigned int i, nargs;
4022 type_suffix_index type0, type1;
4023 if (!r.check_gp_argument (3, i, nargs)
4024 || (type0 = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
4025 || (type1 = r.infer_vector_type (i + 1)) == NUM_TYPE_SUFFIXES
4026 || !r.require_vector_or_scalar_type (i + 2))
4027 return error_mark_node;
4029 auto mode = r.scalar_argument_p (i + 2) ? MODE_n : MODE_none;
4030 if (mode == MODE_none
4031 && !r.require_matching_vector_type (i + 2, i + 1, type1))
4032 return error_mark_node;
4034 if ((type_suffixes[type0].element_bits
4035 == 4 * type_suffixes[type1].element_bits)
4036 && type_suffixes[type0].tclass == type_suffixes[type1].tclass)
4037 if (tree res = r.lookup_form (mode, type0))
4038 return res;
4040 if (!r.require_nonscalar_type (i + 2))
4041 return error_mark_node;
4043 return r.resolve_to (r.mode_suffix_id, type0, type1);
4046 SHAPE (ternary_qq_opt_n_or_011)
4048 /* svbool_t svfoo[_<t0>](sv<t0>_t, sv<t0:quarter>_t, sv<t0:quarter>_t,
4049 uint64_t)
4051 where the final argument is an integer constant expression in
4052 {0, 90, 180, 270}. */
4053 struct ternary_qq_rotate_def : public overloaded_base<0>
4055 void
4056 build (function_builder &b, const function_group_info &group) const override
4058 b.add_overloaded_functions (group, MODE_none);
4059 build_all (b, "v0,v0,vq0,vq0,su64", group, MODE_none);
4062 tree
4063 resolve (function_resolver &r) const override
4065 unsigned int i, nargs;
4066 type_suffix_index type;
4067 if (!r.check_gp_argument (4, i, nargs)
4068 || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
4069 || !r.require_derived_vector_type (i + 1, i, type, r.SAME_TYPE_CLASS,
4070 r.QUARTER_SIZE)
4071 || !r.require_derived_vector_type (i + 2, i, type, r.SAME_TYPE_CLASS,
4072 r.QUARTER_SIZE)
4073 || !r.require_integer_immediate (i + 3))
4074 return error_mark_node;
4076 return r.resolve_to (r.mode_suffix_id, type);
4079 bool
4080 check (function_checker &c) const override
4082 return c.require_immediate_one_of (3, 0, 90, 180, 270);
4085 SHAPE (ternary_qq_rotate)
4087 /* svbool_t svfoo[_<t0>](sv<t0>_t, sv<t0>_t, sv<t0>_t, uint64_t)
4089 where the final argument is an integer constant expression in
4090 {0, 90, 180, 270}. */
4091 struct ternary_rotate_def : public overloaded_base<0>
4093 void
4094 build (function_builder &b, const function_group_info &group) const override
4096 b.add_overloaded_functions (group, MODE_none);
4097 build_all (b, "v0,v0,v0,v0,su64", group, MODE_none);
4100 tree
4101 resolve (function_resolver &r) const override
4103 return r.resolve_uniform (3, 1);
4106 bool
4107 check (function_checker &c) const override
4109 return c.require_immediate_one_of (3, 0, 90, 180, 270);
4112 SHAPE (ternary_rotate)
4114 /* sv<t0>_t svfoo[_n_t0])(sv<t0>_t, sv<t0>_t, uint64_t)
4116 where the final argument must be an integer constant expression in the
4117 range [0, sizeof (<t0>_t) * 8 - 1]. */
4118 struct ternary_shift_left_imm_def : public ternary_shift_imm_base
4120 bool
4121 check (function_checker &c) const override
4123 unsigned int bits = c.type_suffix (0).element_bits;
4124 return c.require_immediate_range (2, 0, bits - 1);
4127 SHAPE (ternary_shift_left_imm)
4129 /* sv<t0>_t svfoo[_n_t0])(sv<t0>_t, sv<t0>_t, uint64_t)
4131 where the final argument must be an integer constant expression in the
4132 range [1, sizeof (<t0>_t) * 8]. */
4133 struct ternary_shift_right_imm_def : public ternary_shift_imm_base
4135 bool
4136 check (function_checker &c) const override
4138 unsigned int bits = c.type_suffix (0).element_bits;
4139 return c.require_immediate_range (2, 1, bits);
4142 SHAPE (ternary_shift_right_imm)
4144 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0>_t, sv<t0:uint>_t). */
4145 struct ternary_uint_def : public overloaded_base<0>
4147 void
4148 build (function_builder &b, const function_group_info &group) const override
4150 b.add_overloaded_functions (group, MODE_none);
4151 build_all (b, "v0,v0,v0,vu0", group, MODE_none);
4154 tree
4155 resolve (function_resolver &r) const override
4157 unsigned int i, nargs;
4158 type_suffix_index type;
4159 if (!r.check_gp_argument (3, i, nargs)
4160 || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
4161 || !r.require_matching_vector_type (i + 1, i, type)
4162 || !r.require_derived_vector_type (i + 2, i, type, TYPE_unsigned))
4163 return error_mark_node;
4165 return r.resolve_to (r.mode_suffix_id, type);
4168 SHAPE (ternary_uint)
4170 /* sv<t0>_t svfoo[_t0](sv<t0>_t, svu<t0:uint:quarter>_t,
4171 sv<t0:int:quarter>_t). */
4172 struct ternary_uintq_intq_def
4173 : public ternary_resize2_base<function_resolver::QUARTER_SIZE,
4174 TYPE_unsigned, TYPE_signed>
4176 void
4177 build (function_builder &b, const function_group_info &group) const override
4179 b.add_overloaded_functions (group, MODE_none);
4180 build_all (b, "v0,v0,vqu0,vqs0", group, MODE_none);
4183 SHAPE (ternary_uintq_intq)
4185 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:uint:quarter>_t, sv<t0:int:quarter>_t,
4186 uint64_t)
4188 where the final argument is an integer constant expression in the range
4189 [0, 16 / sizeof (<t0>_t) - 1]. */
4190 struct ternary_uintq_intq_lane_def
4191 : public ternary_qq_lane_base<TYPE_unsigned, TYPE_signed>
4193 void
4194 build (function_builder &b, const function_group_info &group) const override
4196 b.add_overloaded_functions (group, MODE_none);
4197 build_all (b, "v0,v0,vqu0,vqs0,su64", group, MODE_none);
4200 SHAPE (ternary_uintq_intq_lane)
4202 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:uint:quarter>_t, sv<t0:int:quarter>_t)
4203 sv<t0>_t svfoo[_n_t0](sv<t0>_t, sv<t0:uint:quarter>_t,
4204 <t0:int:quarter>_t). */
4205 struct ternary_uintq_intq_opt_n_def
4206 : public ternary_resize2_opt_n_base<function_resolver::QUARTER_SIZE,
4207 TYPE_unsigned, TYPE_signed>
4209 void
4210 build (function_builder &b, const function_group_info &group) const override
4212 b.add_overloaded_functions (group, MODE_none);
4213 build_all (b, "v0,v0,vqu0,vqs0", group, MODE_none);
4214 build_all (b, "v0,v0,vqu0,sqs0", group, MODE_n);
4217 SHAPE (ternary_uintq_intq_opt_n)
4219 /* svbool_t svfoo[_<t0>](sv<t0>_t, sv<t0>_t, uint64_t)
4221 where the final argument is an integer constant expression in the
4222 range [0, 7]. */
4223 struct tmad_def : public overloaded_base<0>
4225 void
4226 build (function_builder &b, const function_group_info &group) const override
4228 b.add_overloaded_functions (group, MODE_none);
4229 build_all (b, "v0,v0,v0,su64", group, MODE_none);
4232 tree
4233 resolve (function_resolver &r) const override
4235 return r.resolve_uniform (2, 1);
4238 bool
4239 check (function_checker &c) const override
4241 return c.require_immediate_range (2, 0, 7);
4244 SHAPE (tmad)
4246 /* sv<t0>_t svfoo[_t0](sv<t0>_t)
4248 i.e. the standard shape for unary operations that operate on
4249 uniform types. */
4250 struct unary_def : public overloaded_base<0>
4252 void
4253 build (function_builder &b, const function_group_info &group) const override
4255 b.add_overloaded_functions (group, MODE_none);
4256 build_all (b, "t0,t0", group, MODE_none);
4259 tree
4260 resolve (function_resolver &r) const override
4262 return r.resolve_unary ();
4265 SHAPE (unary)
4267 /* sv<t0>_t svfoo_t0[_t1](sv<t1>_t)
4269 where the target type <t0> must be specified explicitly but the source
4270 type <t1> can be inferred. */
4271 struct unary_convert_def : public overloaded_base<1>
4273 void
4274 build (function_builder &b, const function_group_info &group) const override
4276 b.add_overloaded_functions (group, MODE_none);
4277 build_all (b, "c0,c1", group, MODE_none);
4280 tree
4281 resolve (function_resolver &r) const override
4283 return r.resolve_unary (r.type_suffix (0).tclass,
4284 r.type_suffix (0).element_bits);
4287 SHAPE (unary_convert)
4289 /* sv<t0>_t svfoo_t0[_t1](sv<t0>_t, sv<t1>_t)
4291 This is a version of unary_convert in which the even-indexed
4292 elements are passed in as a first parameter, before any governing
4293 predicate. */
4294 struct unary_convert_narrowt_def : public overloaded_base<1>
4296 bool
4297 has_merge_argument_p (const function_instance &, unsigned int) const override
4299 return true;
4302 void
4303 build (function_builder &b, const function_group_info &group) const override
4305 b.add_overloaded_functions (group, MODE_none);
4306 build_all (b, "v0,v1", group, MODE_none);
4309 tree
4310 resolve (function_resolver &r) const override
4312 return r.resolve_unary (r.type_suffix (0).tclass,
4313 r.type_suffix (0).element_bits, true);
4316 SHAPE (unary_convert_narrowt)
4318 /* sv<t0>x<g0>_t svfoo_t0[_t1_g](sv<t1>x<g1>_t)
4320 where the target type <t0> must be specified explicitly but the
4321 source type <t1> can be inferred.
4323 Functions with a group suffix are unpredicated. For them:
4325 - If <t0> is N times wider than <t1>, the return value has N times
4326 more vectors than the argument.
4328 - If <t1> is N times wider than <t0>, the argument has N times
4329 more vectors than the return type. */
4330 struct unary_convertxn_def : public unary_convert_def
4332 bool explicit_group_suffix_p () const override { return false; }
4334 tree
4335 resolve (function_resolver &r) const override
4337 if (r.pred != PRED_none)
4338 return unary_convert_def::resolve (r);
4340 sve_type type;
4341 if (!r.check_num_arguments (1)
4342 || !(type = r.infer_sve_type (0)))
4343 return error_mark_node;
4345 return r.resolve_conversion (r.mode_suffix_id, type);
4348 SHAPE (unary_convertxn)
4350 /* sv<t0>_t svfoo[_t0](sv<t0:half>_t). */
4351 struct unary_long_def : public overloaded_base<0>
4353 void
4354 build (function_builder &b, const function_group_info &group) const override
4356 b.add_overloaded_functions (group, MODE_none);
4357 build_all (b, "v0,vh0", group, MODE_none);
4360 tree
4361 resolve (function_resolver &r) const override
4363 unsigned int i, nargs;
4364 type_suffix_index type, result_type;
4365 if (!r.check_gp_argument (1, i, nargs)
4366 || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
4367 || (result_type = long_type_suffix (r, type)) == NUM_TYPE_SUFFIXES)
4368 return error_mark_node;
4370 if (tree res = r.lookup_form (r.mode_suffix_id, result_type))
4371 return res;
4373 return r.report_no_such_form (type);
4376 SHAPE (unary_long)
4378 /* sv<t0>_t svfoo[_n]_t0(<t0>_t). */
4379 struct unary_n_def : public overloaded_base<1>
4381 void
4382 build (function_builder &b, const function_group_info &group) const override
4384 /* The "_n" suffix is optional; the full name has it, but the short
4385 name doesn't. */
4386 build_all (b, "v0,s0", group, MODE_n, true);
4389 tree
4390 resolve (function_resolver &) const override
4392 /* The short forms just make "_n" implicit, so no resolution is needed. */
4393 gcc_unreachable ();
4396 SHAPE (unary_n)
4398 /* sv<t0:half>_t svfoo[_t0](sv<t0>_t). */
4399 typedef unary_narrowb_base<> unary_narrowb_def;
4400 SHAPE (unary_narrowb)
4402 /* sv<t0:half>_t svfoo[_t0](sv<t0:half>_t, sv<t0>_t). */
4403 typedef unary_narrowt_base<> unary_narrowt_def;
4404 SHAPE (unary_narrowt)
4406 /* sv<t0:uint:half>_t svfoo[_t0](sv<t0>_t). */
4407 typedef unary_narrowb_base<TYPE_unsigned> unary_narrowb_to_uint_def;
4408 SHAPE (unary_narrowb_to_uint)
4410 /* sv<t0:uint:half>_t svfoo[_t0](sv<t0:uint:half>_t, sv<t0>_t). */
4411 typedef unary_narrowt_base<TYPE_unsigned> unary_narrowt_to_uint_def;
4412 SHAPE (unary_narrowt_to_uint)
4414 /* svbool_t svfoo(svbool_t). */
4415 struct unary_pred_def : public nonoverloaded_base
4417 void
4418 build (function_builder &b, const function_group_info &group) const override
4420 build_all (b, "v0,v0", group, MODE_none);
4423 SHAPE (unary_pred)
4425 /* sv<t0:int>_t svfoo[_t0](sv<t0>_t)
4427 i.e. a version of "unary" in which the returned vector contains
4428 signed integers. */
4429 struct unary_to_int_def : public overloaded_base<0>
4431 void
4432 build (function_builder &b, const function_group_info &group) const override
4434 b.add_overloaded_functions (group, MODE_none);
4435 build_all (b, "vs0,v0", group, MODE_none);
4438 tree
4439 resolve (function_resolver &r) const override
4441 return r.resolve_unary (TYPE_signed);
4444 SHAPE (unary_to_int)
4446 /* sv<t0:uint>_t svfoo[_t0](sv<t0>_t)
4448 i.e. a version of "unary" in which the returned vector contains
4449 unsigned integers. */
4450 struct unary_to_uint_def : public overloaded_base<0>
4452 void
4453 build (function_builder &b, const function_group_info &group) const override
4455 b.add_overloaded_functions (group, MODE_none);
4456 build_all (b, "vu0,v0", group, MODE_none);
4459 tree
4460 resolve (function_resolver &r) const override
4462 return r.resolve_unary (TYPE_unsigned);
4465 SHAPE (unary_to_uint)
4467 /* sv<t0>_t svfoo[_t0](sv<t0:uint>_t)
4469 where <t0> always belongs a certain type class, and where <t0:uint>
4470 therefore uniquely determines <t0>. */
4471 struct unary_uint_def : public overloaded_base<0>
4473 void
4474 build (function_builder &b, const function_group_info &group) const override
4476 b.add_overloaded_functions (group, MODE_none);
4477 build_all (b, "v0,vu0", group, MODE_none);
4480 tree
4481 resolve (function_resolver &r) const override
4483 unsigned int i, nargs;
4484 type_suffix_index type;
4485 if (!r.check_gp_argument (1, i, nargs)
4486 || (type = r.infer_unsigned_vector_type (i)) == NUM_TYPE_SUFFIXES)
4487 return error_mark_node;
4489 /* Search for a valid suffix with the same number of bits as TYPE. */
4490 unsigned int element_bits = type_suffixes[type].element_bits;
4491 if (type_suffixes[type].unsigned_p)
4492 for (unsigned int j = 0; j < NUM_TYPE_SUFFIXES; ++j)
4493 if (type_suffixes[j].element_bits == element_bits)
4494 if (tree res = r.lookup_form (r.mode_suffix_id,
4495 type_suffix_index (j)))
4496 return res;
4498 return r.report_no_such_form (type);
4501 SHAPE (unary_uint)
4503 /* sv<t0>_t svfoo[_<t0>](sv<t0:half>_t)
4505 i.e. a version of "unary" in which the source elements are half the
4506 size of the destination elements, but have the same type class. */
4507 struct unary_widen_def : public overloaded_base<0>
4509 void
4510 build (function_builder &b, const function_group_info &group) const override
4512 b.add_overloaded_functions (group, MODE_none);
4513 build_all (b, "v0,vh0", group, MODE_none);
4516 tree
4517 resolve (function_resolver &r) const override
4519 unsigned int i, nargs;
4520 type_suffix_index type;
4521 if (!r.check_gp_argument (1, i, nargs)
4522 || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES)
4523 return error_mark_node;
4525 /* There is only a single form for predicates. */
4526 if (type == TYPE_SUFFIX_b)
4527 return r.resolve_to (r.mode_suffix_id, type);
4529 if (type_suffixes[type].integer_p
4530 && type_suffixes[type].element_bits < 64)
4532 type_suffix_index wide_suffix
4533 = find_type_suffix (type_suffixes[type].tclass,
4534 type_suffixes[type].element_bits * 2);
4535 if (tree res = r.lookup_form (r.mode_suffix_id, wide_suffix))
4536 return res;
4539 return r.report_no_such_form (type);
4542 SHAPE (unary_widen)
4544 /* void svfoo_t0[_t1](uint64_t, svbool_t, svbool_t, sv<t1>_t)
4546 where the first argument is a ZA tile. */
4547 struct unary_za_m_def : public overloaded_base<1>
4549 void
4550 build (function_builder &b, const function_group_info &group) const override
4552 b.add_overloaded_functions (group, MODE_none);
4553 build_all (b, "_,su64,vp,vp,t1", group, MODE_none);
4556 tree
4557 resolve (function_resolver &r) const override
4559 type_suffix_index type;
4560 if (!r.check_num_arguments (4)
4561 || !r.require_integer_immediate (0)
4562 || !r.require_vector_type (1, VECTOR_TYPE_svbool_t)
4563 || !r.require_vector_type (2, VECTOR_TYPE_svbool_t)
4564 || (type = r.infer_vector_type (3)) == NUM_TYPE_SUFFIXES)
4565 return error_mark_node;
4567 return r.resolve_to (r.mode_suffix_id, r.type_suffix_ids[0], type);
4570 bool
4571 check (function_checker &c) const override
4573 return c.require_immediate_range (0, 0, c.num_za_tiles () - 1);
4576 SHAPE (unary_za_m)
4578 /* void svfoo_t0[_t1]_g(uint32_t, sv<t1>x<g>_t). */
4579 struct unary_za_slice_def : public overloaded_base<1>
4581 void
4582 build (function_builder &b, const function_group_info &group) const override
4584 b.add_overloaded_functions (group, MODE_none);
4585 if (!za_group_is_pure_overload (group))
4586 build_all (b, "_,su32,t1", group, MODE_none);
4589 tree
4590 resolve (function_resolver &r) const override
4592 sve_type type;
4593 if (!r.check_num_arguments (2)
4594 || !r.require_scalar_type (0, "uint32_t")
4595 || !(type = r.infer_tuple_type (1)))
4596 return error_mark_node;
4598 return r.resolve_to (r.mode_suffix_id, type);
4601 SHAPE (unary_za_slice)
4603 /* sv<t0>x<g>_t svfoo[_t0_g](sv<t0>x<g>_t). */
4604 struct unaryxn_def : public unary_def
4606 bool explicit_group_suffix_p () const override { return false; }
4608 tree
4609 resolve (function_resolver &r) const override
4611 if (r.pred != PRED_none)
4612 return unary_def::resolve (r);
4614 sve_type type;
4615 if (!r.check_num_arguments (1)
4616 || !(type = r.infer_sve_type (0)))
4617 return error_mark_node;
4619 return r.resolve_to (r.mode_suffix_id, type);
4622 SHAPE (unaryxn)
4624 /* void svfoo_t0[_t1_g](uint64_t, uint32_t, sv<t1>x<g>_t). */
4625 struct write_za_def : public overloaded_base<1>
4627 void
4628 build (function_builder &b, const function_group_info &group) const override
4630 b.add_overloaded_functions (group, MODE_none);
4631 build_all (b, "_,su64,su32,t1", group, MODE_none);
4634 tree
4635 resolve (function_resolver &r) const override
4637 sve_type type;
4638 if (!r.check_num_arguments (3)
4639 || !r.require_integer_immediate (0)
4640 || !r.require_scalar_type (1, "uint32_t")
4641 || !(type = r.infer_tuple_type (2)))
4642 return error_mark_node;
4644 return r.resolve_to (r.mode_suffix_id, type);
4647 bool
4648 check (function_checker &c) const override
4650 return c.require_immediate_range (0, 0, c.num_za_tiles () - 1);
4653 SHAPE (write_za)
4655 /* void svfoo_t0[_t1](uint64_t, uint32_t, svbool_t, sv<t1>_t)
4657 where the first two fields form a (ZA tile, slice) pair. */
4658 struct write_za_m_def : public overloaded_base<1>
4660 void
4661 build (function_builder &b, const function_group_info &group) const override
4663 b.add_overloaded_functions (group, MODE_none);
4664 build_all (b, "_,su64,su32,vp,t1", group, MODE_none);
4667 tree
4668 resolve (function_resolver &r) const override
4670 type_suffix_index type;
4671 if (!r.check_num_arguments (4)
4672 || !r.require_integer_immediate (0)
4673 || !r.require_scalar_type (1, "uint32_t")
4674 || !r.require_vector_type (2, VECTOR_TYPE_svbool_t)
4675 || (type = r.infer_vector_type (3)) == NUM_TYPE_SUFFIXES)
4676 return error_mark_node;
4678 return r.resolve_to (r.mode_suffix_id, r.type_suffix_ids[0], type);
4681 bool
4682 check (function_checker &c) const override
4684 return c.require_immediate_range (0, 0, c.num_za_tiles () - 1);
4687 SHAPE (write_za_m)
4689 /* void svfoo_t0[_t1_g](uint32_t, sv<t1>x<g>_t). */
4690 struct write_za_slice_def : public overloaded_base<1>
4692 void
4693 build (function_builder &b, const function_group_info &group) const override
4695 b.add_overloaded_functions (group, MODE_none);
4696 build_all (b, "_,su32,t1", group, MODE_none);
4699 tree
4700 resolve (function_resolver &r) const override
4702 sve_type type;
4703 if (!r.check_num_arguments (2)
4704 || !r.require_scalar_type (0, "uint32_t")
4705 || !(type = r.infer_tuple_type (1)))
4706 return error_mark_node;
4708 return r.resolve_to (r.mode_suffix_id, type);
4711 SHAPE (write_za_slice)