[PR testsuite/116860] Testsuite adjustment for recently added tests
[official-gcc.git] / gcc / config / aarch64 / aarch64-sve-builtins-shapes.cc
blobaf23a154d0e88a40012fd0ac4695fcfb0644db60
1 /* ACLE support for AArch64 SVE (function shapes)
2 Copyright (C) 2018-2025 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
9 any later version.
11 GCC is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
20 #include "config.h"
21 #include "system.h"
22 #include "coretypes.h"
23 #include "tm.h"
24 #include "tree.h"
25 #include "rtl.h"
26 #include "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 M - mfloat8_t
100 p - a predicate (represented as TYPE_SUFFIX_b)
101 q<elt> - a quarter-sized version of <elt>
102 s<bits> - a signed type with the given number of bits
103 s[01] - a signed type with the same width as type suffix 0 or 1
104 u<bits> - an unsigned type with the given number of bits
105 u[01] - an unsigned type with the same width as type suffix 0 or 1
106 w<elt> - a 64-bit version of <elt> if <elt> is integral, otherwise <elt>
108 where <elt> is another element type. */
109 static type_suffix_index
110 parse_element_type (const function_instance &instance, const char *&format)
112 int ch = *format++;
114 if (ch == 'f' || ch == 's' || ch == 'u')
116 type_class_index tclass = (ch == 'f' ? TYPE_float
117 : ch == 's' ? TYPE_signed
118 : TYPE_unsigned);
119 char *end;
120 unsigned int bits = strtol (format, &end, 10);
121 format = end;
122 if (bits == 0 || bits == 1)
123 bits = instance.type_suffix (bits).element_bits;
124 return find_type_suffix (tclass, bits);
127 if (ch == 'w')
129 type_suffix_index suffix = parse_element_type (instance, format);
130 if (type_suffixes[suffix].integer_p)
131 return find_type_suffix (type_suffixes[suffix].tclass, 64);
132 return suffix;
135 if (ch == 'c')
136 return TYPE_SUFFIX_c;
138 if (ch == 'p')
139 return TYPE_SUFFIX_b;
141 if (ch == 'B')
142 return TYPE_SUFFIX_bf16;
144 if (ch == 'M')
145 return TYPE_SUFFIX_mf8;
147 if (ch == 'q')
149 type_suffix_index suffix = parse_element_type (instance, format);
150 return find_type_suffix (type_suffixes[suffix].tclass,
151 type_suffixes[suffix].element_bits / 4);
154 if (ch == 'h')
156 type_suffix_index suffix = parse_element_type (instance, format);
157 /* Widening and narrowing doesn't change the type for predicates;
158 everything's still an svbool_t. */
159 if (suffix == TYPE_SUFFIX_b)
160 return suffix;
161 return find_type_suffix (type_suffixes[suffix].tclass,
162 type_suffixes[suffix].element_bits / 2);
165 if (ch == '0' || ch == '1')
166 return instance.type_suffix_ids[ch - '0'];
168 gcc_unreachable ();
171 /* Read and return a type from FORMAT for function INSTANCE. Advance
172 FORMAT beyond the type string. The format is:
174 _ - void
175 al - array pointer for loads
176 ap - array pointer for prefetches
177 as - array pointer for stores
178 b - base vector type (from a _<m0>base suffix)
179 c0 - the result of a conversion, based on type and group suffixes
180 c1 - the source of a conversion, based on type and group suffixes
181 d - displacement vector type (from a _<m1>index or _<m1>offset suffix)
182 e<name> - an enum with the given name
183 s<elt> - a scalar type with the given element suffix
184 t<elt> - a vector or tuple type with given element suffix [*1]
185 v<elt> - a vector with the given element suffix
186 D<elt> - a 64 bit neon vector
187 Q<elt> - a 128 bit neon vector
189 where <elt> has the format described above parse_element_type
191 [*1] the vectors_per_tuple function indicates whether the type should
192 be a tuple, and if so, how many vectors it should contain. */
193 static tree
194 parse_type (const function_instance &instance, const char *&format)
196 int ch = *format++;
198 if (ch == '_')
199 return void_type_node;
201 if (ch == 'a')
203 ch = *format++;
204 if (ch == 'l')
205 return build_const_pointer (instance.memory_scalar_type ());
206 if (ch == 'p')
207 return const_ptr_type_node;
208 if (ch == 's')
209 return build_pointer_type (instance.memory_scalar_type ());
210 gcc_unreachable ();
213 if (ch == 'b')
214 return instance.base_vector_type ();
216 if (ch == 'c')
218 int ch = *format++;
219 gcc_assert (ch == '0' || ch == '1');
220 unsigned int id = (ch == '0' ? 0 : 1);
221 auto vector_type = instance.type_suffix (id).vector_type;
222 unsigned int num_vectors = instance.group_suffix ().vectors_per_tuple;
223 if (num_vectors != 1)
225 unsigned int bits = instance.type_suffix (id).element_bits;
226 unsigned int other_bits = instance.type_suffix (1 - id).element_bits;
227 if (other_bits > bits)
228 num_vectors /= other_bits / bits;
230 return acle_vector_types[num_vectors - 1][vector_type];
233 if (ch == 'd')
234 return instance.displacement_vector_type ();
236 if (ch == 'e')
238 if (startswith (format, "pattern"))
240 format += 7;
241 return acle_svpattern;
243 if (startswith (format, "prfop"))
245 format += 5;
246 return acle_svprfop;
248 gcc_unreachable ();
251 if (ch == 's')
253 type_suffix_index suffix = parse_element_type (instance, format);
254 return scalar_types[type_suffixes[suffix].vector_type];
257 if (ch == 't')
259 type_suffix_index suffix = parse_element_type (instance, format);
260 vector_type_index vector_type = type_suffixes[suffix].vector_type;
261 unsigned int num_vectors = instance.vectors_per_tuple ();
262 return acle_vector_types[num_vectors - 1][vector_type];
265 if (ch == 'v')
267 type_suffix_index suffix = parse_element_type (instance, format);
268 return acle_vector_types[0][type_suffixes[suffix].vector_type];
271 if (ch == 'D')
273 type_suffix_index suffix = parse_element_type (instance, format);
274 int neon_index = type_suffixes[suffix].neon64_type;
275 return aarch64_simd_types_trees[neon_index].itype;
278 if (ch == 'Q')
280 type_suffix_index suffix = parse_element_type (instance, format);
281 int neon_index = type_suffixes[suffix].neon128_type;
282 return aarch64_simd_types_trees[neon_index].itype;
285 gcc_unreachable ();
288 /* Read and move past any argument count at FORMAT for the function
289 signature of INSTANCE. The counts are:
291 *q: one argument per element in a 128-bit quadword (as for svdupq)
292 *t: one argument per vector in a tuple (as for svcreate)
294 Otherwise the count is 1. */
295 static unsigned int
296 parse_count (const function_instance &instance, const char *&format)
298 if (format[0] == '*' && format[1] == 'q')
300 format += 2;
301 return instance.elements_per_vq (0);
303 if (format[0] == '*' && format[1] == 't')
305 format += 2;
306 return instance.vectors_per_tuple ();
308 return 1;
311 /* Read a type signature for INSTANCE from FORMAT. Add the argument types
312 to ARGUMENT_TYPES and return the return type.
314 The format is a comma-separated list of types (as for parse_type),
315 with the first type being the return type and the rest being the
316 argument types. Each argument type can be followed by an optional
317 count (as for parse_count). */
318 static tree
319 parse_signature (const function_instance &instance, const char *format,
320 vec<tree> &argument_types)
322 tree return_type = parse_type (instance, format);
323 while (format[0] == ',')
325 format += 1;
326 tree argument_type = parse_type (instance, format);
327 unsigned int count = parse_count (instance, format);
328 for (unsigned int i = 0; i < count; ++i)
329 argument_types.quick_push (argument_type);
331 gcc_assert (format[0] == 0);
332 if (instance.fpm_mode == FPM_set)
333 argument_types.quick_push (get_typenode_from_name (UINT64_TYPE));
334 return return_type;
337 /* Add one function instance for GROUP, using mode suffix MODE_SUFFIX_ID,
338 the type suffixes at index TI, the group suffixes at index GI, and the
339 predication suffix at index PI. The other arguments are as for
340 build_all. */
341 static void
342 build_one (function_builder &b, const char *signature,
343 const function_group_info &group, mode_suffix_index mode_suffix_id,
344 unsigned int ti, unsigned int gi, unsigned int pi,
345 bool force_direct_overloads)
347 /* For simplicity, function definitions are allowed to use the group
348 suffix lists vg2 and vg4 for shapes that have _single forms,
349 even though the _single form applies only to vgNx2 and vgNx4,
350 not to vgNx1. */
351 if (mode_suffix_id == MODE_single
352 && group_suffixes[group.groups[gi]].vectors_per_tuple == 1)
353 return;
355 /* Byte forms of svdupq take 16 arguments. */
356 auto_vec<tree, 16> argument_types;
357 function_instance instance (group.base_name, *group.base, *group.shape,
358 mode_suffix_id, group.types[ti], group.groups[gi],
359 group.preds[pi], group.fpm_mode);
360 tree return_type = parse_signature (instance, signature, argument_types);
361 apply_predication (instance, return_type, argument_types);
362 b.add_unique_function (instance, return_type, argument_types,
363 group.required_extensions, force_direct_overloads);
366 /* GROUP describes some sort of gather or scatter operation. There are
367 two cases:
369 - If the function has any type suffixes (as for loads and stores), the
370 first function type suffix specifies either a 32-bit or a 64-bit type,
371 which in turn selects either MODE32 or MODE64 as the addressing mode.
372 Add a function instance for every type and predicate combination
373 in GROUP for which the associated addressing mode is not MODE_none.
375 - If the function has no type suffixes (as for prefetches), add one
376 MODE32 form and one MODE64 form for each predication type.
378 The other arguments are as for build_all. */
379 static void
380 build_32_64 (function_builder &b, const char *signature,
381 const function_group_info &group, mode_suffix_index mode32,
382 mode_suffix_index mode64, bool force_direct_overloads = false)
384 for (unsigned int pi = 0; group.preds[pi] != NUM_PREDS; ++pi)
385 for (unsigned int gi = 0; group.groups[gi] != NUM_GROUP_SUFFIXES; ++gi)
386 if (group.types[0][0] == NUM_TYPE_SUFFIXES)
388 gcc_assert (mode32 != MODE_none && mode64 != MODE_none);
389 build_one (b, signature, group, mode32, 0, gi, pi,
390 force_direct_overloads);
391 build_one (b, signature, group, mode64, 0, gi, pi,
392 force_direct_overloads);
394 else
395 for (unsigned int ti = 0; group.types[ti][0] != NUM_TYPE_SUFFIXES;
396 ++ti)
398 unsigned int bits = type_suffixes[group.types[ti][0]].element_bits;
399 gcc_assert (bits == 32 || bits == 64);
400 mode_suffix_index mode = bits == 32 ? mode32 : mode64;
401 if (mode != MODE_none)
402 build_one (b, signature, group, mode, ti, gi, pi,
403 force_direct_overloads);
407 /* For every type and predicate combination in GROUP, add one function
408 that takes a scalar (pointer) base and a signed vector array index,
409 and another that instead takes an unsigned vector array index.
410 The vector array index has the same element size as the first
411 function type suffix. SIGNATURE is as for build_all. */
412 static void
413 build_sv_index (function_builder &b, const char *signature,
414 const function_group_info &group)
416 build_32_64 (b, signature, group, MODE_s32index, MODE_s64index);
417 build_32_64 (b, signature, group, MODE_u32index, MODE_u64index);
420 /* Like build_sv_index, but only handle 64-bit types. */
421 static void
422 build_sv_index64 (function_builder &b, const char *signature,
423 const function_group_info &group)
425 build_32_64 (b, signature, group, MODE_none, MODE_s64index);
426 build_32_64 (b, signature, group, MODE_none, MODE_u64index);
429 /* Like build_sv_index, but taking vector byte offsets instead of vector
430 array indices. */
431 static void
432 build_sv_offset (function_builder &b, const char *signature,
433 const function_group_info &group)
435 build_32_64 (b, signature, group, MODE_s32offset, MODE_s64offset);
436 build_32_64 (b, signature, group, MODE_u32offset, MODE_u64offset);
439 /* Like build_sv_offset, but exclude offsets that must be interpreted
440 as signed (i.e. s32offset). */
441 static void
442 build_sv_uint_offset (function_builder &b, const char *signature,
443 const function_group_info &group)
445 build_32_64 (b, signature, group, MODE_none, MODE_s64offset);
446 build_32_64 (b, signature, group, MODE_u32offset, MODE_u64offset);
449 /* For every type and predicate combination in GROUP, add a function
450 that takes a vector base address and no displacement. The vector
451 base has the same element size as the first type suffix.
453 The other arguments are as for build_all. */
454 static void
455 build_v_base (function_builder &b, const char *signature,
456 const function_group_info &group,
457 bool force_direct_overloads = false)
459 build_32_64 (b, signature, group, MODE_u32base, MODE_u64base,
460 force_direct_overloads);
463 /* Like build_v_base, but for functions that also take a scalar array
464 index. */
465 static void
466 build_vs_index (function_builder &b, const char *signature,
467 const function_group_info &group,
468 bool force_direct_overloads = false)
470 build_32_64 (b, signature, group, MODE_u32base_index, MODE_u64base_index,
471 force_direct_overloads);
474 /* Like build_v_base, but for functions that also take a scalar byte
475 offset. */
476 static void
477 build_vs_offset (function_builder &b, const char *signature,
478 const function_group_info &group,
479 bool force_direct_overloads = false)
481 build_32_64 (b, signature, group, MODE_u32base_offset, MODE_u64base_offset,
482 force_direct_overloads);
485 /* Add a function instance for every type and predicate combination
486 in GROUP. Take the function base name from GROUP and the mode suffix
487 from MODE_SUFFIX_ID. Use SIGNATURE to construct the function signature
488 without a governing predicate, then use apply_predication to add in the
489 predicate. FORCE_DIRECT_OVERLOADS is true if there is a one-to-one
490 mapping between "short" and "full" names, and if standard overload
491 resolution therefore isn't necessary. */
492 static void
493 build_all (function_builder &b, const char *signature,
494 const function_group_info &group, mode_suffix_index mode_suffix_id,
495 bool force_direct_overloads = false)
497 for (unsigned int pi = 0; group.preds[pi] != NUM_PREDS; ++pi)
498 for (unsigned int gi = 0; group.groups[gi] != NUM_GROUP_SUFFIXES; ++gi)
499 for (unsigned int ti = 0;
500 ti == 0 || group.types[ti][0] != NUM_TYPE_SUFFIXES; ++ti)
501 build_one (b, signature, group, mode_suffix_id, ti, gi, pi,
502 force_direct_overloads);
505 /* TYPE is the largest type suffix associated with the arguments of R,
506 but the result is twice as wide. Return the associated type suffix
507 if it exists, otherwise report an appropriate error and return
508 NUM_TYPE_SUFFIXES. */
509 static type_suffix_index
510 long_type_suffix (function_resolver &r, type_suffix_index type)
512 unsigned int element_bits = type_suffixes[type].element_bits;
513 if (type_suffixes[type].integer_p && element_bits < 64)
514 return find_type_suffix (type_suffixes[type].tclass, element_bits * 2);
516 r.report_no_such_form (type);
517 return NUM_TYPE_SUFFIXES;
520 /* Declare the function shape NAME, pointing it to an instance
521 of class <NAME>_def. */
522 #define SHAPE(NAME) \
523 static CONSTEXPR const NAME##_def NAME##_obj; \
524 namespace shapes { const function_shape *const NAME = &NAME##_obj; }
526 /* Base class for functions that are not overloaded. */
527 struct nonoverloaded_base : public function_shape
529 bool
530 explicit_type_suffix_p (unsigned int) const override
532 return true;
535 tree
536 resolve (function_resolver &) const override
538 gcc_unreachable ();
542 /* Base class for overloaded functions. Bit N of EXPLICIT_MASK is true
543 if type suffix N appears in the overloaded name. */
544 template<unsigned int EXPLICIT_MASK>
545 struct overloaded_base : public function_shape
547 bool
548 explicit_type_suffix_p (unsigned int i) const override
550 return (EXPLICIT_MASK >> i) & 1;
554 /* Base class for adr_index and adr_offset. */
555 struct adr_base : public overloaded_base<0>
557 /* The function takes two arguments: a vector base and a vector displacement
558 (either an index or an offset). Resolve based on them both. */
559 tree
560 resolve (function_resolver &r) const override
562 unsigned int i, nargs;
563 mode_suffix_index mode;
564 if (!r.check_gp_argument (2, i, nargs)
565 || (mode = r.resolve_adr_address (0)) == MODE_none)
566 return error_mark_node;
568 return r.resolve_to (mode);
572 /* Base class for narrowing bottom binary functions that take an
573 immediate second operand. The result is half the size of input
574 and has class CLASS. */
575 template<type_class_index CLASS = function_resolver::SAME_TYPE_CLASS>
576 struct binary_imm_narrowb_base : public overloaded_base<0>
578 void
579 build (function_builder &b, const function_group_info &group) const override
581 b.add_overloaded_functions (group, MODE_n);
582 STATIC_ASSERT (CLASS == function_resolver::SAME_TYPE_CLASS
583 || CLASS == TYPE_unsigned);
584 if (CLASS == TYPE_unsigned)
585 build_all (b, "vhu0,v0,su64", group, MODE_n);
586 else
587 build_all (b, "vh0,v0,su64", group, MODE_n);
590 tree
591 resolve (function_resolver &r) const override
593 return r.resolve_uniform (1, 1);
597 /* The top equivalent of binary_imm_narrowb_base. It takes three arguments,
598 with the first being the values of the even elements, which are typically
599 the result of the narrowb operation. */
600 template<type_class_index CLASS = function_resolver::SAME_TYPE_CLASS>
601 struct binary_imm_narrowt_base : public overloaded_base<0>
603 void
604 build (function_builder &b, const function_group_info &group) const override
606 b.add_overloaded_functions (group, MODE_n);
607 STATIC_ASSERT (CLASS == function_resolver::SAME_TYPE_CLASS
608 || CLASS == TYPE_unsigned);
609 if (CLASS == TYPE_unsigned)
610 build_all (b, "vhu0,vhu0,v0,su64", group, MODE_n);
611 else
612 build_all (b, "vh0,vh0,v0,su64", group, MODE_n);
615 tree
616 resolve (function_resolver &r) const override
618 unsigned int i, nargs;
619 type_suffix_index type;
620 if (!r.check_gp_argument (3, i, nargs)
621 || (type = r.infer_vector_type (i + 1)) == NUM_TYPE_SUFFIXES
622 || !r.require_derived_vector_type (i, i + 1, type, CLASS, r.HALF_SIZE)
623 || !r.require_integer_immediate (i + 2))
624 return error_mark_node;
626 return r.resolve_to (r.mode_suffix_id, type);
630 /* Base class for long (i.e. narrow op narrow -> wide) binary functions
631 that take an immediate second operand. The type suffix specifies
632 the wider type. */
633 struct binary_imm_long_base : public overloaded_base<0>
635 void
636 build (function_builder &b, const function_group_info &group) const override
638 b.add_overloaded_functions (group, MODE_n);
639 build_all (b, "v0,vh0,su64", group, MODE_n);
642 tree
643 resolve (function_resolver &r) const override
645 unsigned int i, nargs;
646 type_suffix_index type, result_type;
647 if (!r.check_gp_argument (2, i, nargs)
648 || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
649 || !r.require_integer_immediate (i + 1)
650 || (result_type = long_type_suffix (r, type)) == NUM_TYPE_SUFFIXES)
651 return error_mark_node;
653 if (tree res = r.lookup_form (r.mode_suffix_id, result_type))
654 return res;
656 return r.report_no_such_form (type);
660 /* Base class for binary_za_m and similar shapes. */
661 template<type_class_index TCLASS = function_resolver::SAME_TYPE_CLASS,
662 unsigned int BITS = function_resolver::SAME_SIZE>
663 struct binary_za_m_base : public overloaded_base<1>
665 tree
666 resolve (function_resolver &r) const override
668 type_suffix_index type;
669 if (!r.check_num_arguments (5)
670 || !r.require_integer_immediate (0)
671 || !r.require_vector_type (1, VECTOR_TYPE_svbool_t)
672 || !r.require_vector_type (2, VECTOR_TYPE_svbool_t)
673 || (type = r.infer_vector_type (3)) == NUM_TYPE_SUFFIXES
674 || !r.require_derived_vector_type (4, 3, type, TCLASS, BITS))
675 return error_mark_node;
677 return r.resolve_to (r.mode_suffix_id, r.type_suffix_ids[0], type);
680 bool
681 check (function_checker &c) const override
683 return c.require_immediate_range (0, 0, c.num_za_tiles () - 1);
687 /* Base class for shapes like binary_za_slice_lane. TCLASS is the type
688 class of the final vector argument. */
689 template<type_class_index TCLASS = function_resolver::SAME_TYPE_CLASS>
690 struct binary_za_slice_lane_base : public overloaded_base<1>
692 constexpr binary_za_slice_lane_base (unsigned int lane_type_suffix)
693 : m_lane_type_suffix (lane_type_suffix) {}
695 void
696 build (function_builder &b, const function_group_info &group) const override
698 b.add_overloaded_functions (group, MODE_none);
699 build_all (b, "_,su32,t1,v1,su64", group, MODE_none);
702 tree
703 resolve (function_resolver &r) const override
705 sve_type type;
706 if (!r.check_num_arguments (4)
707 || !r.require_scalar_type (0, "uint32_t")
708 || !(type = r.infer_tuple_type (1))
709 || !r.require_derived_vector_type (2, 1, type, TCLASS)
710 || !r.require_integer_immediate (3))
711 return error_mark_node;
713 return r.resolve_to (r.mode_suffix_id, type);
716 bool
717 check (function_checker &c) const override
719 unsigned int bytes = c.type_suffix (m_lane_type_suffix).element_bytes;
720 return c.require_immediate_range (3, 0, 16 / bytes - 1);
723 unsigned int m_lane_type_suffix;
726 /* Base class for shapes like binary_za_slice_opt_single. TCLASS is the
727 type class of the final argument. */
728 template<type_class_index TCLASS = function_resolver::SAME_TYPE_CLASS>
729 struct binary_za_slice_opt_single_base : public overloaded_base<1>
731 tree
732 resolve (function_resolver &r) const override
734 sve_type type;
735 if (!r.check_num_arguments (3)
736 || !r.require_scalar_type (0, "uint32_t")
737 || !(type = r.infer_tuple_type (1)))
738 return error_mark_node;
740 return r.finish_opt_single_resolution (2, 1, type, TCLASS);
744 /* Base class for ext and extq. */
745 struct ext_base : public overloaded_base<0>
747 void
748 build (function_builder &b, const function_group_info &group) const override
750 b.add_overloaded_functions (group, MODE_none);
751 build_all (b, "v0,v0,v0,su64", group, MODE_none);
754 tree
755 resolve (function_resolver &r) const override
757 return r.resolve_uniform (2, 1);
761 /* Base class for inc_dec and inc_dec_pat. */
762 struct inc_dec_base : public overloaded_base<0>
764 CONSTEXPR inc_dec_base (bool pat_p) : m_pat_p (pat_p) {}
766 /* Resolve based on the first argument only, which must be either a
767 scalar or a vector. If it's a scalar, it must be a 32-bit or
768 64-bit integer. */
769 tree
770 resolve (function_resolver &r) const
772 unsigned int i, nargs;
773 if (!r.check_gp_argument (m_pat_p ? 3 : 2, i, nargs)
774 || !r.require_vector_or_scalar_type (i))
775 return error_mark_node;
777 mode_suffix_index mode;
778 type_suffix_index type;
779 if (r.scalar_argument_p (i))
781 mode = MODE_n;
782 type = r.infer_integer_scalar_type (i);
784 else
786 mode = MODE_none;
787 type = r.infer_vector_type (i);
789 if (type == NUM_TYPE_SUFFIXES)
790 return error_mark_node;
792 for (++i; i < nargs; ++i)
793 if (!r.require_integer_immediate (i))
794 return error_mark_node;
796 return r.resolve_to (mode, type);
799 bool
800 check (function_checker &c) const override
802 return c.require_immediate_range (m_pat_p ? 2 : 1, 1, 16);
805 bool m_pat_p;
808 /* Base class for load and load_replicate. */
809 struct load_contiguous_base : public overloaded_base<0>
811 /* Resolve a call based purely on a pointer argument. The other arguments
812 are a governing predicate and (for MODE_vnum) a vnum offset. */
813 tree
814 resolve (function_resolver &r) const override
816 bool vnum_p = r.mode_suffix_id == MODE_vnum;
817 gcc_assert (r.mode_suffix_id == MODE_none || vnum_p);
819 unsigned int i, nargs;
820 type_suffix_index type;
821 if (!r.check_gp_argument (vnum_p ? 2 : 1, i, nargs)
822 || (type = r.infer_pointer_type (i)) == NUM_TYPE_SUFFIXES
823 || (vnum_p && !r.require_scalar_type (i + 1, "int64_t")))
824 return error_mark_node;
826 return r.resolve_to (r.mode_suffix_id, type, NUM_TYPE_SUFFIXES,
827 r.group_suffix_id);
831 /* Base class for gather loads that take a scalar base and a vector
832 displacement (either an offset or an index). */
833 struct load_gather_sv_base : public overloaded_base<0>
835 tree
836 resolve (function_resolver &r) const override
838 unsigned int i, nargs;
839 mode_suffix_index mode;
840 type_suffix_index type;
841 auto restrictions = get_target_type_restrictions (r);
842 if (!r.check_gp_argument (2, i, nargs)
843 || (type = r.infer_pointer_type (i, true,
844 restrictions)) == NUM_TYPE_SUFFIXES
845 || (mode = r.resolve_sv_displacement (i + 1, type, true),
846 mode == MODE_none))
847 return error_mark_node;
849 return r.resolve_to (mode, type);
852 virtual function_resolver::target_type_restrictions
853 get_target_type_restrictions (const function_instance &) const
855 return function_resolver::TARGET_32_64;
859 /* Base class for load_gather64_sv_index and load_gather64_sv_offset. */
860 struct load_gather64_sv_base : public load_gather_sv_base
862 type_suffix_index
863 vector_base_type (type_suffix_index) const override
865 return TYPE_SUFFIX_u64;
868 function_resolver::target_type_restrictions
869 get_target_type_restrictions (const function_instance &) const override
871 return function_resolver::TARGET_ANY;
875 /* Base class for load_ext_gather_index and load_ext_gather_offset,
876 which differ only in the units of the displacement. */
877 struct load_ext_gather_base : public overloaded_base<1>
879 /* Resolve a gather load that takes one of:
881 - a scalar pointer base and a vector displacement
882 - a vector base with no displacement or
883 - a vector base and a scalar displacement
885 The function has an explicit type suffix that determines the type
886 of the loaded data. */
887 tree
888 resolve (function_resolver &r) const override
890 /* No resolution is needed for a vector base with no displacement;
891 there's a one-to-one mapping between short and long names. */
892 gcc_assert (r.displacement_units () != UNITS_none);
894 type_suffix_index type = r.type_suffix_ids[0];
896 unsigned int i, nargs;
897 mode_suffix_index mode;
898 if (!r.check_gp_argument (2, i, nargs)
899 || (mode = r.resolve_gather_address (i, type, true)) == MODE_none)
900 return error_mark_node;
902 return r.resolve_to (mode, type);
907 /* sv<v0>_t svlut[_<t0>_g](sv<t0>x<g>_t, svuint8_t, uint64_t)
909 where the final argument is a constant index, the instruction divides
910 the vector argument in BITS-bit quantities. */
911 template<unsigned int BITS>
912 struct luti_base : public overloaded_base<0>
914 bool explicit_group_suffix_p () const override { return false; }
916 void
917 build (function_builder &b, const function_group_info &group) const override
919 /* Format: return type, table vector, indices vector, immediate value. */
920 b.add_overloaded_functions (group, MODE_none);
921 build_all (b, "v0,t0,vu8,su64", group, MODE_none);
924 bool
925 check (function_checker &c) const override
927 auto max_range = c.type_suffix (0).element_bits / BITS - 1;
928 return c.require_immediate_range (2, 0, max_range);
931 tree
932 resolve (function_resolver &r) const override
934 sve_type type;
935 if (!r.check_num_arguments (3)
936 || !(type = r.infer_sve_type (0))
937 || !r.require_vector_type (1, VECTOR_TYPE_svuint8_t)
938 || !r.require_scalar_type (2, "uint64_t"))
939 return error_mark_node;
941 return r.resolve_to (r.mode_suffix_id, type);
945 /* Specializations for 2-bit and 4-bit indices. */
946 using luti2_def = luti_base<2>;
947 SHAPE (luti2)
949 using luti4_def = luti_base<4>;
950 SHAPE (luti4)
953 /* sv<t0>x<g>_t svfoo_t0_g(uint64_t, svuint8_t, uint64_t)
955 where the first argument is the ZT register number (currently always 0)
956 and the final argument is a constant index. The instruction divides
957 the vector argument in BITS-bit quantities. */
958 template<unsigned int BITS>
959 struct luti_lane_zt_base : public nonoverloaded_base
961 void
962 build (function_builder &b, const function_group_info &group) const override
964 build_all (b, "t0,su64,vu8,su64", group, MODE_none);
967 bool
968 check (function_checker &c) const override
970 auto nvectors = c.vectors_per_tuple ();
971 return (c.require_immediate_range (0, 0, 0)
972 && c.require_immediate_range (2, 0, 32 / BITS / nvectors - 1));
976 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:quarter>_t,
977 sv<t0:quarter>_t) (for integer t0)
978 sv<t0>_t svmmla[_t0](sv<t0>_t, sv<t0>_t, sv<t0>_t) (for floating-point t0)
980 The functions act like the equivalent of "ternary_qq" for integer elements
981 and normal vector-only ternary functions for floating-point elements. */
982 struct mmla_def : public overloaded_base<0>
984 void
985 build (function_builder &b, const function_group_info &group) const override
987 b.add_overloaded_functions (group, MODE_none);
988 if (type_suffixes[group.types[0][0]].float_p)
989 build_all (b, "v0,v0,v0,v0", group, MODE_none);
990 else
991 build_all (b, "v0,v0,vq0,vq0", group, MODE_none);
994 tree
995 resolve (function_resolver &r) const override
997 unsigned int i, nargs;
998 type_suffix_index type;
999 if (!r.check_gp_argument (3, i, nargs)
1000 || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES)
1001 return error_mark_node;
1003 /* Make sure that the function exists now, since not all forms
1004 follow a set pattern after this point. */
1005 tree res = r.resolve_to (r.mode_suffix_id, type);
1006 if (res == error_mark_node)
1007 return res;
1009 bool float_p = type_suffixes[type].float_p;
1010 unsigned int modifier = float_p ? r.SAME_SIZE : r.QUARTER_SIZE;
1011 if (!r.require_derived_vector_type (i + 1, i, type, r.SAME_TYPE_CLASS,
1012 modifier)
1013 || !r.require_derived_vector_type (i + 2, i, type, r.SAME_TYPE_CLASS,
1014 modifier))
1015 return error_mark_node;
1017 return res;
1020 SHAPE (mmla)
1022 /* Base class for prefetch_gather_index and prefetch_gather_offset,
1023 which differ only in the units of the displacement. */
1024 struct prefetch_gather_base : public overloaded_base<0>
1026 /* Resolve a gather prefetch that takes one of:
1028 - a scalar pointer base (const void *) and a vector displacement
1029 - a vector base with no displacement or
1030 - a vector base and a scalar displacement
1032 The prefetch operation is the final argument. This is purely a
1033 mode-based resolution; there are no type suffixes. */
1034 tree
1035 resolve (function_resolver &r) const override
1037 bool has_displacement_p = r.displacement_units () != UNITS_none;
1039 unsigned int i, nargs;
1040 mode_suffix_index mode;
1041 if (!r.check_gp_argument (has_displacement_p ? 3 : 2, i, nargs)
1042 || (mode = r.resolve_gather_address (i, NUM_TYPE_SUFFIXES,
1043 false)) == MODE_none
1044 || !r.require_integer_immediate (nargs - 1))
1045 return error_mark_node;
1047 return r.resolve_to (mode);
1051 /* Wraps BASE to provide a narrowing shift right function. Argument N
1052 is an immediate shift amount in the range [1, sizeof(<t0>_t) * 4]. */
1053 template<typename BASE, unsigned int N>
1054 struct shift_right_imm_narrow_wrapper : public BASE
1056 bool
1057 check (function_checker &c) const override
1059 unsigned int bits = c.type_suffix (0).element_bits / 2;
1060 return c.require_immediate_range (N, 1, bits);
1064 /* Base class for store_scatter_index and store_scatter_offset,
1065 which differ only in the units of the displacement. */
1066 struct store_scatter_base : public overloaded_base<0>
1068 /* Resolve a scatter store that takes one of:
1070 - a scalar pointer base and a vector displacement
1071 - a vector base with no displacement or
1072 - a vector base and a scalar displacement
1074 The stored data is the final argument, and it determines the
1075 type suffix. */
1076 tree
1077 resolve (function_resolver &r) const override
1079 bool has_displacement_p = r.displacement_units () != UNITS_none;
1081 unsigned int i, nargs;
1082 mode_suffix_index mode;
1083 type_suffix_index type;
1084 if (!r.check_gp_argument (has_displacement_p ? 3 : 2, i, nargs)
1085 || (type = infer_vector_type (r, nargs - 1)) == NUM_TYPE_SUFFIXES
1086 || (mode = r.resolve_gather_address (i, type, false)) == MODE_none)
1087 return error_mark_node;
1089 return r.resolve_to (mode, type);
1092 virtual type_suffix_index
1093 infer_vector_type (function_resolver &r, unsigned int argno) const
1095 return r.infer_sd_vector_type (argno);
1099 /* Base class for store_scatter64_index and store_scatter64_offset. */
1100 struct store_scatter64_base : public store_scatter_base
1102 type_suffix_index
1103 vector_base_type (type_suffix_index) const override
1105 return TYPE_SUFFIX_u64;
1108 type_suffix_index
1109 infer_vector_type (function_resolver &r, unsigned int argno) const override
1111 return r.infer_vector_type (argno);
1115 /* Base class for ternary operations in which the final argument is an
1116 immediate shift amount. The derived class should check the range. */
1117 struct ternary_shift_imm_base : public overloaded_base<0>
1119 void
1120 build (function_builder &b, const function_group_info &group) const override
1122 b.add_overloaded_functions (group, MODE_n);
1123 build_all (b, "v0,v0,v0,su64", group, MODE_n);
1126 tree
1127 resolve (function_resolver &r) const override
1129 return r.resolve_uniform (2, 1);
1133 /* Base class for ternary operations in which the first argument has the
1134 same element type as the result, and in which the second and third
1135 arguments have an element type that is derived the first.
1137 MODIFIER is the number of element bits in the second and third
1138 arguments, or a function_resolver modifier that says how this
1139 precision is derived from the first argument's elements.
1141 TYPE_CLASS2 and TYPE_CLASS3 are the type classes of the second and
1142 third arguments, or function_resolver::SAME_TYPE_CLASS if the type
1143 class is the same as the first argument. */
1144 template<unsigned int MODIFIER,
1145 type_class_index TYPE_CLASS2 = function_resolver::SAME_TYPE_CLASS,
1146 type_class_index TYPE_CLASS3 = function_resolver::SAME_TYPE_CLASS>
1147 struct ternary_resize2_opt_n_base : public overloaded_base<0>
1149 tree
1150 resolve (function_resolver &r) const override
1152 unsigned int i, nargs;
1153 type_suffix_index type;
1154 if (!r.check_gp_argument (3, i, nargs)
1155 || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
1156 || !r.require_derived_vector_type (i + 1, i, type, TYPE_CLASS2,
1157 MODIFIER))
1158 return error_mark_node;
1160 return r.finish_opt_n_resolution (i + 2, i, type, TYPE_CLASS3, MODIFIER);
1164 /* Like ternary_resize2_opt_n_base, but for functions that don't take
1165 a final scalar argument. */
1166 template<unsigned int MODIFIER,
1167 type_class_index TYPE_CLASS2 = function_resolver::SAME_TYPE_CLASS,
1168 type_class_index TYPE_CLASS3 = function_resolver::SAME_TYPE_CLASS>
1169 struct ternary_resize2_base : public overloaded_base<0>
1171 tree
1172 resolve (function_resolver &r) const override
1174 unsigned int i, nargs;
1175 type_suffix_index type;
1176 if (!r.check_gp_argument (3, i, nargs)
1177 || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
1178 || !r.require_derived_vector_type (i + 1, i, type, TYPE_CLASS2,
1179 MODIFIER)
1180 || !r.require_derived_vector_type (i + 2, i, type, TYPE_CLASS3,
1181 MODIFIER))
1182 return error_mark_node;
1184 return r.resolve_to (r.mode_suffix_id, type);
1188 /* Like ternary_resize2_opt_n_base, but for functions that take a final
1189 lane argument. */
1190 template<unsigned int MODIFIER,
1191 type_class_index TYPE_CLASS2 = function_resolver::SAME_TYPE_CLASS,
1192 type_class_index TYPE_CLASS3 = function_resolver::SAME_TYPE_CLASS>
1193 struct ternary_resize2_lane_base : public overloaded_base<0>
1195 tree
1196 resolve (function_resolver &r) const override
1198 unsigned int i, nargs;
1199 type_suffix_index type;
1200 if (!r.check_gp_argument (4, i, nargs)
1201 || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
1202 || !r.require_derived_vector_type (i + 1, i, type, TYPE_CLASS2,
1203 MODIFIER)
1204 || !r.require_derived_vector_type (i + 2, i, type, TYPE_CLASS3,
1205 MODIFIER)
1206 || !r.require_integer_immediate (i + 3))
1207 return error_mark_node;
1209 return r.resolve_to (r.mode_suffix_id, type);
1213 /* A specialization of ternary_resize2_lane_base for bfloat16 elements,
1214 indexed in groups of N elements. */
1215 template<unsigned int N>
1216 struct ternary_bfloat_lane_base
1217 : public ternary_resize2_lane_base<16, TYPE_bfloat, TYPE_bfloat>
1219 void
1220 build (function_builder &b, const function_group_info &group) const override
1222 b.add_overloaded_functions (group, MODE_none);
1223 build_all (b, "v0,v0,vB,vB,su64", group, MODE_none);
1226 bool
1227 check (function_checker &c) const override
1229 return c.require_immediate_lane_index (3, 2, N);
1233 /* A specialization of ternary_resize2_lane_base for quarter-sized
1234 elements. */
1235 template<type_class_index TYPE_CLASS2 = function_resolver::SAME_TYPE_CLASS,
1236 type_class_index TYPE_CLASS3 = function_resolver::SAME_TYPE_CLASS>
1237 struct ternary_qq_lane_base
1238 : public ternary_resize2_lane_base<function_resolver::QUARTER_SIZE,
1239 TYPE_CLASS2, TYPE_CLASS3>
1241 bool
1242 check (function_checker &c) const override
1244 return c.require_immediate_lane_index (3, 0);
1248 /* Base class for narrowing bottom unary functions. The result is half
1249 the size of input and has class CLASS. */
1250 template<type_class_index CLASS = function_resolver::SAME_TYPE_CLASS>
1251 struct unary_narrowb_base : public overloaded_base<0>
1253 void
1254 build (function_builder &b, const function_group_info &group) const override
1256 b.add_overloaded_functions (group, MODE_none);
1257 STATIC_ASSERT (CLASS == function_resolver::SAME_TYPE_CLASS
1258 || CLASS == TYPE_unsigned);
1259 if (CLASS == TYPE_unsigned)
1260 build_all (b, "vhu0,v0", group, MODE_none);
1261 else
1262 build_all (b, "vh0,v0", group, MODE_none);
1265 tree
1266 resolve (function_resolver &r) const override
1268 return r.resolve_unary (CLASS, r.HALF_SIZE);
1272 /* The top equivalent of unary_imm_narrowb_base. All forms take the values
1273 of the even elements as an extra argument, before any governing predicate.
1274 These even elements are typically the result of the narrowb operation. */
1275 template<type_class_index CLASS = function_resolver::SAME_TYPE_CLASS>
1276 struct unary_narrowt_base : public overloaded_base<0>
1278 void
1279 build (function_builder &b, const function_group_info &group) const override
1281 b.add_overloaded_functions (group, MODE_none);
1282 STATIC_ASSERT (CLASS == function_resolver::SAME_TYPE_CLASS
1283 || CLASS == TYPE_unsigned);
1284 if (CLASS == TYPE_unsigned)
1285 build_all (b, "vhu0,vhu0,v0", group, MODE_none);
1286 else
1287 build_all (b, "vh0,vh0,v0", group, MODE_none);
1290 tree
1291 resolve (function_resolver &r) const override
1293 unsigned int i, nargs;
1294 type_suffix_index type;
1295 if (!r.check_gp_argument (2, i, nargs)
1296 || (type = r.infer_vector_type (i + 1)) == NUM_TYPE_SUFFIXES
1297 || !r.require_derived_vector_type (i, i + 1, type, CLASS, r.HALF_SIZE))
1298 return error_mark_node;
1300 return r.resolve_to (r.mode_suffix_id, type);
1304 /* sv<m0>_t svfoo[_m0base]_[m1]index(sv<m0>_t, sv<m1>_t)
1306 for all valid combinations of vector base type <m0> and vector
1307 displacement type <m1>. */
1308 struct adr_index_def : public adr_base
1310 void
1311 build (function_builder &b, const function_group_info &group) const override
1313 b.add_overloaded_functions (group, MODE_index);
1314 build_all (b, "b,b,d", group, MODE_u32base_s32index);
1315 build_all (b, "b,b,d", group, MODE_u32base_u32index);
1316 build_all (b, "b,b,d", group, MODE_u64base_s64index);
1317 build_all (b, "b,b,d", group, MODE_u64base_u64index);
1320 SHAPE (adr_index)
1322 /* sv<m0>_t svfoo[_m0base]_[m1]offset(sv<m0>_t, sv<m1>_t).
1324 for all valid combinations of vector base type <m0> and vector
1325 displacement type <m1>. */
1326 struct adr_offset_def : public adr_base
1328 void
1329 build (function_builder &b, const function_group_info &group) const override
1331 b.add_overloaded_functions (group, MODE_offset);
1332 build_all (b, "b,b,d", group, MODE_u32base_s32offset);
1333 build_all (b, "b,b,d", group, MODE_u32base_u32offset);
1334 build_all (b, "b,b,d", group, MODE_u64base_s64offset);
1335 build_all (b, "b,b,d", group, MODE_u64base_u64offset);
1338 SHAPE (adr_offset)
1340 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0>_t)
1342 i.e. a binary operation with uniform types, but with no scalar form. */
1343 struct binary_def : public overloaded_base<0>
1345 void
1346 build (function_builder &b, const function_group_info &group) const override
1348 b.add_overloaded_functions (group, MODE_none);
1349 build_all (b, "v0,v0,v0", group, MODE_none);
1352 tree
1353 resolve (function_resolver &r) const override
1355 return r.resolve_uniform (2);
1358 SHAPE (binary)
1360 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:int>_t)
1361 sv<t0>_t svfoo[_n_t0](sv<t0>_t, <t0:int>_t).
1363 i.e. a version of the standard binary shape binary_opt_n in which
1364 the final argument is always a signed integer. */
1365 struct binary_int_opt_n_def : public overloaded_base<0>
1367 void
1368 build (function_builder &b, const function_group_info &group) const override
1370 b.add_overloaded_functions (group, MODE_none);
1371 build_all (b, "v0,v0,vs0", group, MODE_none);
1372 build_all (b, "v0,v0,ss0", group, MODE_n);
1375 tree
1376 resolve (function_resolver &r) const override
1378 unsigned int i, nargs;
1379 type_suffix_index type;
1380 if (!r.check_gp_argument (2, i, nargs)
1381 || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES)
1382 return error_mark_node;
1384 return r.finish_opt_n_resolution (i + 1, i, type, TYPE_signed);
1387 SHAPE (binary_int_opt_n)
1389 /* Like binary_int_opt_n for single vectors. For tuples:
1391 sv<t0>x<g>_t svfoo[_t0_g](sv<t0>x<g>_t, sv<t0:int>x<g>_t)
1392 sv<t0>x<g>_t svfoo[_single_t0_g](sv<t0>x<g>_t, sv<t0:int>_t). */
1393 struct binary_int_opt_single_n_def : public overloaded_base<0>
1395 bool explicit_group_suffix_p () const override { return false; }
1397 void
1398 build (function_builder &b, const function_group_info &group) const override
1400 b.add_overloaded_functions (group, MODE_none);
1401 build_all (b, "t0,t0,ts0", group, MODE_none);
1402 if (group.groups[0] == GROUP_none)
1403 build_all (b, "v0,v0,ss0", group, MODE_n);
1404 else
1405 build_all (b, "t0,t0,vs0", group, MODE_single);
1408 tree
1409 resolve (function_resolver &r) const override
1411 unsigned int i, nargs;
1412 sve_type type;
1413 if (!r.check_gp_argument (2, i, nargs)
1414 || !(type = r.infer_sve_type (i)))
1415 return error_mark_node;
1417 return (type.num_vectors == 1 && r.scalar_argument_p (i + 1)
1418 ? r.finish_opt_n_resolution (i + 1, i, type.type, TYPE_signed)
1419 : r.finish_opt_single_resolution (i + 1, i, type, TYPE_signed));
1422 SHAPE (binary_int_opt_single_n)
1424 /* sv<t0>_t svfoo_<t0>(sv<t0>_t, sv<t0>_t, uint64_t)
1426 where the final argument is an integer constant expression in the
1427 range [0, 16 / sizeof (<t0>_t) - 1]. */
1428 struct binary_lane_def : public overloaded_base<0>
1430 void
1431 build (function_builder &b, const function_group_info &group) const override
1433 b.add_overloaded_functions (group, MODE_none);
1434 build_all (b, "v0,v0,v0,su64", group, MODE_none);
1437 tree
1438 resolve (function_resolver &r) const override
1440 return r.resolve_uniform (2, 1);
1443 bool
1444 check (function_checker &c) const override
1446 return c.require_immediate_lane_index (2, 1);
1449 SHAPE (binary_lane)
1451 /* sv<t0>_t svfoo[_t0](sv<t0:half>_t, sv<t0:half>_t, uint64_t).
1453 where the final argument is an integer constant expression in the
1454 range [0, 32 / sizeof (<t0>_t) - 1]. */
1455 struct binary_long_lane_def : public overloaded_base<0>
1457 void
1458 build (function_builder &b, const function_group_info &group) const override
1460 b.add_overloaded_functions (group, MODE_none);
1461 build_all (b, "v0,vh0,vh0,su64", group, MODE_none);
1464 tree
1465 resolve (function_resolver &r) const override
1467 unsigned int i, nargs;
1468 type_suffix_index type, result_type;
1469 if (!r.check_gp_argument (3, i, nargs)
1470 || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
1471 || !r.require_matching_vector_type (i + 1, i, type)
1472 || !r.require_integer_immediate (i + 2)
1473 || (result_type = long_type_suffix (r, type)) == NUM_TYPE_SUFFIXES)
1474 return error_mark_node;
1476 if (tree res = r.lookup_form (r.mode_suffix_id, result_type))
1477 return res;
1479 return r.report_no_such_form (type);
1482 bool
1483 check (function_checker &c) const override
1485 return c.require_immediate_lane_index (2, 1);
1488 SHAPE (binary_long_lane)
1490 /* sv<t0>_t svfoo[_t0](sv<t0:half>_t, sv<t0:half>_t)
1491 sv<t0>_t svfoo[_n_t0](sv<t0:half>_t, <t0:half>_t). */
1492 struct binary_long_opt_n_def : public overloaded_base<0>
1494 void
1495 build (function_builder &b, const function_group_info &group) const override
1497 b.add_overloaded_functions (group, MODE_none);
1498 build_all (b, "v0,vh0,vh0", group, MODE_none);
1499 build_all (b, "v0,vh0,sh0", group, MODE_n);
1502 tree
1503 resolve (function_resolver &r) const override
1505 unsigned int i, nargs;
1506 type_suffix_index type, result_type;
1507 if (!r.check_gp_argument (2, i, nargs)
1508 || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
1509 || (result_type = long_type_suffix (r, type)) == NUM_TYPE_SUFFIXES)
1510 return error_mark_node;
1512 return r.finish_opt_n_resolution (i + 1, i, type, r.SAME_TYPE_CLASS,
1513 r.SAME_SIZE, result_type);
1516 SHAPE (binary_long_opt_n)
1518 /* sv<t0>_t svfoo[_n_t0](sv<t0>_t, <t0>_t).
1520 i.e. a binary operation in which the final argument is always a scalar
1521 rather than a vector. */
1522 struct binary_n_def : public overloaded_base<0>
1524 void
1525 build (function_builder &b, const function_group_info &group) const override
1527 b.add_overloaded_functions (group, MODE_n);
1528 build_all (b, "v0,v0,s0", group, MODE_n);
1531 tree
1532 resolve (function_resolver &r) const override
1534 unsigned int i, nargs;
1535 type_suffix_index type;
1536 if (!r.check_gp_argument (2, i, nargs)
1537 || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
1538 || !r.require_derived_scalar_type (i + 1, r.SAME_TYPE_CLASS))
1539 return error_mark_node;
1541 return r.resolve_to (r.mode_suffix_id, type);
1544 SHAPE (binary_n)
1546 /* sv<t0:half>_t svfoo[_t0](sv<t0>_t, sv<t0>_t)
1547 sv<t0:half>_t svfoo[_n_t0](sv<t0>_t, <t0>_t)
1549 i.e. a version of binary_opt_n in which the output elements are half the
1550 width of the input elements. */
1551 struct binary_narrowb_opt_n_def : public overloaded_base<0>
1553 void
1554 build (function_builder &b, const function_group_info &group) const override
1556 b.add_overloaded_functions (group, MODE_none);
1557 build_all (b, "vh0,v0,v0", group, MODE_none);
1558 build_all (b, "vh0,v0,s0", group, MODE_n);
1561 tree
1562 resolve (function_resolver &r) const override
1564 return r.resolve_uniform_opt_n (2);
1567 SHAPE (binary_narrowb_opt_n)
1569 /* sv<t0:half>_t svfoo[_t0](sv<t0:half>_t, sv<t0>_t, sv<t0>_t)
1570 sv<t0:half>_t svfoo[_n_t0](sv<t0:half>_t, sv<t0>_t, <t0>_t)
1572 This is the "top" counterpart to binary_narrowb_opt_n. */
1573 struct binary_narrowt_opt_n_def : public overloaded_base<0>
1575 void
1576 build (function_builder &b, const function_group_info &group) const override
1578 b.add_overloaded_functions (group, MODE_none);
1579 build_all (b, "vh0,vh0,v0,v0", group, MODE_none);
1580 build_all (b, "vh0,vh0,v0,s0", group, MODE_n);
1583 tree
1584 resolve (function_resolver &r) const override
1586 unsigned int i, nargs;
1587 type_suffix_index type;
1588 if (!r.check_gp_argument (3, i, nargs)
1589 || (type = r.infer_vector_type (i + 1)) == NUM_TYPE_SUFFIXES
1590 || !r.require_derived_vector_type (i, i + 1, type, r.SAME_TYPE_CLASS,
1591 r.HALF_SIZE))
1592 return error_mark_node;
1594 return r.finish_opt_n_resolution (i + 2, i + 1, type);
1597 SHAPE (binary_narrowt_opt_n)
1599 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0>_t)
1600 sv<t0>_t svfoo[_n_t0](sv<t0>_t, <t0>_t)
1602 i.e. the standard shape for binary operations that operate on
1603 uniform types. */
1604 struct binary_opt_n_def : public overloaded_base<0>
1606 void
1607 build (function_builder &b, const function_group_info &group) const override
1609 b.add_overloaded_functions (group, MODE_none);
1610 build_all (b, "v0,v0,v0", group, MODE_none);
1611 /* _b functions do not have an _n form, but are classified as
1612 binary_opt_n so that they can be overloaded with vector
1613 functions. */
1614 if (group.types[0][0] == TYPE_SUFFIX_b)
1615 gcc_assert (group.types[0][1] == NUM_TYPE_SUFFIXES);
1616 else
1617 build_all (b, "v0,v0,s0", group, MODE_n);
1620 tree
1621 resolve (function_resolver &r) const override
1623 return r.resolve_uniform_opt_n (2);
1626 SHAPE (binary_opt_n)
1628 /* Like binary_opt_n for single vectors. For tuples:
1630 sv<t0>x<g>_t svfoo[_t0_g](sv<t0>x<g>_t, sv<t0>x<g>_t)
1631 sv<t0>x<g>_t svfoo[_single_t0_g](sv<t0>x<g>_t, sv<t0>_t). */
1632 struct binary_opt_single_n_def : public overloaded_base<0>
1634 bool explicit_group_suffix_p () const override { return false; }
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, "t0,t0,t0", group, MODE_none);
1641 if (group.groups[0] == GROUP_none)
1642 build_all (b, "v0,v0,s0", group, MODE_n);
1643 else
1644 build_all (b, "t0,t0,v0", group, MODE_single);
1647 tree
1648 resolve (function_resolver &r) const override
1650 unsigned int i, nargs;
1651 sve_type type;
1652 if (!r.check_gp_argument (2, i, nargs)
1653 || !(type = r.infer_sve_type (i)))
1654 return error_mark_node;
1656 return (type.num_vectors == 1 && r.scalar_argument_p (i + 1)
1657 ? r.finish_opt_n_resolution (i + 1, i, type.type)
1658 : r.finish_opt_single_resolution (i + 1, i, type));
1661 SHAPE (binary_opt_single_n)
1663 /* svbool_t svfoo(svbool_t, svbool_t). */
1664 struct binary_pred_def : public nonoverloaded_base
1666 void
1667 build (function_builder &b, const function_group_info &group) const override
1669 build_all (b, "v0,v0,v0", group, MODE_none);
1672 SHAPE (binary_pred)
1674 /* sv<t0>_t svfoo[_<t0>](sv<t0>_t, sv<t0>_t, uint64_t)
1676 where the final argument must be 90 or 270. */
1677 struct binary_rotate_def : public overloaded_base<0>
1679 void
1680 build (function_builder &b, const function_group_info &group) const override
1682 b.add_overloaded_functions (group, MODE_none);
1683 build_all (b, "v0,v0,v0,su64", group, MODE_none);
1686 tree
1687 resolve (function_resolver &r) const override
1689 return r.resolve_uniform (2, 1);
1692 bool
1693 check (function_checker &c) const override
1695 return c.require_immediate_either_or (2, 90, 270);
1698 SHAPE (binary_rotate)
1700 /* sv<t0>_t svfoo_t0(<t0>_t, <t0>_t)
1702 i.e. a binary function that takes two scalars and returns a vector.
1703 An explicit type suffix is required. */
1704 struct binary_scalar_def : public nonoverloaded_base
1706 void
1707 build (function_builder &b, const function_group_info &group) const override
1709 build_all (b, "v0,s0,s0", group, MODE_none);
1712 SHAPE (binary_scalar)
1714 /* sv<t0>x<g>_t svfoo[_single_t0_g](sv<t0>x<g>_t, sv<t0>_t). */
1715 struct binary_single_def : public overloaded_base<0>
1717 bool explicit_group_suffix_p () const override { return false; }
1719 void
1720 build (function_builder &b, const function_group_info &group) const override
1722 b.add_overloaded_functions (group, MODE_none);
1723 build_all (b, "t0,t0,v0", group, MODE_single);
1726 tree
1727 resolve (function_resolver &r) const override
1729 sve_type type;
1730 if (!r.check_num_arguments (2)
1731 || !(type = r.infer_sve_type (0))
1732 || !r.require_derived_vector_type (1, 0, type, r.SAME_TYPE_CLASS,
1733 r.SAME_SIZE, 1))
1734 return error_mark_node;
1736 return r.resolve_to (MODE_single, type);
1739 SHAPE (binary_single)
1741 /* sv<t0:uint>_t svfoo[_t0](sv<t0>_t, sv<t0>_t).
1743 i.e. a version of "binary" that returns unsigned integers. */
1744 struct binary_to_uint_def : public overloaded_base<0>
1746 void
1747 build (function_builder &b, const function_group_info &group) const override
1749 b.add_overloaded_functions (group, MODE_none);
1750 build_all (b, "vu0,v0,v0", group, MODE_none);
1753 tree
1754 resolve (function_resolver &r) const override
1756 return r.resolve_uniform (2);
1759 SHAPE (binary_to_uint)
1761 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:uint>_t)
1763 i.e. a version of "binary" in which the final argument is always an
1764 unsigned integer. */
1765 struct binary_uint_def : public overloaded_base<0>
1767 void
1768 build (function_builder &b, const function_group_info &group) const override
1770 b.add_overloaded_functions (group, MODE_none);
1771 build_all (b, "v0,v0,vu0", group, MODE_none);
1774 tree
1775 resolve (function_resolver &r) const override
1777 unsigned int i, nargs;
1778 type_suffix_index type;
1779 if (!r.check_gp_argument (2, i, nargs)
1780 || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
1781 || !r.require_derived_vector_type (i + 1, i, type, TYPE_unsigned))
1782 return error_mark_node;
1784 return r.resolve_to (r.mode_suffix_id, type);
1787 SHAPE (binary_uint)
1789 /* sv<t0>_t svfoo[_t0](sv<t0>_t, <t0:uint>_t)
1791 i.e. a version of binary_n in which the final argument is always an
1792 unsigned integer. */
1793 struct binary_uint_n_def : public overloaded_base<0>
1795 void
1796 build (function_builder &b, const function_group_info &group) const override
1798 b.add_overloaded_functions (group, MODE_none);
1799 build_all (b, "v0,v0,su0", group, MODE_none);
1802 tree
1803 resolve (function_resolver &r) const override
1805 unsigned int i, nargs;
1806 type_suffix_index type;
1807 if (!r.check_gp_argument (2, i, nargs)
1808 || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
1809 || !r.require_derived_scalar_type (i + 1, TYPE_unsigned))
1810 return error_mark_node;
1812 return r.resolve_to (r.mode_suffix_id, type);
1815 SHAPE (binary_uint_n)
1817 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:uint>_t)
1818 sv<t0>_t svfoo[_n_t0](sv<t0>_t, <t0:uint>_t)
1820 i.e. a version of the standard binary shape binary_opt_n in which
1821 the final argument is always an unsigned integer. */
1822 struct binary_uint_opt_n_def : public overloaded_base<0>
1824 void
1825 build (function_builder &b, const function_group_info &group) const override
1827 b.add_overloaded_functions (group, MODE_none);
1828 build_all (b, "v0,v0,vu0", group, MODE_none);
1829 build_all (b, "v0,v0,su0", group, MODE_n);
1832 tree
1833 resolve (function_resolver &r) const override
1835 unsigned int i, nargs;
1836 type_suffix_index type;
1837 if (!r.check_gp_argument (2, i, nargs)
1838 || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES)
1839 return error_mark_node;
1841 return r.finish_opt_n_resolution (i + 1, i, type, TYPE_unsigned);
1844 SHAPE (binary_uint_opt_n)
1846 /* sv<t0>_t svfoo[_t0](sv<t0>_t, uint64_t).
1848 i.e. a version of binary_n in which the final argument is always
1849 a 64-bit unsigned integer. */
1850 struct binary_uint64_n_def : public overloaded_base<0>
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, "v0,v0,su64", group, MODE_none);
1859 tree
1860 resolve (function_resolver &r) const override
1862 unsigned int i, nargs;
1863 type_suffix_index type;
1864 if (!r.check_gp_argument (2, i, nargs)
1865 || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
1866 || !r.require_scalar_type (i + 1, "uint64_t"))
1867 return error_mark_node;
1869 return r.resolve_to (r.mode_suffix_id, type);
1872 SHAPE (binary_uint64_n)
1874 /* sv<t0>_t svfoo[_t0](sv<t0>_t, svuint64_t)
1875 sv<t0>_t svfoo[_n_t0](sv<t0>_t, uint64_t)
1877 i.e. a version of the standard binary shape binary_opt_n in which
1878 the final argument is always a uint64_t. */
1879 struct binary_uint64_opt_n_def : public overloaded_base<0>
1881 void
1882 build (function_builder &b, const function_group_info &group) const override
1884 b.add_overloaded_functions (group, MODE_none);
1885 build_all (b, "v0,v0,vu64", group, MODE_none);
1886 build_all (b, "v0,v0,su64", group, MODE_n);
1889 tree
1890 resolve (function_resolver &r) const override
1892 unsigned int i, nargs;
1893 type_suffix_index type;
1894 if (!r.check_gp_argument (2, i, nargs)
1895 || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES)
1896 return error_mark_node;
1898 return r.finish_opt_n_resolution (i + 1, i, type, TYPE_unsigned, 64);
1901 SHAPE (binary_uint64_opt_n)
1903 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:half>_t). */
1904 struct binary_wide_def : public overloaded_base<0>
1906 void
1907 build (function_builder &b, const function_group_info &group) const override
1909 b.add_overloaded_functions (group, MODE_none);
1910 build_all (b, "v0,v0,vh0", group, MODE_none);
1913 tree
1914 resolve (function_resolver &r) const override
1916 unsigned int i, nargs;
1917 type_suffix_index type;
1918 if (!r.check_gp_argument (2, i, nargs)
1919 || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
1920 || !r.require_derived_vector_type (i + 1, i, type, r.SAME_TYPE_CLASS,
1921 r.HALF_SIZE))
1922 return error_mark_node;
1924 return r.resolve_to (r.mode_suffix_id, type);
1927 SHAPE (binary_wide)
1929 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:half>_t)
1930 sv<t0>_t svfoo[_n_t0](sv<t0>_t, <t0:half>_t). */
1931 struct binary_wide_opt_n_def : public overloaded_base<0>
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, "v0,v0,vh0", group, MODE_none);
1938 build_all (b, "v0,v0,sh0", group, MODE_n);
1941 tree
1942 resolve (function_resolver &r) const override
1944 unsigned int i, nargs;
1945 type_suffix_index type;
1946 if (!r.check_gp_argument (2, i, nargs)
1947 || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES)
1948 return error_mark_node;
1950 return r.finish_opt_n_resolution (i + 1, i, type, r.SAME_TYPE_CLASS,
1951 r.HALF_SIZE);
1954 SHAPE (binary_wide_opt_n)
1956 /* void svfoo_t0[_t1]_g(uint64_t, svbool_t, svbool_t, sv<t1>x<g>_t,
1957 sv<t1:int>x<g>_t)
1959 where the first argument is a ZA tile. */
1960 struct binary_za_int_m_def : public binary_za_m_base<TYPE_signed>
1962 void
1963 build (function_builder &b, const function_group_info &group) const override
1965 b.add_overloaded_functions (group, MODE_none);
1966 build_all (b, "_,su64,vp,vp,t1,ts1", group, MODE_none);
1969 SHAPE (binary_za_int_m)
1971 /* void svfoo_t0[_t1]_g(uint64_t, svbool_t, svbool_t, sv<t1>x<g>_t,
1972 sv<t1>x<g>_t)
1974 where the first argument is a ZA tile. */
1975 struct binary_za_m_def : public binary_za_m_base<>
1977 void
1978 build (function_builder &b, const function_group_info &group) const override
1980 b.add_overloaded_functions (group, MODE_none);
1981 /* Allow the overloaded form to be specified seperately, with just
1982 a single suffix. This is necessary for the 64-bit SME MOP intrinsics,
1983 which have some forms dependent on FEAT_SME_I16I64 and some forms
1984 dependent on FEAT_SME_F64F64. The resolver needs to be defined
1985 for base SME. */
1986 if (group.types[0][1] != NUM_TYPE_SUFFIXES)
1987 build_all (b, "_,su64,vp,vp,t1,t1", group, MODE_none);
1990 SHAPE (binary_za_m)
1992 /* void svfoo_lane_t0[_t1]_g(uint32_t, sv<t1>x<g>_t, sv<t1>_t, uint64_t)
1994 where the first argument is a variable ZA slice and the final argument
1995 indexes a single element in the preceding vector argument. */
1996 struct binary_za_slice_lane_def : public binary_za_slice_lane_base<>
1998 constexpr binary_za_slice_lane_def () : binary_za_slice_lane_base<> (1) {}
2000 SHAPE (binary_za_slice_lane)
2002 /* void svfoo_t0[_t1]_g(uint32_t, sv<t1>x<g>_t, sv<t1:int>x<g>_t)
2003 void svfoo[_single]_t0[_t1]_g(uint32_t, sv<t1>x<g>_t, sv<t1:int>_t).
2005 where the first argument is a variable ZA slice. */
2006 struct binary_za_slice_int_opt_single_def
2007 : public binary_za_slice_opt_single_base<TYPE_signed>
2009 void
2010 build (function_builder &b, const function_group_info &group) const override
2012 b.add_overloaded_functions (group, MODE_none);
2013 build_all (b, "_,su32,t1,ts1", group, MODE_none);
2014 build_all (b, "_,su32,t1,vs1", group, MODE_single);
2017 SHAPE (binary_za_slice_int_opt_single)
2019 /* void svfoo_t0[_t1]_g(uint32_t, sv<t1>x<g>_t, sv<t1>x<g>_t)
2020 void svfoo[_single]_t0[_t1]_g(uint32_t, sv<t1>x<g>_t, sv<t1>_t)
2022 where the first argument is a variable ZA slice. */
2023 struct binary_za_slice_opt_single_def
2024 : public binary_za_slice_opt_single_base<>
2026 void
2027 build (function_builder &b, const function_group_info &group) const override
2029 b.add_overloaded_functions (group, MODE_none);
2030 build_all (b, "_,su32,t1,t1", group, MODE_none);
2031 build_all (b, "_,su32,t1,v1", group, MODE_single);
2034 SHAPE (binary_za_slice_opt_single)
2036 /* void svfoo_t0[_t1]_g(uint32_t, sv<t1>x<g>_t, sv<t1:uint>x<g>_t)
2037 void svfoo[_single]_t0[_t1]_g(uint32_t, sv<t1>x<g>_t, sv<t1:uint>_t)
2039 where the first argument is a variable ZA slice. */
2040 struct binary_za_slice_uint_opt_single_def
2041 : public binary_za_slice_opt_single_base<TYPE_unsigned>
2043 void
2044 build (function_builder &b, const function_group_info &group) const override
2046 b.add_overloaded_functions (group, MODE_none);
2047 build_all (b, "_,su32,t1,tu1", group, MODE_none);
2048 build_all (b, "_,su32,t1,vu1", group, MODE_single);
2051 SHAPE (binary_za_slice_uint_opt_single)
2053 /* void svfoo_t0[_t1]_g(uint64_t, svbool_t, svbool_t, sv<t1>x<g>_t,
2054 sv<t1:uint>x<g>_t)
2056 where the first argument is a ZA tile. */
2057 struct binary_za_uint_m_def : public binary_za_m_base<TYPE_unsigned>
2059 void
2060 build (function_builder &b, const function_group_info &group) const override
2062 b.add_overloaded_functions (group, MODE_none);
2063 build_all (b, "_,su64,vp,vp,t1,tu1", group, MODE_none);
2066 SHAPE (binary_za_uint_m)
2068 /* sv<t0>x<g>_t svfoo[_t0_t1_g](sv<t0>x<g>_t, sv<t0>x<g>_t). */
2069 struct binaryxn_def : public overloaded_base<0>
2071 bool explicit_group_suffix_p () const override { return false; }
2073 void
2074 build (function_builder &b, const function_group_info &group) const override
2076 b.add_overloaded_functions (group, MODE_none);
2077 build_all (b, "t0,t0,t0", group, MODE_none);
2080 tree
2081 resolve (function_resolver &r) const override
2083 vector_type_index pred_type;
2084 sve_type type;
2085 if (!r.check_num_arguments (3)
2086 || (pred_type = r.infer_predicate_type (0)) == NUM_VECTOR_TYPES
2087 || !(type = r.infer_sve_type (1))
2088 || !r.require_matching_predicate_type (pred_type, type)
2089 || !r.require_matching_vector_type (2, 1, type))
2090 return error_mark_node;
2092 return r.resolve_to (r.mode_suffix_id, type);
2095 SHAPE (binaryxn)
2097 /* bool svfoo(). */
2098 struct bool_inherent_def : public nonoverloaded_base
2100 void
2101 build (function_builder &b, const function_group_info &group) const override
2103 build_all (b, "sp", group, MODE_none);
2106 SHAPE (bool_inherent)
2108 /* Either:
2110 sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0>_t, sv<t0>_t)
2112 for single vectors or:
2114 sv<t0>x<g>_t svfoo[_single_t0_g](sv<t0>x<g>_t, sv<t0>_t, sv<t0>_t)
2116 for tuples. */
2117 struct clamp_def : public overloaded_base<0>
2119 bool explicit_group_suffix_p () const override { return false; }
2121 void
2122 build (function_builder &b, const function_group_info &group) const override
2124 b.add_overloaded_functions (group, MODE_none);
2125 build_all (b, "t0,t0,v0,v0", group,
2126 group.groups[0] == GROUP_none ? MODE_none : MODE_single);
2129 tree
2130 resolve (function_resolver &r) const override
2132 sve_type type;
2133 if (!r.check_num_arguments (3)
2134 || !(type = r.infer_sve_type (0))
2135 || !r.require_derived_vector_type (1, 0, type, r.SAME_TYPE_CLASS,
2136 r.SAME_SIZE, 1)
2137 || !r.require_derived_vector_type (2, 0, type, r.SAME_TYPE_CLASS,
2138 r.SAME_SIZE, 1))
2139 return error_mark_node;
2141 auto mode = type.num_vectors == 1 ? MODE_none : MODE_single;
2142 return r.resolve_to (mode, type);
2145 SHAPE (clamp)
2147 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0>_t)
2148 <t0>_t svfoo[_n_t0](<t0>_t, sv<t0>_t). */
2149 struct clast_def : public overloaded_base<0>
2151 void
2152 build (function_builder &b, const function_group_info &group) const override
2154 b.add_overloaded_functions (group, MODE_none);
2155 build_all (b, "v0,v0,v0", group, MODE_none);
2156 build_all (b, "s0,s0,v0", group, MODE_n);
2159 tree
2160 resolve (function_resolver &r) const override
2162 unsigned int i, nargs;
2163 if (!r.check_gp_argument (2, i, nargs)
2164 || !r.require_vector_or_scalar_type (i))
2165 return error_mark_node;
2167 if (r.scalar_argument_p (i))
2169 type_suffix_index type;
2170 if (!r.require_derived_scalar_type (i, r.SAME_TYPE_CLASS)
2171 || (type = r.infer_vector_type (i + 1)) == NUM_TYPE_SUFFIXES)
2172 return error_mark_node;
2173 return r.resolve_to (MODE_n, type);
2175 else
2177 type_suffix_index type;
2178 if ((type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
2179 || !r.require_matching_vector_type (i + 1, i, type))
2180 return error_mark_node;
2181 return r.resolve_to (MODE_none, type);
2185 SHAPE (clast)
2187 /* svbool_t svfoo[_t0](sv<t0>_t, sv<t0>_t). */
2188 struct compare_def : public overloaded_base<0>
2190 void
2191 build (function_builder &b, const function_group_info &group) const override
2193 b.add_overloaded_functions (group, MODE_none);
2194 build_all (b, "vp,v0,v0", group, MODE_none);
2197 tree
2198 resolve (function_resolver &r) const override
2200 return r.resolve_uniform (2);
2203 SHAPE (compare)
2205 /* svbool_t svfoo[_t0](sv<t0>_t, sv<t0>_t)
2206 svbool_t svfoo[_n_t0](sv<t0>_t, <t0>_t)
2208 i.e. a comparison between two vectors, or between a vector and a scalar. */
2209 struct compare_opt_n_def : public overloaded_base<0>
2211 void
2212 build (function_builder &b, const function_group_info &group) const override
2214 b.add_overloaded_functions (group, MODE_none);
2215 build_all (b, "vp,v0,v0", group, MODE_none);
2216 build_all (b, "vp,v0,s0", group, MODE_n);
2219 tree
2220 resolve (function_resolver &r) const override
2222 return r.resolve_uniform_opt_n (2);
2225 SHAPE (compare_opt_n)
2227 /* svbool_t svfoo[_t0](const <t0>_t *, const <t0>_t *). */
2228 struct compare_ptr_def : public overloaded_base<0>
2230 void
2231 build (function_builder &b, const function_group_info &group) const override
2233 b.add_overloaded_functions (group, MODE_none);
2234 build_all (b, "vp,al,al", group, MODE_none);
2237 tree
2238 resolve (function_resolver &r) const override
2240 unsigned int i, nargs;
2241 type_suffix_index type;
2242 if (!r.check_gp_argument (2, i, nargs)
2243 || (type = r.infer_pointer_type (i)) == NUM_TYPE_SUFFIXES
2244 || !r.require_matching_pointer_type (i + 1, i, type))
2245 return error_mark_node;
2247 return r.resolve_to (r.mode_suffix_id, type);
2250 SHAPE (compare_ptr)
2252 /* svboolx<g>_t svfoo_t0[_t1]_g(<t1>_t, <t1>_t)
2254 where _t0 is a _b<bits> suffix that describes the predicate result.
2255 There is no direct relationship between the element sizes of _t0
2256 and _t1. */
2257 struct compare_scalar_def : public overloaded_base<1>
2259 void
2260 build (function_builder &b, const function_group_info &group) const override
2262 b.add_overloaded_functions (group, MODE_none);
2263 build_all (b, "tp,s1,s1", group, MODE_none);
2266 tree
2267 resolve (function_resolver &r) const override
2269 unsigned int i, nargs;
2270 type_suffix_index type;
2271 if (!r.check_gp_argument (2, i, nargs)
2272 || (type = r.infer_integer_scalar_type (i)) == NUM_TYPE_SUFFIXES
2273 || !r.require_matching_integer_scalar_type (i + 1, i, type))
2274 return error_mark_node;
2276 return r.resolve_to (r.mode_suffix_id, r.type_suffix_ids[0], type,
2277 r.group_suffix_id);
2280 SHAPE (compare_scalar)
2282 /* svcount_t svfoo_t0[_t1](<t1>_t, <t1>_t, uint64_t)
2284 where _t0 is a _c<bits> suffix that describes the predicate-as-counter
2285 result. The final argument is an integer constant that specifies the
2286 number of vectors (2 or 4). */
2287 struct compare_scalar_count_def : public overloaded_base<1>
2289 void
2290 build (function_builder &b, const function_group_info &group) const override
2292 b.add_overloaded_functions (group, MODE_none);
2293 build_all (b, "v0,s1,s1,su64", group, MODE_none);
2296 tree
2297 resolve (function_resolver &r) const override
2299 unsigned int i, nargs;
2300 type_suffix_index type;
2301 if (!r.check_gp_argument (3, i, nargs)
2302 || (type = r.infer_64bit_scalar_integer_pair (i)) == NUM_TYPE_SUFFIXES
2303 || !r.require_integer_immediate (i + 2))
2304 return error_mark_node;
2306 return r.resolve_to (r.mode_suffix_id, r.type_suffix_ids[0], type);
2309 bool
2310 check (function_checker &c) const override
2312 return c.require_immediate_either_or (2, 2, 4);
2315 SHAPE (compare_scalar_count)
2317 /* svbool_t svfoo[_t0](sv<t0>_t, svint64_t) (for signed t0)
2318 svbool_t svfoo[_n_t0](sv<t0>_t, int64_t) (for signed t0)
2319 svbool_t svfoo[_t0](sv<t0>_t, svuint64_t) (for unsigned t0)
2320 svbool_t svfoo[_n_t0](sv<t0>_t, uint64_t) (for unsigned t0)
2322 i.e. a comparison in which the second argument is 64 bits. */
2323 struct compare_wide_opt_n_def : public overloaded_base<0>
2325 void
2326 build (function_builder &b, const function_group_info &group) const override
2328 b.add_overloaded_functions (group, MODE_none);
2329 build_all (b, "vp,v0,vw0", group, MODE_none);
2330 build_all (b, "vp,v0,sw0", group, MODE_n);
2333 tree
2334 resolve (function_resolver &r) const override
2336 unsigned int i, nargs;
2337 type_suffix_index type;
2338 if (!r.check_gp_argument (2, i, nargs)
2339 || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES)
2340 return error_mark_node;
2342 return r.finish_opt_n_resolution (i + 1, i, type, r.SAME_TYPE_CLASS, 64);
2345 SHAPE (compare_wide_opt_n)
2347 /* uint64_t svfoo(). */
2348 struct count_inherent_def : public nonoverloaded_base
2350 void
2351 build (function_builder &b, const function_group_info &group) const override
2353 build_all (b, "su64", group, MODE_none);
2356 SHAPE (count_inherent)
2358 /* uint64_t svfoo(enum svpattern). */
2359 struct count_pat_def : public nonoverloaded_base
2361 void
2362 build (function_builder &b, const function_group_info &group) const override
2364 build_all (b, "su64,epattern", group, MODE_none);
2367 SHAPE (count_pat)
2369 /* uint64_t svfoo(svbool_t). */
2370 struct count_pred_def : public nonoverloaded_base
2372 void
2373 build (function_builder &b, const function_group_info &group) const override
2375 build_all (b, "su64,vp", group, MODE_none);
2378 SHAPE (count_pred)
2380 /* uint64_t svfoo_t0(sv<t0>_t, uint64_t)
2382 where the final argument must be 2 or 4. */
2383 struct count_pred_c_def : public nonoverloaded_base
2385 void
2386 build (function_builder &b, const function_group_info &group) const override
2388 build_all (b, "su64,v0,su64", group, MODE_none);
2391 bool
2392 check (function_checker &c) const override
2394 return c.require_immediate_either_or (1, 2, 4);
2397 SHAPE (count_pred_c)
2399 /* uint64_t svfoo[_t0](sv<t0>_t). */
2400 struct count_vector_def : public overloaded_base<0>
2402 void
2403 build (function_builder &b, const function_group_info &group) const override
2405 b.add_overloaded_functions (group, MODE_none);
2406 build_all (b, "su64,v0", group, MODE_none);
2409 tree
2410 resolve (function_resolver &r) const override
2412 return r.resolve_uniform (1);
2415 SHAPE (count_vector)
2417 /* sv<t0>xN_t svfoo[_t0](sv<t0>_t, ..., sv<t0>_t)
2419 where there are N arguments in total. */
2420 struct create_def : public overloaded_base<0>
2422 void
2423 build (function_builder &b, const function_group_info &group) const override
2425 b.add_overloaded_functions (group, MODE_none);
2426 build_all (b, "t0,v0*t", group, MODE_none);
2429 tree
2430 resolve (function_resolver &r) const override
2432 return r.resolve_uniform (r.vectors_per_tuple ());
2435 SHAPE (create)
2437 /* void svfoo_lane_t0[_t1]_g(uint32_t, sv<t1>x<g>_t, sv<t1:int>_t, uint64_t)
2439 where the final argument indexes a <t0>-sized group of elements in the
2440 preceding vector argument. */
2441 struct dot_za_slice_int_lane_def
2442 : public binary_za_slice_lane_base<TYPE_signed>
2444 constexpr dot_za_slice_int_lane_def ()
2445 : binary_za_slice_lane_base<TYPE_signed> (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, "_,su32,t1,vs1,su64", group, MODE_none);
2454 SHAPE (dot_za_slice_int_lane)
2456 /* void svfoo_lane_t0[_t1]_g(uint32_t, sv<t1>x<g>_t, sv<t1>_t, uint64_t)
2458 where the final argument indexes a <t0>-sized group of elements in the
2459 preceding vector argument. */
2460 struct dot_za_slice_lane_def : public binary_za_slice_lane_base<>
2462 constexpr dot_za_slice_lane_def () : binary_za_slice_lane_base<> (0) {}
2464 SHAPE (dot_za_slice_lane)
2466 /* void svfoo_lane_t0[_t1]_g(uint32_t, sv<t1>x<g>_t, sv<t1:uint>_t, uint64_t)
2468 where the final argument indexes a <t0>-sized group of elements in the
2469 preceding vector argument. */
2470 struct dot_za_slice_uint_lane_def
2471 : public binary_za_slice_lane_base<TYPE_unsigned>
2473 constexpr dot_za_slice_uint_lane_def ()
2474 : binary_za_slice_lane_base<TYPE_unsigned> (0) {}
2476 void
2477 build (function_builder &b, const function_group_info &group) const override
2479 b.add_overloaded_functions (group, MODE_none);
2480 build_all (b, "_,su32,t1,vu1,su64", group, MODE_none);
2483 SHAPE (dot_za_slice_uint_lane)
2485 /* sv<t0>_t svfoo[_n]_t0(<t0>_t, ..., <t0>_t)
2487 where there are enough arguments to fill 128 bits of data (or to
2488 control 128 bits of data in the case of predicates). */
2489 struct dupq_def : public overloaded_base<1>
2491 void
2492 build (function_builder &b, const function_group_info &group) const override
2494 /* The "_n" suffix is optional; the full name has it, but the short
2495 name doesn't. */
2496 build_all (b, "v0,s0*q", group, MODE_n, true);
2499 tree
2500 resolve (function_resolver &) const override
2502 /* The short forms just make "_n" implicit, so no resolution is needed. */
2503 gcc_unreachable ();
2506 SHAPE (dupq)
2508 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0>_t, uint64_t)
2510 where the final argument is an integer constant expression that when
2511 multiplied by the number of bytes in t0 is in the range [0, 255]. */
2512 struct ext_def : public ext_base
2514 bool
2515 check (function_checker &c) const override
2517 unsigned int bytes = c.type_suffix (0).element_bytes;
2518 return c.require_immediate_range (2, 0, 256 / bytes - 1);
2521 SHAPE (ext)
2523 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0>_t, uint64_t)
2525 where the final argument is an integer constant expression that when
2526 multiplied by the number of bytes in t0 is in the range [0, 15]. */
2527 struct extq_def : public ext_base
2529 bool
2530 check (function_checker &c) const override
2532 unsigned int bytes = c.type_suffix (0).element_bytes;
2533 return c.require_immediate_range (2, 0, 16 / bytes - 1);
2536 SHAPE (extq)
2538 /* svboolx<g>_t svfoo_t0_g(sv<t0>_t, sv<t0>_t, uint32_t). */
2539 struct extract_pred_def : public nonoverloaded_base
2541 void
2542 build (function_builder &b, const function_group_info &group) const override
2544 build_all (b, "tp,vc,su64", group, MODE_none);
2547 bool
2548 check (function_checker &c) const override
2550 unsigned int size = c.vectors_per_tuple ();
2551 return c.require_immediate_range (1, 0, 4 / size - 1);
2554 SHAPE (extract_pred)
2556 /* <t0>_t svfoo[_t0](<t0>_t, sv<t0>_t). */
2557 struct fold_left_def : public overloaded_base<0>
2559 void
2560 build (function_builder &b, const function_group_info &group) const override
2562 b.add_overloaded_functions (group, MODE_none);
2563 build_all (b, "s0,s0,v0", group, MODE_none);
2566 tree
2567 resolve (function_resolver &r) const override
2569 unsigned int i, nargs;
2570 type_suffix_index type;
2571 if (!r.check_gp_argument (2, i, nargs)
2572 || !r.require_derived_scalar_type (i, r.SAME_TYPE_CLASS)
2573 || (type = r.infer_vector_type (i + 1)) == NUM_TYPE_SUFFIXES)
2574 return error_mark_node;
2576 return r.resolve_to (r.mode_suffix_id, type);
2579 SHAPE (fold_left)
2581 /* sv<t0>_t svfoo[_t0](sv<t0>xN_t, uint64_t)
2583 where the final argument is an integer constant expression in
2584 the range [0, N - 1]. */
2585 struct get_def : public overloaded_base<0>
2587 void
2588 build (function_builder &b, const function_group_info &group) const override
2590 b.add_overloaded_functions (group, MODE_none);
2591 build_all (b, "v0,t0,su64", group, MODE_none);
2594 tree
2595 resolve (function_resolver &r) const override
2597 unsigned int i, nargs;
2598 sve_type type;
2599 if (!r.check_gp_argument (2, i, nargs)
2600 || !(type = r.infer_tuple_type (i))
2601 || !r.require_integer_immediate (i + 1))
2602 return error_mark_node;
2604 return r.resolve_to (r.mode_suffix_id, type);
2607 bool
2608 check (function_checker &c) const override
2610 unsigned int nvectors = c.vectors_per_tuple ();
2611 return c.require_immediate_range (1, 0, nvectors - 1);
2614 SHAPE (get)
2616 /* <t0>xN_t svfoo[_t0](sv<t0>_t). */
2617 struct get_neonq_def : public overloaded_base<0>
2619 void
2620 build (function_builder &b, const function_group_info &group) const override
2622 b.add_overloaded_functions (group, MODE_none);
2623 build_all (b, "Q0,v0", group, MODE_none);
2625 tree
2626 resolve (function_resolver &r) const override
2628 return r.resolve_unary ();
2631 SHAPE (get_neonq)
2633 /* sv<t0>_t svfoo[_t0](sv<t0>_t, <t0>xN_t). */
2634 struct set_neonq_def : public overloaded_base<0>
2636 void
2637 build (function_builder &b, const function_group_info &group) const override
2639 b.add_overloaded_functions (group, MODE_none);
2640 build_all (b, "v0,v0,Q0", group, MODE_none);
2642 tree
2643 resolve (function_resolver &r) const override
2645 unsigned int i, nargs;
2646 type_suffix_index type;
2647 if (!r.check_gp_argument (2, i, nargs)
2648 || (type = r.infer_neon128_vector_type (i + 1)) == NUM_TYPE_SUFFIXES)
2649 return error_mark_node;
2650 return r.resolve_to (r.mode_suffix_id, type);
2653 SHAPE (set_neonq)
2655 /* sv<t0>_t svfoo[_t0](<t0>xN_t). */
2656 struct dup_neonq_def : public overloaded_base<0>
2658 void
2659 build (function_builder &b, const function_group_info &group) const override
2661 b.add_overloaded_functions (group, MODE_none);
2662 build_all (b, "v0,Q0", group, MODE_none);
2664 tree
2665 resolve (function_resolver &r) const override
2667 unsigned int i, nargs;
2668 type_suffix_index type;
2669 if (!r.check_gp_argument (1, i, nargs)
2670 || (type = r.infer_neon128_vector_type (i)) == NUM_TYPE_SUFFIXES)
2671 return error_mark_node;
2672 return r.resolve_to (r.mode_suffix_id, type);
2675 SHAPE (dup_neonq)
2677 /* sv<t0>_t svfoo[_t0](sv<t0>_t, uint64_t)
2678 <t0>_t svfoo[_n_t0](<t0>_t, uint64_t)
2680 where the t0 in the vector form is a signed or unsigned integer
2681 whose size is tied to the [bhwd] suffix of "svfoo". */
2682 struct inc_dec_def : public inc_dec_base
2684 CONSTEXPR inc_dec_def () : inc_dec_base (false) {}
2686 void
2687 build (function_builder &b, const function_group_info &group) const override
2689 b.add_overloaded_functions (group, MODE_none);
2690 /* These functions are unusual in that the type suffixes for
2691 the scalar and vector forms are not related. The vector
2692 form always has exactly two potential suffixes while the
2693 scalar form always has four. */
2694 if (group.types[2][0] == NUM_TYPE_SUFFIXES)
2695 build_all (b, "v0,v0,su64", group, MODE_none);
2696 else
2697 build_all (b, "s0,s0,su64", group, MODE_n);
2700 SHAPE (inc_dec)
2702 /* sv<t0>_t svfoo[_t0](sv<t0>_t, enum svpattern, uint64_t)
2703 <t0>_t svfoo[_n_t0](<t0>_t, enum svpattern, uint64_t)
2705 where the t0 in the vector form is a signed or unsigned integer
2706 whose size is tied to the [bhwd] suffix of "svfoo". */
2707 struct inc_dec_pat_def : public inc_dec_base
2709 CONSTEXPR inc_dec_pat_def () : inc_dec_base (true) {}
2711 void
2712 build (function_builder &b, const function_group_info &group) const override
2714 b.add_overloaded_functions (group, MODE_none);
2715 /* These functions are unusual in that the type suffixes for
2716 the scalar and vector forms are not related. The vector
2717 form always has exactly two potential suffixes while the
2718 scalar form always has four. */
2719 if (group.types[2][0] == NUM_TYPE_SUFFIXES)
2720 build_all (b, "v0,v0,epattern,su64", group, MODE_none);
2721 else
2722 build_all (b, "s0,s0,epattern,su64", group, MODE_n);
2725 SHAPE (inc_dec_pat)
2727 /* sv<t0>_t svfoo[_t0](sv<t0>_t, svbool_t). */
2728 struct inc_dec_pred_def : public overloaded_base<0>
2730 void
2731 build (function_builder &b, const function_group_info &group) const override
2733 b.add_overloaded_functions (group, MODE_none);
2734 build_all (b, "v0,v0,vp", group, MODE_none);
2737 tree
2738 resolve (function_resolver &r) const override
2740 unsigned int i, nargs;
2741 type_suffix_index type;
2742 if (!r.check_gp_argument (2, i, nargs)
2743 || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
2744 || !r.require_vector_type (i + 1, VECTOR_TYPE_svbool_t))
2745 return error_mark_node;
2747 return r.resolve_to (r.mode_suffix_id, type);
2750 SHAPE (inc_dec_pred)
2752 /* <t0>_t svfoo[_n_t0]_t1(<t0>_t, svbool_t)
2754 where _t1 is a _b<bits> suffix that describes the svbool_t argument. */
2755 struct inc_dec_pred_scalar_def : public overloaded_base<2>
2757 void
2758 build (function_builder &b, const function_group_info &group) const override
2760 b.add_overloaded_functions (group, MODE_n);
2761 build_all (b, "s0,s0,vp", group, MODE_n);
2764 tree
2765 resolve (function_resolver &r) const override
2767 unsigned int i, nargs;
2768 type_suffix_index type;
2769 if (!r.check_gp_argument (2, i, nargs)
2770 || (type = r.infer_integer_scalar_type (i)) == NUM_TYPE_SUFFIXES
2771 || !r.require_vector_type (i + 1, VECTOR_TYPE_svbool_t))
2772 return error_mark_node;
2774 return r.resolve_to (r.mode_suffix_id, type, r.type_suffix_ids[1]);
2777 SHAPE (inc_dec_pred_scalar)
2779 /* sv<t0>[xN]_t svfoo_t0(). */
2780 struct inherent_def : public nonoverloaded_base
2782 void
2783 build (function_builder &b, const function_group_info &group) const override
2785 build_all (b, "t0", group, MODE_none);
2788 SHAPE (inherent)
2790 /* svbool_t svfoo[_b](). */
2791 struct inherent_b_def : public overloaded_base<0>
2793 void
2794 build (function_builder &b, const function_group_info &group) const override
2796 /* The "_b" suffix is optional; the full name has it, but the short
2797 name doesn't. */
2798 build_all (b, "v0", group, MODE_none, true);
2801 tree
2802 resolve (function_resolver &) const override
2804 /* The short forms just make "_b" implicit, so no resolution is needed. */
2805 gcc_unreachable ();
2808 SHAPE (inherent_b)
2810 /* void svfoo_t0(). */
2811 struct inherent_za_def : public nonoverloaded_base
2813 void
2814 build (function_builder &b, const function_group_info &group) const override
2816 build_all (b, "_", group, MODE_none);
2819 SHAPE (inherent_za)
2821 /* void svfoo_t0(uint64_t). */
2822 struct inherent_za_slice_def : public nonoverloaded_base
2824 void
2825 build (function_builder &b, const function_group_info &group) const override
2827 build_all (b, "_,su32", group, MODE_none);
2830 SHAPE (inherent_za_slice)
2832 /* void svfoo_zt(uint64_t)
2834 where the argument must be zero. */
2835 struct inherent_zt_def : public nonoverloaded_base
2837 void
2838 build (function_builder &b, const function_group_info &group) const override
2840 build_all (b, "_,su64", group, MODE_none);
2843 bool
2844 check (function_checker &c) const override
2846 return c.require_immediate_range (0, 0, 0);
2849 SHAPE (inherent_zt)
2851 /* void svfoo_t0(uint64_t)
2853 where the argument is an integer constant that specifies an 8-bit mask. */
2854 struct inherent_mask_za_def : public nonoverloaded_base
2856 void
2857 build (function_builder &b, const function_group_info &group) const override
2859 build_all (b, "_,su64", group, MODE_none);
2862 bool
2863 check (function_checker &c) const override
2865 return c.require_immediate_range (0, 0, 255);
2868 SHAPE (inherent_mask_za)
2870 /* void svfoo_t0(uint32_t, const void *)
2871 void svfoo_vnum_t0(uint32_t, const void *, int64_t)
2873 where the first argument is a variable ZA slice. */
2874 struct ldr_za_def : public nonoverloaded_base
2876 void
2877 build (function_builder &b, const function_group_info &group) const override
2879 build_all (b, "_,su32,al", group, MODE_none);
2880 build_all (b, "_,su32,al,ss64", group, MODE_vnum);
2883 SHAPE (ldr_za)
2885 /* void svfoo_zt(uint64_t, const void *)
2887 where the first argument must be zero. */
2888 struct ldr_zt_def : public nonoverloaded_base
2890 void
2891 build (function_builder &b, const function_group_info &group) const override
2893 build_all (b, "_,su64,al", group, MODE_none);
2896 bool
2897 check (function_checker &c) const override
2899 return c.require_immediate_range (0, 0, 0);
2902 SHAPE (ldr_zt)
2904 /* sv<t0>[xN]_t svfoo[_t0]_g(const <t0>_t *)
2905 sv<t0>[xN]_t svfoo_vnum[_t0]_g(const <t0>_t *, int64_t). */
2906 struct load_def : public load_contiguous_base
2908 void
2909 build (function_builder &b, const function_group_info &group) const override
2911 b.add_overloaded_functions (group, MODE_none);
2912 b.add_overloaded_functions (group, MODE_vnum);
2913 build_all (b, "t0,al", group, MODE_none);
2914 build_all (b, "t0,al,ss64", group, MODE_vnum);
2917 SHAPE (load)
2919 /* sv<t0>_t svfoo_t0(const <X>_t *)
2920 sv<t0>_t svfoo_vnum_t0(const <X>_t *, int64_t)
2922 where <X> is determined by the function base name. */
2923 struct load_ext_def : public nonoverloaded_base
2925 void
2926 build (function_builder &b, const function_group_info &group) const override
2928 build_all (b, "t0,al", group, MODE_none);
2929 build_all (b, "t0,al,ss64", group, MODE_vnum);
2932 SHAPE (load_ext)
2934 /* sv<t0>_t svfoo_[s32]index_t0(const <X>_t *, svint32_t)
2935 sv<t0>_t svfoo_[s64]index_t0(const <X>_t *, svint64_t)
2936 sv<t0>_t svfoo_[u32]index_t0(const <X>_t *, svuint32_t)
2937 sv<t0>_t svfoo_[u64]index_t0(const <X>_t *, svuint64_t)
2939 sv<t0>_t svfoo[_u32base]_index_t0(svuint32_t, int64_t)
2940 sv<t0>_t svfoo[_u64base]_index_t0(svuint64_t, int64_t)
2942 where <X> is determined by the function base name. */
2943 struct load_ext_gather_index_def : public load_ext_gather_base
2945 void
2946 build (function_builder &b, const function_group_info &group) const override
2948 b.add_overloaded_functions (group, MODE_index);
2949 build_sv_index (b, "t0,al,d", group);
2950 build_vs_index (b, "t0,b,ss64", group);
2953 SHAPE (load_ext_gather_index)
2955 /* sv<t0>_t svfoo_[s64]index_t0(const <X>_t *, svint64_t)
2956 sv<t0>_t svfoo_[u64]index_t0(const <X>_t *, svuint64_t)
2958 sv<t0>_t svfoo[_u32base]_index_t0(svuint32_t, int64_t)
2959 sv<t0>_t svfoo[_u64base]_index_t0(svuint64_t, int64_t)
2961 where <X> is determined by the function base name. This is
2962 load_ext_gather_index that doesn't support 32-bit vector indices. */
2963 struct load_ext_gather_index_restricted_def : public load_ext_gather_base
2965 void
2966 build (function_builder &b, const function_group_info &group) const override
2968 b.add_overloaded_functions (group, MODE_index);
2969 build_sv_index64 (b, "t0,al,d", group);
2970 build_vs_index (b, "t0,b,ss64", group);
2973 SHAPE (load_ext_gather_index_restricted)
2975 /* sv<t0>_t svfoo_[s32]offset_t0(const <X>_t *, svint32_t)
2976 sv<t0>_t svfoo_[s64]offset_t0(const <X>_t *, svint64_t)
2977 sv<t0>_t svfoo_[u32]offset_t0(const <X>_t *, svuint32_t)
2978 sv<t0>_t svfoo_[u64]offset_t0(const <X>_t *, svuint64_t)
2980 sv<t0>_t svfoo[_u32base]_t0(svuint32_t)
2981 sv<t0>_t svfoo[_u64base]_t0(svuint64_t)
2983 sv<t0>_t svfoo[_u32base]_offset_t0(svuint32_t, int64_t)
2984 sv<t0>_t svfoo[_u64base]_offset_t0(svuint64_t, int64_t)
2986 where <X> is determined by the function base name. */
2987 struct load_ext_gather_offset_def : public load_ext_gather_base
2989 void
2990 build (function_builder &b, const function_group_info &group) const override
2992 b.add_overloaded_functions (group, MODE_offset);
2993 build_sv_offset (b, "t0,al,d", group);
2994 build_v_base (b, "t0,b", group, true);
2995 build_vs_offset (b, "t0,b,ss64", group);
2998 SHAPE (load_ext_gather_offset)
3000 /* sv<t0>_t svfoo_[s64]offset_t0(const <X>_t *, svint64_t)
3001 sv<t0>_t svfoo_[u32]offset_t0(const <X>_t *, svuint32_t)
3002 sv<t0>_t svfoo_[u64]offset_t0(const <X>_t *, svuint64_t)
3004 sv<t0>_t svfoo[_u32base]_t0(svuint32_t)
3005 sv<t0>_t svfoo[_u64base]_t0(svuint64_t)
3007 sv<t0>_t svfoo[_u32base]_offset_t0(svuint32_t, int64_t)
3008 sv<t0>_t svfoo[_u64base]_offset_t0(svuint64_t, int64_t)
3010 where <X> is determined by the function base name. This is
3011 load_ext_gather_offset without the s32 vector offset form. */
3012 struct load_ext_gather_offset_restricted_def : public load_ext_gather_base
3014 void
3015 build (function_builder &b, const function_group_info &group) const override
3017 b.add_overloaded_functions (group, MODE_offset);
3018 build_sv_uint_offset (b, "t0,al,d", group);
3019 build_v_base (b, "t0,b", group, true);
3020 build_vs_offset (b, "t0,b,ss64", group);
3023 SHAPE (load_ext_gather_offset_restricted)
3025 /* sv<t0>_t svfoo_[s32]index[_t0](const <t0>_t *, svint32_t)
3026 sv<t0>_t svfoo_[s64]index[_t0](const <t0>_t *, svint64_t)
3027 sv<t0>_t svfoo_[u32]index[_t0](const <t0>_t *, svuint32_t)
3028 sv<t0>_t svfoo_[u64]index[_t0](const <t0>_t *, svuint64_t)
3030 sv<t0>_t svfoo_[s32]offset[_t0](const <t0>_t *, svint32_t)
3031 sv<t0>_t svfoo_[s64]offset[_t0](const <t0>_t *, svint64_t)
3032 sv<t0>_t svfoo_[u32]offset[_t0](const <t0>_t *, svuint32_t)
3033 sv<t0>_t svfoo_[u64]offset[_t0](const <t0>_t *, svuint64_t). */
3034 struct load_gather_sv_def : public load_gather_sv_base
3036 void
3037 build (function_builder &b, const function_group_info &group) const override
3039 b.add_overloaded_functions (group, MODE_index);
3040 b.add_overloaded_functions (group, MODE_offset);
3041 build_sv_index (b, "t0,al,d", group);
3042 build_sv_offset (b, "t0,al,d", group);
3045 SHAPE (load_gather_sv)
3047 /* sv<t0>_t svfoo_[u32]index[_t0](const <t0>_t *, svuint32_t)
3048 sv<t0>_t svfoo_[u64]index[_t0](const <t0>_t *, svuint64_t)
3050 sv<t0>_t svfoo_[s64]offset[_t0](const <t0>_t *, svint64_t)
3051 sv<t0>_t svfoo_[u32]offset[_t0](const <t0>_t *, svuint32_t)
3052 sv<t0>_t svfoo_[u64]offset[_t0](const <t0>_t *, svuint64_t)
3054 This is load_gather_sv without the 32-bit vector index forms and
3055 without the s32 vector offset form. */
3056 struct load_gather_sv_restricted_def : public load_gather_sv_base
3058 void
3059 build (function_builder &b, const function_group_info &group) const override
3061 b.add_overloaded_functions (group, MODE_index);
3062 b.add_overloaded_functions (group, MODE_offset);
3063 build_sv_index64 (b, "t0,al,d", group);
3064 build_sv_uint_offset (b, "t0,al,d", group);
3067 SHAPE (load_gather_sv_restricted)
3069 /* sv<t0>_t svfoo[_u32base]_t0(svuint32_t)
3070 sv<t0>_t svfoo[_u64base]_t0(svuint64_t)
3072 sv<t0>_t svfoo[_u32base]_index_t0(svuint32_t, int64_t)
3073 sv<t0>_t svfoo[_u64base]_index_t0(svuint64_t, int64_t)
3075 sv<t0>_t svfoo[_u32base]_offset_t0(svuint32_t, int64_t)
3076 sv<t0>_t svfoo[_u64base]_offset_t0(svuint64_t, int64_t). */
3077 struct load_gather_vs_def : public overloaded_base<1>
3079 void
3080 build (function_builder &b, const function_group_info &group) const override
3082 /* The base vector mode is optional; the full name has it but the
3083 short name doesn't. There is no ambiguity with SHAPE_load_gather_sv
3084 because the latter uses an implicit type suffix. */
3085 build_v_base (b, "t0,b", group, true);
3086 build_vs_index (b, "t0,b,ss64", group, true);
3087 build_vs_offset (b, "t0,b,ss64", group, true);
3090 tree
3091 resolve (function_resolver &) const override
3093 /* The short name just makes the base vector mode implicit;
3094 no resolution is needed. */
3095 gcc_unreachable ();
3098 SHAPE (load_gather_vs)
3100 /* sv<t0>_t svfoo_[s64]index[_t0](const <t0>_t *, svint64_t)
3101 sv<t0>_t svfoo_[u64]index[_t0](const <t0>_t *, svuint64_t). */
3102 struct load_gather64_sv_index_def : public load_gather64_sv_base
3104 void
3105 build (function_builder &b, const function_group_info &group) const override
3107 b.add_overloaded_functions (group, MODE_index);
3108 build_all (b, "t0,al,d", group, MODE_s64index);
3109 build_all (b, "t0,al,d", group, MODE_u64index);
3112 SHAPE (load_gather64_sv_index)
3114 /* sv<t0>_t svfoo_[s64]offset[_t0](const <t0>_t *, svint64_t)
3115 sv<t0>_t svfoo_[u64]offset[_t0](const <t0>_t *, svuint64_t). */
3116 struct load_gather64_sv_offset_def : public load_gather64_sv_base
3118 void
3119 build (function_builder &b, const function_group_info &group) const override
3121 b.add_overloaded_functions (group, MODE_offset);
3122 build_all (b, "t0,al,d", group, MODE_s64offset);
3123 build_all (b, "t0,al,d", group, MODE_u64offset);
3126 SHAPE (load_gather64_sv_offset)
3128 /* sv<t0>_t svfoo[_u64base]_index_t0(svuint64_t, int64_t). */
3129 struct load_gather64_vs_index_def : public nonoverloaded_base
3131 void
3132 build (function_builder &b, const function_group_info &group) const override
3134 build_all (b, "t0,b,ss64", group, MODE_u64base_index, true);
3137 tree
3138 resolve (function_resolver &) const override
3140 /* The short name just makes the base vector mode implicit;
3141 no resolution is needed. */
3142 gcc_unreachable ();
3145 SHAPE (load_gather64_vs_index)
3147 /* sv<t0>_t svfoo[_u64base]_t0(svuint64_t)
3149 sv<t0>_t svfoo[_u64base]_offset_t0(svuint64_t, int64_t). */
3150 struct load_gather64_vs_offset_def : public nonoverloaded_base
3152 void
3153 build (function_builder &b, const function_group_info &group) const override
3155 build_all (b, "t0,b", group, MODE_u64base, true);
3156 build_all (b, "t0,b,ss64", group, MODE_u64base_offset, true);
3159 tree
3160 resolve (function_resolver &) const override
3162 /* The short name just makes the base vector mode implicit;
3163 no resolution is needed. */
3164 gcc_unreachable ();
3167 SHAPE (load_gather64_vs_offset)
3169 /* sv<t0>_t svfoo[_t0](const <t0>_t *)
3171 The only difference from "load" is that this shape has no vnum form. */
3172 struct load_replicate_def : public load_contiguous_base
3174 void
3175 build (function_builder &b, const function_group_info &group) const override
3177 b.add_overloaded_functions (group, MODE_none);
3178 build_all (b, "t0,al", group, MODE_none);
3181 SHAPE (load_replicate)
3183 /* void svfoo_t0(uint64_t, uint32_t, svbool_t, const void *)
3184 void svfoo_vnum_t0(uint64_t, uint32_t, svbool_t, const void *, int64_t)
3186 where the first two fields form a (ZA tile, slice) pair. */
3187 struct load_za_def : public nonoverloaded_base
3189 void
3190 build (function_builder &b, const function_group_info &group) const override
3192 build_all (b, "_,su64,su32,vp,al", group, MODE_none);
3193 build_all (b, "_,su64,su32,vp,al,ss64", group, MODE_vnum);
3196 bool
3197 check (function_checker &c) const override
3199 return c.require_immediate_range (0, 0, c.num_za_tiles () - 1);
3202 SHAPE (load_za)
3204 using luti2_lane_zt_def = luti_lane_zt_base<2>;
3205 SHAPE (luti2_lane_zt)
3207 using luti4_lane_zt_def = luti_lane_zt_base<4>;
3208 SHAPE (luti4_lane_zt)
3210 /* svbool_t svfoo(enum svpattern). */
3211 struct pattern_pred_def : public nonoverloaded_base
3213 void
3214 build (function_builder &b, const function_group_info &group) const override
3216 build_all (b, "vp,epattern", group, MODE_none);
3219 SHAPE (pattern_pred)
3221 /* svbool_t svfoo[_t0](sv<t0>_t). */
3222 struct pmov_from_vector_def : public overloaded_base<0>
3224 void
3225 build (function_builder &b, const function_group_info &group) const override
3227 b.add_overloaded_functions (group, MODE_none);
3228 build_all (b, "vp,v0", group, MODE_none);
3231 tree
3232 resolve (function_resolver &r) const override
3234 return r.resolve_uniform (1);
3237 SHAPE (pmov_from_vector)
3239 /* svbool_t svfoo[_t0](sv<t0>_t, uint64_t)
3241 where the final argument is an integer constant expression in the
3242 range [0, sizeof (<t0>_t) - 1]. */
3243 struct pmov_from_vector_lane_def : public overloaded_base<0>
3245 void
3246 build (function_builder &b, const function_group_info &group) const override
3248 b.add_overloaded_functions (group, MODE_none);
3249 build_all (b, "vp,v0,su64", group, MODE_none);
3252 tree
3253 resolve (function_resolver &r) const override
3255 return r.resolve_uniform (1, 1);
3258 bool
3259 check (function_checker &c) const override
3261 unsigned int bytes = c.type_suffix (0).element_bytes;
3262 return c.require_immediate_range (1, 0, bytes - 1);
3265 SHAPE (pmov_from_vector_lane)
3267 /* sv<t0>_t svfoo_t0(uint64_t)
3269 where the final argument is an integer constant expression in the
3270 range [1, sizeof (<t0>_t) - 1]. */
3271 struct pmov_to_vector_lane_def : public overloaded_base<0>
3273 void
3274 build (function_builder &b, const function_group_info &group) const override
3276 b.add_overloaded_functions (group, MODE_none);
3277 build_all (b, "v0,su64", group, MODE_none);
3280 tree
3281 resolve (function_resolver &r) const override
3283 type_suffix_index type;
3284 gcc_assert (r.pred == PRED_m);
3285 if (!r.check_num_arguments (3)
3286 || (type = r.infer_vector_type (0)) == NUM_TYPE_SUFFIXES
3287 || !r.require_vector_type (1, VECTOR_TYPE_svbool_t)
3288 || !r.require_integer_immediate (2))
3289 return error_mark_node;
3291 return r.resolve_to (r.mode_suffix_id, type);
3294 bool
3295 check (function_checker &c) const override
3297 unsigned int bytes = c.type_suffix (0).element_bytes;
3298 /* 1 to account for the vector argument.
3300 ??? This should probably be folded into function_checker::m_base_arg,
3301 but it doesn't currently have the necessary information. */
3302 return c.require_immediate_range (1, 1, bytes - 1);
3305 SHAPE (pmov_to_vector_lane)
3307 /* void svfoo(const void *, svprfop)
3308 void svfoo_vnum(const void *, int64_t, svprfop). */
3309 struct prefetch_def : public nonoverloaded_base
3311 void
3312 build (function_builder &b, const function_group_info &group) const override
3314 build_all (b, "_,ap,eprfop", group, MODE_none);
3315 build_all (b, "_,ap,ss64,eprfop", group, MODE_vnum);
3318 SHAPE (prefetch)
3320 /* void svfoo_[s32]index(const void *, svint32_t, svprfop)
3321 void svfoo_[s64]index(const void *, svint64_t, svprfop)
3322 void svfoo_[u32]index(const void *, svuint32_t, svprfop)
3323 void svfoo_[u64]index(const void *, svuint64_t, svprfop)
3325 void svfoo[_u32base](svuint32_t, svprfop)
3326 void svfoo[_u64base](svuint64_t, svprfop)
3328 void svfoo[_u32base]_index(svuint32_t, int64_t, svprfop)
3329 void svfoo[_u64base]_index(svuint64_t, int64_t, svprfop). */
3330 struct prefetch_gather_index_def : public prefetch_gather_base
3332 void
3333 build (function_builder &b, const function_group_info &group) const override
3335 b.add_overloaded_functions (group, MODE_none);
3336 b.add_overloaded_functions (group, MODE_index);
3337 build_sv_index (b, "_,ap,d,eprfop", group);
3338 build_v_base (b, "_,b,eprfop", group);
3339 build_vs_index (b, "_,b,ss64,eprfop", group);
3342 SHAPE (prefetch_gather_index)
3344 /* void svfoo_[s32]offset(const void *, svint32_t, svprfop)
3345 void svfoo_[s64]offset(const void *, svint64_t, svprfop)
3346 void svfoo_[u32]offset(const void *, svuint32_t, svprfop)
3347 void svfoo_[u64]offset(const void *, svuint64_t, svprfop)
3349 void svfoo[_u32base](svuint32_t, svprfop)
3350 void svfoo[_u64base](svuint64_t, svprfop)
3352 void svfoo[_u32base]_offset(svuint32_t, int64_t, svprfop)
3353 void svfoo[_u64base]_offset(svuint64_t, int64_t, svprfop). */
3354 struct prefetch_gather_offset_def : public prefetch_gather_base
3356 void
3357 build (function_builder &b, const function_group_info &group) const override
3359 b.add_overloaded_functions (group, MODE_none);
3360 b.add_overloaded_functions (group, MODE_offset);
3361 build_sv_offset (b, "_,ap,d,eprfop", group);
3362 build_v_base (b, "_,b,eprfop", group);
3363 build_vs_offset (b, "_,b,ss64,eprfop", group);
3366 SHAPE (prefetch_gather_offset)
3368 /* bool svfoo(svbool_t). */
3369 struct ptest_def : public nonoverloaded_base
3371 void
3372 build (function_builder &b, const function_group_info &group) const override
3374 build_all (b, "sp,vp", group, MODE_none);
3377 SHAPE (ptest)
3379 /* svbool_t svfoo(). */
3380 struct rdffr_def : public nonoverloaded_base
3382 void
3383 build (function_builder &b, const function_group_info &group) const override
3385 build_all (b, "vp", group, MODE_none);
3388 SHAPE (rdffr)
3390 /* sv<t1>x<g>_t svfoo_t0_t1_g(uint64_t, uint32_t). */
3391 struct read_za_def : public nonoverloaded_base
3393 void
3394 build (function_builder &b, const function_group_info &group) const override
3396 build_all (b, "t1,su64,su32", group, MODE_none);
3399 bool
3400 check (function_checker &c) const override
3402 return c.require_immediate_range (0, 0, c.num_za_tiles () - 1);
3405 SHAPE (read_za)
3407 /* sv<t1>_t svfoo_t0[_t1](uint64_t, uint32_t)
3409 where the first two fields form a (ZA tile, slice) pair. */
3410 struct read_za_m_def : public overloaded_base<1>
3412 bool
3413 has_merge_argument_p (const function_instance &, unsigned int) const override
3415 return true;
3418 void
3419 build (function_builder &b, const function_group_info &group) const override
3421 b.add_overloaded_functions (group, MODE_none);
3422 build_all (b, "t1,su64,su32", group, MODE_none);
3425 tree
3426 resolve (function_resolver &r) const override
3428 gcc_assert (r.pred == PRED_m);
3429 type_suffix_index type;
3430 if (!r.check_num_arguments (4)
3431 || (type = r.infer_vector_type (0)) == NUM_TYPE_SUFFIXES
3432 || !r.require_vector_type (1, VECTOR_TYPE_svbool_t)
3433 || !r.require_integer_immediate (2)
3434 || !r.require_scalar_type (3, "uint32_t"))
3435 return error_mark_node;
3437 return r.resolve_to (r.mode_suffix_id, r.type_suffix_ids[0], type);
3440 bool
3441 check (function_checker &c) const override
3443 gcc_assert (c.pred == PRED_m);
3444 return c.require_immediate_range (1, 0, c.num_za_tiles () - 1);
3447 SHAPE (read_za_m)
3449 /* sv<t1>x<g>_t svfoo_t0_t1_g(uint32_t). */
3450 struct read_za_slice_def : public nonoverloaded_base
3452 void
3453 build (function_builder &b, const function_group_info &group) const override
3455 build_all (b, "t1,su32", group, MODE_none);
3458 SHAPE (read_za_slice)
3460 /* <t0>_t svfoo[_t0](sv<t0>_t). */
3461 struct reduction_def : public overloaded_base<0>
3463 void
3464 build (function_builder &b, const function_group_info &group) const override
3466 b.add_overloaded_functions (group, MODE_none);
3467 build_all (b, "s0,v0", group, MODE_none);
3470 tree
3471 resolve (function_resolver &r) const override
3473 return r.resolve_uniform (1);
3476 SHAPE (reduction)
3478 /* <t0>xN_t svfoo[_t0](sv<t0>_t). */
3479 struct reduction_neonq_def : public overloaded_base<0>
3481 void
3482 build (function_builder &b, const function_group_info &group) const override
3484 b.add_overloaded_functions (group, MODE_none);
3485 build_all (b, "Q0,v0", group, MODE_none);
3488 tree
3489 resolve (function_resolver &r) const override
3491 return r.resolve_uniform (1);
3494 SHAPE (reduction_neonq)
3496 /* int64_t svfoo[_t0](sv<t0>_t) (for signed t0)
3497 uint64_t svfoo[_t0](sv<t0>_t) (for unsigned t0)
3498 <t0>_t svfoo[_t0](sv<t0>_t) (for floating-point t0)
3500 i.e. a version of "reduction" in which the return type for integers
3501 always has 64 bits. */
3502 struct reduction_wide_def : public overloaded_base<0>
3504 void
3505 build (function_builder &b, const function_group_info &group) const override
3507 b.add_overloaded_functions (group, MODE_none);
3508 build_all (b, "sw0,v0", group, MODE_none);
3511 tree
3512 resolve (function_resolver &r) const override
3514 return r.resolve_uniform (1);
3517 SHAPE (reduction_wide)
3519 /* sv<t0>x<g>_t svfoo_t0[_t1_g](sv<t1>x<g>_t)
3521 where the target type <t0> must be specified explicitly but the source
3522 type <t1> can be inferred. */
3523 struct reinterpret_def : public overloaded_base<1>
3525 bool explicit_group_suffix_p () const override { return false; }
3527 void
3528 build (function_builder &b, const function_group_info &group) const override
3530 b.add_overloaded_functions (group, MODE_none);
3531 build_all (b, "t0,t1", group, MODE_none);
3534 tree
3535 resolve (function_resolver &r) const override
3537 sve_type type;
3538 if (!r.check_num_arguments (1)
3539 || !(type = r.infer_sve_type (0)))
3540 return error_mark_node;
3542 return r.resolve_to (r.mode_suffix_id, type);
3545 SHAPE (reinterpret)
3547 /* sv<t0>_t svfoo_t0(sv<t0>_t, sv<t0>_t, uint32_t). */
3548 struct select_pred_def : public nonoverloaded_base
3550 void
3551 build (function_builder &b, const function_group_info &group) const override
3553 build_all (b, "v0,v0,vp,su32", group, MODE_none);
3556 SHAPE (select_pred)
3558 /* sv<t0>xN_t svfoo[_t0](sv<t0>xN_t, uint64_t, sv<t0>_t)
3560 where the second argument is an integer constant expression in the
3561 range [0, N - 1]. */
3562 struct set_def : public overloaded_base<0>
3564 void
3565 build (function_builder &b, const function_group_info &group) const override
3567 b.add_overloaded_functions (group, MODE_none);
3568 build_all (b, "t0,t0,su64,v0", group, MODE_none);
3571 tree
3572 resolve (function_resolver &r) const override
3574 unsigned int i, nargs;
3575 sve_type type;
3576 if (!r.check_gp_argument (3, i, nargs)
3577 || !(type = r.infer_tuple_type (i))
3578 || !r.require_integer_immediate (i + 1)
3579 || !r.require_derived_vector_type (i + 2, i, type))
3580 return error_mark_node;
3582 return r.resolve_to (r.mode_suffix_id, type);
3585 bool
3586 check (function_checker &c) const override
3588 unsigned int nvectors = c.vectors_per_tuple ();
3589 return c.require_immediate_range (1, 0, nvectors - 1);
3592 SHAPE (set)
3594 /* void svfoo(). */
3595 struct setffr_def : public nonoverloaded_base
3597 void
3598 build (function_builder &b, const function_group_info &group) const override
3600 build_all (b, "_", group, MODE_none);
3603 SHAPE (setffr)
3605 /* sv<t0>_t svfoo[_n_t0])(sv<t0>_t, uint64_t)
3607 where the final argument must be an integer constant expression in the
3608 range [0, sizeof (<t0>_t) * 8 - 1]. */
3609 struct shift_left_imm_def : public overloaded_base<0>
3611 void
3612 build (function_builder &b, const function_group_info &group) const override
3614 b.add_overloaded_functions (group, MODE_n);
3615 build_all (b, "v0,v0,su64", group, MODE_n);
3618 tree
3619 resolve (function_resolver &r) const override
3621 return r.resolve_uniform (1, 1);
3624 bool
3625 check (function_checker &c) const override
3627 unsigned int bits = c.type_suffix (0).element_bits;
3628 return c.require_immediate_range (1, 0, bits - 1);
3631 SHAPE (shift_left_imm)
3633 /* sv<t0>_t svfoo[_n_t0])(sv<t0:half>_t, uint64_t)
3635 where the final argument must be an integer constant expression in the
3636 range [0, sizeof (<t0>_t) * 4 - 1]. */
3637 struct shift_left_imm_long_def : public binary_imm_long_base
3639 bool
3640 check (function_checker &c) const override
3642 unsigned int bits = c.type_suffix (0).element_bits / 2;
3643 return c.require_immediate_range (1, 0, bits - 1);
3646 SHAPE (shift_left_imm_long)
3648 /* sv<t0:uint>_t svfoo[_n_t0])(sv<t0>_t, uint64_t)
3650 where the final argument must be an integer constant expression in the
3651 range [0, sizeof (<t0>_t) * 8 - 1]. */
3652 struct shift_left_imm_to_uint_def : public shift_left_imm_def
3654 void
3655 build (function_builder &b, const function_group_info &group) const override
3657 b.add_overloaded_functions (group, MODE_n);
3658 build_all (b, "vu0,v0,su64", group, MODE_n);
3661 SHAPE (shift_left_imm_to_uint)
3663 /* sv<t0>_t svfoo[_n_t0])(sv<t0>_t, uint64_t)
3665 where the final argument must be an integer constant expression in the
3666 range [1, sizeof (<t0>_t) * 8]. */
3667 struct shift_right_imm_def : public overloaded_base<0>
3669 void
3670 build (function_builder &b, const function_group_info &group) const override
3672 b.add_overloaded_functions (group, MODE_n);
3673 build_all (b, "v0,v0,su64", group, MODE_n);
3676 tree
3677 resolve (function_resolver &r) const override
3679 return r.resolve_uniform (1, 1);
3682 bool
3683 check (function_checker &c) const override
3685 unsigned int bits = c.type_suffix (0).element_bits;
3686 return c.require_immediate_range (1, 1, bits);
3689 SHAPE (shift_right_imm)
3691 /* sv<t0:half>_t svfoo[_n_t0])(sv<t0>_t, uint64_t)
3693 where the final argument must be an integer constant expression in the
3694 range [1, sizeof (<t0>_t) * 4]. */
3695 typedef shift_right_imm_narrow_wrapper<binary_imm_narrowb_base<>, 1>
3696 shift_right_imm_narrowb_def;
3697 SHAPE (shift_right_imm_narrowb)
3699 /* sv<t0:half>_t svfoo[_n_t0])(sv<t0:half>_t, sv<t0>_t, uint64_t)
3701 where the final argument must be an integer constant expression in the
3702 range [1, sizeof (<t0>_t) * 4]. */
3703 typedef shift_right_imm_narrow_wrapper<binary_imm_narrowt_base<>, 2>
3704 shift_right_imm_narrowt_def;
3705 SHAPE (shift_right_imm_narrowt)
3707 /* sv<t0:uint:half>_t svfoo[_n_t0])(sv<t0>_t, uint64_t)
3709 where the final argument must be an integer constant expression in the
3710 range [1, sizeof (<t0>_t) * 4]. */
3711 typedef binary_imm_narrowb_base<TYPE_unsigned>
3712 binary_imm_narrowb_base_unsigned;
3713 typedef shift_right_imm_narrow_wrapper<binary_imm_narrowb_base_unsigned, 1>
3714 shift_right_imm_narrowb_to_uint_def;
3715 SHAPE (shift_right_imm_narrowb_to_uint)
3717 /* sv<t0:uint:half>_t svfoo[_n_t0])(sv<t0:uint:half>_t, sv<t0>_t, uint64_t)
3719 where the final argument must be an integer constant expression in the
3720 range [1, sizeof (<t0>_t) * 4]. */
3721 typedef binary_imm_narrowt_base<TYPE_unsigned>
3722 binary_imm_narrowt_base_unsigned;
3723 typedef shift_right_imm_narrow_wrapper<binary_imm_narrowt_base_unsigned, 2>
3724 shift_right_imm_narrowt_to_uint_def;
3725 SHAPE (shift_right_imm_narrowt_to_uint)
3727 /* sv<t0>_t svfoo[_n_t0])(sv<t0>_t, uint64_t)
3729 where the final argument must be an integer constant expression in the
3730 range [1, sizeof (<t0>_t) * 8]. */
3731 struct shift_right_imm_narrowxn_def : public overloaded_base<1>
3733 bool explicit_group_suffix_p () const override { return false; }
3735 void
3736 build (function_builder &b, const function_group_info &group) const override
3738 b.add_overloaded_functions (group, MODE_n);
3739 build_all (b, "c0,c1,su64", group, MODE_n);
3742 tree
3743 resolve (function_resolver &r) const override
3745 sve_type type;
3746 if (!r.check_num_arguments (2)
3747 || !(type = r.infer_sve_type (0))
3748 || !r.require_integer_immediate (1))
3749 return error_mark_node;
3750 return r.resolve_to (r.mode_suffix_id, type);
3753 bool
3754 check (function_checker &c) const override
3756 unsigned int suffix = c.group_suffix_id == GROUP_x4 ? 1 : 0;
3757 unsigned int bits = c.type_suffix (suffix).element_bits;
3758 return c.require_immediate_range (1, 1, bits);
3761 SHAPE (shift_right_imm_narrowxn)
3763 /* void svfoo[_t0](<X>_t *, sv<t0>[xN]_t)
3764 void svfoo_vnum[_t0](<X>_t *, int64_t, sv<t0>[xN]_t)
3766 where <X> might be tied to <t0> (for non-truncating stores) or might
3767 depend on the function base name (for truncating stores). */
3768 struct store_def : public overloaded_base<0>
3770 void
3771 build (function_builder &b, const function_group_info &group) const override
3773 b.add_overloaded_functions (group, MODE_none);
3774 b.add_overloaded_functions (group, MODE_vnum);
3775 build_all (b, "_,as,t0", group, MODE_none);
3776 build_all (b, "_,as,ss64,t0", group, MODE_vnum);
3779 tree
3780 resolve (function_resolver &r) const override
3782 bool vnum_p = r.mode_suffix_id == MODE_vnum;
3783 gcc_assert (r.mode_suffix_id == MODE_none || vnum_p);
3785 unsigned int i, nargs;
3786 sve_type type;
3787 if (!r.check_gp_argument (vnum_p ? 3 : 2, i, nargs)
3788 || !r.require_pointer_type (i)
3789 || (vnum_p && !r.require_scalar_type (i + 1, "int64_t"))
3790 || !(type = r.infer_tuple_type (nargs - 1)))
3791 return error_mark_node;
3793 return r.resolve_to (r.mode_suffix_id, type);
3796 SHAPE (store)
3798 /* void svfoo_[s32]index[_t0](<X>_t *, svint32_t, sv<t0>_t)
3799 void svfoo_[s64]index[_t0](<X>_t *, svint64_t, sv<t0>_t)
3800 void svfoo_[u32]index[_t0](<X>_t *, svuint32_t, sv<t0>_t)
3801 void svfoo_[u64]index[_t0](<X>_t *, svuint64_t, sv<t0>_t)
3803 void svfoo[_u32base]_index[_t0](svuint32_t, int64_t, sv<t0>_t)
3804 void svfoo[_u64base]_index[_t0](svuint64_t, int64_t, sv<t0>_t)
3806 where <X> might be tied to <t0> (for non-truncating stores) or might
3807 depend on the function base name (for truncating stores). */
3808 struct store_scatter_index_def : public store_scatter_base
3810 void
3811 build (function_builder &b, const function_group_info &group) const override
3813 b.add_overloaded_functions (group, MODE_index);
3814 build_sv_index (b, "_,as,d,t0", group);
3815 build_vs_index (b, "_,b,ss64,t0", group);
3818 SHAPE (store_scatter_index)
3820 /* void svfoo_[s64]index[_t0](<X>_t *, svint64_t, sv<t0>_t)
3821 void svfoo_[u64]index[_t0](<X>_t *, svuint64_t, sv<t0>_t)
3823 void svfoo[_u32base]_index[_t0](svuint32_t, int64_t, sv<t0>_t)
3824 void svfoo[_u64base]_index[_t0](svuint64_t, int64_t, sv<t0>_t)
3826 i.e. a version of store_scatter_index that doesn't support 32-bit
3827 vector indices. */
3828 struct store_scatter_index_restricted_def : public store_scatter_base
3830 void
3831 build (function_builder &b, const function_group_info &group) const override
3833 b.add_overloaded_functions (group, MODE_index);
3834 build_sv_index64 (b, "_,as,d,t0", group);
3835 build_vs_index (b, "_,b,ss64,t0", group);
3838 SHAPE (store_scatter_index_restricted)
3840 /* void svfoo_[s32]offset[_t0](<X>_t *, svint32_t, sv<t0>_t)
3841 void svfoo_[s64]offset[_t0](<X>_t *, svint64_t, sv<t0>_t)
3842 void svfoo_[u32]offset[_t0](<X>_t *, svuint32_t, sv<t0>_t)
3843 void svfoo_[u64]offset[_t0](<X>_t *, svuint64_t, sv<t0>_t)
3845 void svfoo[_u32base_t0](svuint32_t, sv<t0>_t)
3846 void svfoo[_u64base_t0](svuint64_t, sv<t0>_t)
3848 void svfoo[_u32base]_offset[_t0](svuint32_t, int64_t, sv<t0>_t)
3849 void svfoo[_u64base]_offset[_t0](svuint64_t, int64_t, sv<t0>_t)
3851 where <X> might be tied to <t0> (for non-truncating stores) or might
3852 depend on the function base name (for truncating stores). */
3853 struct store_scatter_offset_def : public store_scatter_base
3855 void
3856 build (function_builder &b, const function_group_info &group) const override
3858 b.add_overloaded_functions (group, MODE_none);
3859 b.add_overloaded_functions (group, MODE_offset);
3860 build_sv_offset (b, "_,as,d,t0", group);
3861 build_v_base (b, "_,b,t0", group);
3862 build_vs_offset (b, "_,b,ss64,t0", group);
3865 SHAPE (store_scatter_offset)
3867 /* void svfoo_[s64]offset[_t0](<X>_t *, svint64_t, sv<t0>_t)
3868 void svfoo_[u32]offset[_t0](<X>_t *, svuint32_t, sv<t0>_t)
3869 void svfoo_[u64]offset[_t0](<X>_t *, svuint64_t, sv<t0>_t)
3871 void svfoo[_u32base_t0](svuint32_t, sv<t0>_t)
3872 void svfoo[_u64base_t0](svuint64_t, sv<t0>_t)
3874 void svfoo[_u32base]_offset[_t0](svuint32_t, int64_t, sv<t0>_t)
3875 void svfoo[_u64base]_offset[_t0](svuint64_t, int64_t, sv<t0>_t)
3877 i.e. a version of store_scatter_offset that doesn't support svint32_t
3878 offsets. */
3879 struct store_scatter_offset_restricted_def : public store_scatter_base
3881 void
3882 build (function_builder &b, const function_group_info &group) const override
3884 b.add_overloaded_functions (group, MODE_none);
3885 b.add_overloaded_functions (group, MODE_offset);
3886 build_sv_uint_offset (b, "_,as,d,t0", group);
3887 build_v_base (b, "_,b,t0", group);
3888 build_vs_offset (b, "_,b,ss64,t0", group);
3891 SHAPE (store_scatter_offset_restricted)
3893 /* void svfoo_[s64]index[_t0](<t0>_t *, svint64_t, sv<t0>_t)
3894 void svfoo_[u64]index[_t0](<t0>_t *, svuint64_t, sv<t0>_t)
3896 void svfoo[_u64base]_index[_t0](svuint64_t, int64_t, sv<t0>_t). */
3897 struct store_scatter64_index_def : public store_scatter64_base
3899 void
3900 build (function_builder &b, const function_group_info &group) const override
3902 b.add_overloaded_functions (group, MODE_index);
3903 build_all (b, "_,as,d,t0", group, MODE_s64index);
3904 build_all (b, "_,as,d,t0", group, MODE_u64index);
3905 build_all (b, "_,b,ss64,t0", group, MODE_u64base_index);
3908 SHAPE (store_scatter64_index)
3910 /* void svfoo_[s64]offset[_t0](<t0>_t *, svint64_t, sv<t0>_t)
3911 void svfoo_[u64]offset[_t0](<t0>_t *, svuint64_t, sv<t0>_t)
3913 void svfoo[_u64base_t0](svuint64_t, sv<t0>_t)
3915 void svfoo[_u64base]_offset[_t0](svuint64_t, int64_t, sv<t0>_t). */
3916 struct store_scatter64_offset_def : public store_scatter64_base
3918 void
3919 build (function_builder &b, const function_group_info &group) const override
3921 b.add_overloaded_functions (group, MODE_none);
3922 b.add_overloaded_functions (group, MODE_offset);
3923 build_all (b, "_,as,d,t0", group, MODE_s64offset);
3924 build_all (b, "_,as,d,t0", group, MODE_u64offset);
3925 build_all (b, "_,b,t0", group, MODE_u64base);
3926 build_all (b, "_,b,ss64,t0", group, MODE_u64base_offset);
3929 SHAPE (store_scatter64_offset)
3931 /* void svfoo_t0(uint64_t, uint32_t, svbool_t, void *)
3932 void svfoo_vnum_t0(uint64_t, uint32_t, svbool_t, void *, int64_t)
3934 where the first two fields form a (ZA tile, slice) pair. */
3935 struct store_za_def : public nonoverloaded_base
3937 void
3938 build (function_builder &b, const function_group_info &group) const override
3940 build_all (b, "_,su64,su32,vp,as", group, MODE_none);
3941 build_all (b, "_,su64,su32,vp,as,ss64", group, MODE_vnum);
3944 bool
3945 check (function_checker &c) const override
3947 return c.require_immediate_range (0, 0, c.num_za_tiles () - 1);
3950 SHAPE (store_za)
3952 /* void svfoo[_t0_g](<X>_t *, sv<t0>x<g>_t)
3953 void svfoo_vnum[_t0_g](<X>_t *, int64_t, sv<t0>x<g>_t)
3955 where <X> might be tied to <t0> (for non-truncating stores) or might
3956 depend on the function base name (for truncating stores). */
3957 struct storexn_def : public store_def
3959 bool explicit_group_suffix_p () const override { return false; }
3961 tree
3962 resolve (function_resolver &r) const override
3964 bool vnum_p = r.mode_suffix_id == MODE_vnum;
3965 gcc_assert (r.mode_suffix_id == MODE_none || vnum_p);
3967 unsigned int nargs = vnum_p ? 4 : 3;
3968 vector_type_index pred_type;
3969 sve_type type;
3970 if (!r.check_num_arguments (nargs)
3971 || (pred_type = r.infer_predicate_type (0)) == NUM_VECTOR_TYPES
3972 || !r.require_pointer_type (1)
3973 || (vnum_p && !r.require_scalar_type (2, "int64_t"))
3974 || !(type = r.infer_sve_type (nargs - 1))
3975 || !r.require_matching_predicate_type (pred_type, type))
3976 return error_mark_node;
3978 return r.resolve_to (r.mode_suffix_id, type);
3981 SHAPE (storexn)
3983 /* void svfoo_t0(uint32_t, void *)
3984 void svfoo_vnum_t0(uint32_t, void *, int64_t)
3986 where the first argument is a variable ZA slice. */
3987 struct str_za_def : public nonoverloaded_base
3989 void
3990 build (function_builder &b, const function_group_info &group) const override
3992 build_all (b, "_,su32,as", group, MODE_none);
3993 build_all (b, "_,su32,as,ss64", group, MODE_vnum);
3996 SHAPE (str_za)
3998 /* void svfoo_zt(uint64_t, void *)
4000 where the first argument must be zero. */
4001 struct str_zt_def : public nonoverloaded_base
4003 void
4004 build (function_builder &b, const function_group_info &group) const override
4006 build_all (b, "_,su64,as", group, MODE_none);
4009 bool
4010 check (function_checker &c) const override
4012 return c.require_immediate_range (0, 0, 0);
4015 SHAPE (str_zt)
4017 /* sv<t0>_t svfoo[_t0](sv<t0>xN_t, sv<t0:uint>_t). */
4018 struct tbl_tuple_def : public overloaded_base<0>
4020 void
4021 build (function_builder &b, const function_group_info &group) const override
4023 b.add_overloaded_functions (group, MODE_none);
4024 build_all (b, "v0,t0,vu0", group, MODE_none);
4027 tree
4028 resolve (function_resolver &r) const override
4030 unsigned int i, nargs;
4031 sve_type type;
4032 if (!r.check_gp_argument (2, i, nargs)
4033 || !(type = r.infer_tuple_type (i))
4034 || !r.require_derived_vector_type (i + 1, i, type, TYPE_unsigned))
4035 return error_mark_node;
4037 return r.resolve_to (r.mode_suffix_id, type);
4040 SHAPE (tbl_tuple)
4042 /* sv<t0>_t svfoo[_t0](sv<t0>_t, svbfloatt16_t, svbfloat16_t). */
4043 struct ternary_bfloat_def
4044 : public ternary_resize2_base<16, TYPE_bfloat, TYPE_bfloat>
4046 void
4047 build (function_builder &b, const function_group_info &group) const override
4049 b.add_overloaded_functions (group, MODE_none);
4050 build_all (b, "v0,v0,vB,vB", group, MODE_none);
4053 SHAPE (ternary_bfloat)
4055 /* sv<t0>_t svfoo[_t0](sv<t0>_t, svmfloat8_t, svmfloat8_t). */
4056 struct ternary_mfloat8_def
4057 : public ternary_resize2_base<8, TYPE_mfloat, TYPE_mfloat>
4059 void
4060 build (function_builder &b, const function_group_info &group) const override
4062 gcc_assert (group.fpm_mode == FPM_set);
4063 b.add_overloaded_functions (group, MODE_none);
4064 build_all (b, "v0,v0,vM,vM", group, MODE_none);
4067 tree
4068 resolve (function_resolver &r) const override
4070 type_suffix_index type;
4071 if (!r.check_num_arguments (4)
4072 || (type = r.infer_vector_type (0)) == NUM_TYPE_SUFFIXES
4073 || !r.require_vector_type (1, VECTOR_TYPE_svmfloat8_t)
4074 || !r.require_vector_type (2, VECTOR_TYPE_svmfloat8_t)
4075 || !r.require_scalar_type (3, "uint64_t"))
4076 return error_mark_node;
4078 return r.resolve_to (r.mode_suffix_id, type, TYPE_SUFFIX_mf8, GROUP_none);
4081 SHAPE (ternary_mfloat8)
4083 /* sv<t0>_t svfoo[_t0](sv<t0>_t, svbfloat16_t, svbfloat16_t, uint64_t)
4085 where the final argument is an integer constant expression in the range
4086 [0, 7]. */
4087 typedef ternary_bfloat_lane_base<1> ternary_bfloat_lane_def;
4088 SHAPE (ternary_bfloat_lane)
4090 /* sv<t0>_t svfoo[_t0](sv<t0>_t, svbfloat16_t, svbfloat16_t, uint64_t)
4092 where the final argument is an integer constant expression in the range
4093 [0, 3]. */
4094 typedef ternary_bfloat_lane_base<2> ternary_bfloat_lanex2_def;
4095 SHAPE (ternary_bfloat_lanex2)
4097 /* sv<t0>_t svfoo[_t0](sv<t0>_t, svmfloat8_t, svmfloat8_t, uint64_t)
4099 where the final argument is an integer constant expression in the range
4100 [0, 15]. */
4101 struct ternary_mfloat8_lane_def
4102 : public ternary_resize2_lane_base<8, TYPE_mfloat, TYPE_mfloat>
4104 void
4105 build (function_builder &b, const function_group_info &group) const override
4107 gcc_assert (group.fpm_mode == FPM_set);
4108 b.add_overloaded_functions (group, MODE_none);
4109 build_all (b, "v0,v0,vM,vM,su64", group, MODE_none);
4112 bool
4113 check (function_checker &c) const override
4115 return c.require_immediate_lane_index (3, 2, 1);
4118 tree
4119 resolve (function_resolver &r) const override
4121 type_suffix_index type;
4122 if (!r.check_num_arguments (5)
4123 || (type = r.infer_vector_type (0)) == NUM_TYPE_SUFFIXES
4124 || !r.require_vector_type (1, VECTOR_TYPE_svmfloat8_t)
4125 || !r.require_vector_type (2, VECTOR_TYPE_svmfloat8_t)
4126 || !r.require_integer_immediate (3)
4127 || !r.require_scalar_type (4, "uint64_t"))
4128 return error_mark_node;
4130 return r.resolve_to (r.mode_suffix_id, type, TYPE_SUFFIX_mf8, GROUP_none);
4133 SHAPE (ternary_mfloat8_lane)
4135 /* sv<t0>_t svfoo[_t0](sv<t0>_t, svmfloat8_t, svmfloat8_t, uint64_t)
4137 where the final argument is an integer constant expression in the range
4138 [0, 7] or [0, 3]. */
4139 struct ternary_mfloat8_lane_group_selection_def
4140 : public ternary_mfloat8_lane_def
4142 bool
4143 check (function_checker &c) const override
4145 machine_mode mode = c.vector_mode (0);
4146 if (mode == E_VNx8HFmode)
4147 return c.require_immediate_lane_index (3, 2, 2);
4148 else if (mode == E_VNx4SFmode)
4149 return c.require_immediate_lane_index (3, 2, 4);
4150 gcc_unreachable ();
4153 SHAPE (ternary_mfloat8_lane_group_selection)
4155 /* sv<t0>_t svfoo[_t0](sv<t0>_t, svbfloatt16_t, svbfloat16_t)
4156 sv<t0>_t svfoo[_n_t0](sv<t0>_t, svbfloat16_t, bfloat16_t). */
4157 struct ternary_bfloat_opt_n_def
4158 : public ternary_resize2_opt_n_base<16, TYPE_bfloat, TYPE_bfloat>
4160 void
4161 build (function_builder &b, const function_group_info &group) const override
4163 b.add_overloaded_functions (group, MODE_none);
4164 build_all (b, "v0,v0,vB,vB", group, MODE_none);
4165 build_all (b, "v0,v0,vB,sB", group, MODE_n);
4168 SHAPE (ternary_bfloat_opt_n)
4170 /* sv<t0>_t svfoo[_t0](sv<t0>_t, svmfloatt8_t, svmfloat8_t)
4171 sv<t0>_t svfoo[_n_t0](sv<t0>_t, svmfloat8_t, bfloat8_t). */
4172 struct ternary_mfloat8_opt_n_def
4173 : public ternary_resize2_opt_n_base<8, TYPE_mfloat, TYPE_mfloat>
4175 void
4176 build (function_builder &b, const function_group_info &group) const override
4178 gcc_assert (group.fpm_mode == FPM_set);
4179 b.add_overloaded_functions (group, MODE_none);
4180 build_all (b, "v0,v0,vM,vM", group, MODE_none);
4181 build_all (b, "v0,v0,vM,sM", group, MODE_n);
4184 tree
4185 resolve (function_resolver &r) const override
4187 type_suffix_index type;
4188 if (!r.check_num_arguments (4)
4189 || (type = r.infer_vector_type (0)) == NUM_TYPE_SUFFIXES
4190 || !r.require_vector_type (1, VECTOR_TYPE_svmfloat8_t)
4191 || !r.require_vector_or_scalar_type (2)
4192 || !r.require_scalar_type (3, "uint64_t"))
4193 return error_mark_node;
4195 auto mode = r.mode_suffix_id;
4196 if (r.scalar_argument_p (2))
4197 mode = MODE_n;
4198 else if (!r.require_vector_type (2, VECTOR_TYPE_svmfloat8_t))
4199 return error_mark_node;
4201 return r.resolve_to (mode, type, TYPE_SUFFIX_mf8, GROUP_none);
4204 SHAPE (ternary_mfloat8_opt_n)
4206 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:int:quarter>_t, sv<t0:uint:quarter>_t,
4207 uint64_t)
4209 where the final argument is an integer constant expression in the range
4210 [0, 16 / sizeof (<t0>_t) - 1]. */
4211 struct ternary_intq_uintq_lane_def
4212 : public ternary_qq_lane_base<TYPE_signed, TYPE_unsigned>
4214 void
4215 build (function_builder &b, const function_group_info &group) const override
4217 b.add_overloaded_functions (group, MODE_none);
4218 build_all (b, "v0,v0,vqs0,vqu0,su64", group, MODE_none);
4221 SHAPE (ternary_intq_uintq_lane)
4223 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:int:quarter>_t, sv<t0:uint:quarter>_t)
4224 sv<t0>_t svfoo[_n_t0](sv<t0>_t, sv<t0:int:quarter>_t,
4225 <t0:uint:quarter>_t). */
4226 struct ternary_intq_uintq_opt_n_def
4227 : public ternary_resize2_opt_n_base<function_resolver::QUARTER_SIZE,
4228 TYPE_signed, TYPE_unsigned>
4230 void
4231 build (function_builder &b, const function_group_info &group) const override
4233 b.add_overloaded_functions (group, MODE_none);
4234 build_all (b, "v0,v0,vqs0,vqu0", group, MODE_none);
4235 build_all (b, "v0,v0,vqs0,squ0", group, MODE_n);
4238 SHAPE (ternary_intq_uintq_opt_n)
4240 /* svbool_t svfoo[_<t0>](sv<t0>_t, sv<t0>_t, sv<t0>_t, uint64_t)
4242 where the final argument is an integer constant expression in the
4243 range [0, 16 / sizeof (<t0>_t) - 1]. */
4244 struct ternary_lane_def : public overloaded_base<0>
4246 void
4247 build (function_builder &b, const function_group_info &group) const override
4249 b.add_overloaded_functions (group, MODE_none);
4250 build_all (b, "v0,v0,v0,v0,su64", group, MODE_none);
4253 tree
4254 resolve (function_resolver &r) const override
4256 return r.resolve_uniform (3, 1);
4259 bool
4260 check (function_checker &c) const override
4262 return c.require_immediate_lane_index (3, 2);
4265 SHAPE (ternary_lane)
4267 /* svbool_t svfoo[_<t0>](sv<t0>_t, sv<t0>_t, sv<t0>_t, uint64_t, uint64_t)
4269 where the penultimate argument is an integer constant expression in
4270 the range [0, 8 / sizeof (<t0>_t) - 1] and where the final argument
4271 is an integer constant expression in {0, 90, 180, 270}. */
4272 struct ternary_lane_rotate_def : public overloaded_base<0>
4274 void
4275 build (function_builder &b, const function_group_info &group) const override
4277 b.add_overloaded_functions (group, MODE_none);
4278 build_all (b, "v0,v0,v0,v0,su64,su64", group, MODE_none);
4281 tree
4282 resolve (function_resolver &r) const override
4284 return r.resolve_uniform (3, 2);
4287 bool
4288 check (function_checker &c) const override
4290 return (c.require_immediate_lane_index (3, 2, 2)
4291 && c.require_immediate_one_of (4, 0, 90, 180, 270));
4294 SHAPE (ternary_lane_rotate)
4296 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:half>_t, sv<t0:half>_t, uint64_t)
4298 where the final argument is an integer constant expression in the range
4299 [0, 32 / sizeof (<t0>_t) - 1]. */
4300 struct ternary_long_lane_def
4301 : public ternary_resize2_lane_base<function_resolver::HALF_SIZE>
4303 void
4304 build (function_builder &b, const function_group_info &group) const override
4306 b.add_overloaded_functions (group, MODE_none);
4307 build_all (b, "v0,v0,vh0,vh0,su64", group, MODE_none);
4310 bool
4311 check (function_checker &c) const override
4313 return c.require_immediate_lane_index (3, 2);
4316 SHAPE (ternary_long_lane)
4318 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:half>_t, sv<t0:half>_t)
4319 sv<t0>_t svfoo[_n_t0](sv<t0>_t, sv<t0:half>_t, <t0:half>_t)
4321 i.e. a version of the standard ternary shape ternary_opt_n in which
4322 the element type of the last two arguments is the half-sized
4323 equivalent of <t0>. */
4324 struct ternary_long_opt_n_def
4325 : public ternary_resize2_opt_n_base<function_resolver::HALF_SIZE>
4327 void
4328 build (function_builder &b, const function_group_info &group) const override
4330 b.add_overloaded_functions (group, MODE_none);
4331 build_all (b, "v0,v0,vh0,vh0", group, MODE_none);
4332 build_all (b, "v0,v0,vh0,sh0", group, MODE_n);
4335 SHAPE (ternary_long_opt_n)
4337 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0>_t, sv<t0>_t)
4338 sv<t0>_t svfoo[_n_t0](sv<t0>_t, sv<t0>_t, <t0>_t)
4340 i.e. the standard shape for ternary operations that operate on
4341 uniform types. */
4342 struct ternary_opt_n_def : public overloaded_base<0>
4344 void
4345 build (function_builder &b, const function_group_info &group) const override
4347 b.add_overloaded_functions (group, MODE_none);
4348 build_all (b, "v0,v0,v0,v0", group, MODE_none);
4349 build_all (b, "v0,v0,v0,s0", group, MODE_n);
4352 tree
4353 resolve (function_resolver &r) const override
4355 return r.resolve_uniform_opt_n (3);
4358 SHAPE (ternary_opt_n)
4360 /* A choice between:
4362 (1) sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:quarter>_t, sv<t0:quarter>_t,
4363 uint64_t)
4365 (2) sv<t0>_t svfoo[_t0_t1](sv<t0>_t, sv<t1>_t, sv<t1>_t, uint64_t)
4367 where the final argument is an integer constant expression in the range
4368 [0, 16 / sizeof (<t0>_t) - 1]. */
4369 struct ternary_qq_or_011_lane_def : public ternary_qq_lane_base<>
4371 void
4372 build (function_builder &b, const function_group_info &group) const override
4374 b.add_overloaded_functions (group, MODE_none);
4375 if (group.types[0][1] == NUM_TYPE_SUFFIXES)
4376 build_all (b, "v0,v0,vq0,vq0,su64", group, MODE_none);
4377 else
4378 build_all (b, "v0,v0,v1,v1,su64", group, MODE_none);
4381 tree
4382 resolve (function_resolver &r) const override
4384 unsigned int i, nargs;
4385 type_suffix_index type0, type1;
4386 if (!r.check_gp_argument (4, i, nargs)
4387 || (type0 = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
4388 || (type1 = r.infer_vector_type (i + 1)) == NUM_TYPE_SUFFIXES
4389 || !r.require_matching_vector_type (i + 2, i + 1, type1)
4390 || !r.require_integer_immediate (i + 3))
4391 return error_mark_node;
4393 if ((type_suffixes[type0].element_bits
4394 == 4 * type_suffixes[type1].element_bits)
4395 && type_suffixes[type0].tclass == type_suffixes[type1].tclass)
4396 if (tree res = r.lookup_form (MODE_none, type0))
4397 return res;
4399 return r.resolve_to (r.mode_suffix_id, type0, type1);
4402 SHAPE (ternary_qq_or_011_lane)
4404 /* svbool_t svfoo[_<t0>](sv<t0>_t, sv<t0:quarter>_t, sv<t0:quarter>_t,
4405 uint64_t)
4407 where the final argument is an integer constant expression in
4408 {0, 90, 180, 270}. */
4409 struct ternary_qq_lane_rotate_def : public overloaded_base<0>
4411 void
4412 build (function_builder &b, const function_group_info &group) const override
4414 b.add_overloaded_functions (group, MODE_none);
4415 build_all (b, "v0,v0,vq0,vq0,su64,su64", group, MODE_none);
4418 tree
4419 resolve (function_resolver &r) const override
4421 unsigned int i, nargs;
4422 type_suffix_index type;
4423 if (!r.check_gp_argument (5, i, nargs)
4424 || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
4425 || !r.require_derived_vector_type (i + 1, i, type, r.SAME_TYPE_CLASS,
4426 r.QUARTER_SIZE)
4427 || !r.require_derived_vector_type (i + 2, i, type, r.SAME_TYPE_CLASS,
4428 r.QUARTER_SIZE)
4429 || !r.require_integer_immediate (i + 3)
4430 || !r.require_integer_immediate (i + 4))
4431 return error_mark_node;
4433 return r.resolve_to (r.mode_suffix_id, type);
4436 bool
4437 check (function_checker &c) const override
4439 return (c.require_immediate_lane_index (3, 0)
4440 && c.require_immediate_one_of (4, 0, 90, 180, 270));
4443 SHAPE (ternary_qq_lane_rotate)
4445 /* A choice between:
4447 (1) sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:quarter>_t, sv<t0:quarter>_t)
4448 sv<t0>_t svfoo[_n_t0](sv<t0>_t, sv<t0:quarter>_t, <t0:quarter>_t)
4450 i.e. a version of the standard ternary shape ternary_opt_n in which
4451 the element type of the last two arguments is the quarter-sized
4452 equivalent of <t0>.
4454 (2) sv<t0>_t svfoo[_t0_t1](sv<t0>_t, sv<t1>_t, sv<t1>_t)
4456 where the element type of the last two arguments is specified
4457 explicitly. */
4458 struct ternary_qq_opt_n_or_011_def
4459 : public ternary_resize2_opt_n_base<function_resolver::QUARTER_SIZE>
4461 void
4462 build (function_builder &b, const function_group_info &group) const override
4464 b.add_overloaded_functions (group, MODE_none);
4465 if (group.types[0][1] == NUM_TYPE_SUFFIXES)
4467 build_all (b, "v0,v0,vq0,vq0", group, MODE_none);
4468 build_all (b, "v0,v0,vq0,sq0", group, MODE_n);
4470 else
4471 build_all (b, "v0,v0,v1,v1", group, MODE_none);
4474 tree
4475 resolve (function_resolver &r) const override
4477 unsigned int i, nargs;
4478 type_suffix_index type0, type1;
4479 if (!r.check_gp_argument (3, i, nargs)
4480 || (type0 = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
4481 || (type1 = r.infer_vector_type (i + 1)) == NUM_TYPE_SUFFIXES
4482 || !r.require_vector_or_scalar_type (i + 2))
4483 return error_mark_node;
4485 auto mode = r.scalar_argument_p (i + 2) ? MODE_n : MODE_none;
4486 if (mode == MODE_none
4487 && !r.require_matching_vector_type (i + 2, i + 1, type1))
4488 return error_mark_node;
4490 if ((type_suffixes[type0].element_bits
4491 == 4 * type_suffixes[type1].element_bits)
4492 && type_suffixes[type0].tclass == type_suffixes[type1].tclass)
4493 if (tree res = r.lookup_form (mode, type0))
4494 return res;
4496 if (!r.require_nonscalar_type (i + 2))
4497 return error_mark_node;
4499 return r.resolve_to (r.mode_suffix_id, type0, type1);
4502 SHAPE (ternary_qq_opt_n_or_011)
4504 /* svbool_t svfoo[_<t0>](sv<t0>_t, sv<t0:quarter>_t, sv<t0:quarter>_t,
4505 uint64_t)
4507 where the final argument is an integer constant expression in
4508 {0, 90, 180, 270}. */
4509 struct ternary_qq_rotate_def : public overloaded_base<0>
4511 void
4512 build (function_builder &b, const function_group_info &group) const override
4514 b.add_overloaded_functions (group, MODE_none);
4515 build_all (b, "v0,v0,vq0,vq0,su64", group, MODE_none);
4518 tree
4519 resolve (function_resolver &r) const override
4521 unsigned int i, nargs;
4522 type_suffix_index type;
4523 if (!r.check_gp_argument (4, i, nargs)
4524 || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
4525 || !r.require_derived_vector_type (i + 1, i, type, r.SAME_TYPE_CLASS,
4526 r.QUARTER_SIZE)
4527 || !r.require_derived_vector_type (i + 2, i, type, r.SAME_TYPE_CLASS,
4528 r.QUARTER_SIZE)
4529 || !r.require_integer_immediate (i + 3))
4530 return error_mark_node;
4532 return r.resolve_to (r.mode_suffix_id, type);
4535 bool
4536 check (function_checker &c) const override
4538 return c.require_immediate_one_of (3, 0, 90, 180, 270);
4541 SHAPE (ternary_qq_rotate)
4543 /* svbool_t svfoo[_<t0>](sv<t0>_t, sv<t0>_t, sv<t0>_t, uint64_t)
4545 where the final argument is an integer constant expression in
4546 {0, 90, 180, 270}. */
4547 struct ternary_rotate_def : public overloaded_base<0>
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, "v0,v0,v0,v0,su64", group, MODE_none);
4556 tree
4557 resolve (function_resolver &r) const override
4559 return r.resolve_uniform (3, 1);
4562 bool
4563 check (function_checker &c) const override
4565 return c.require_immediate_one_of (3, 0, 90, 180, 270);
4568 SHAPE (ternary_rotate)
4570 /* sv<t0>_t svfoo[_n_t0])(sv<t0>_t, sv<t0>_t, uint64_t)
4572 where the final argument must be an integer constant expression in the
4573 range [0, sizeof (<t0>_t) * 8 - 1]. */
4574 struct ternary_shift_left_imm_def : public ternary_shift_imm_base
4576 bool
4577 check (function_checker &c) const override
4579 unsigned int bits = c.type_suffix (0).element_bits;
4580 return c.require_immediate_range (2, 0, bits - 1);
4583 SHAPE (ternary_shift_left_imm)
4585 /* sv<t0>_t svfoo[_n_t0])(sv<t0>_t, sv<t0>_t, uint64_t)
4587 where the final argument must be an integer constant expression in the
4588 range [1, sizeof (<t0>_t) * 8]. */
4589 struct ternary_shift_right_imm_def : public ternary_shift_imm_base
4591 bool
4592 check (function_checker &c) const override
4594 unsigned int bits = c.type_suffix (0).element_bits;
4595 return c.require_immediate_range (2, 1, bits);
4598 SHAPE (ternary_shift_right_imm)
4600 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0>_t, sv<t0:uint>_t). */
4601 struct ternary_uint_def : public overloaded_base<0>
4603 void
4604 build (function_builder &b, const function_group_info &group) const override
4606 b.add_overloaded_functions (group, MODE_none);
4607 build_all (b, "v0,v0,v0,vu0", group, MODE_none);
4610 tree
4611 resolve (function_resolver &r) const override
4613 unsigned int i, nargs;
4614 type_suffix_index type;
4615 if (!r.check_gp_argument (3, i, nargs)
4616 || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
4617 || !r.require_matching_vector_type (i + 1, i, type)
4618 || !r.require_derived_vector_type (i + 2, i, type, TYPE_unsigned))
4619 return error_mark_node;
4621 return r.resolve_to (r.mode_suffix_id, type);
4624 SHAPE (ternary_uint)
4626 /* sv<t0>_t svfoo[_t0](sv<t0>_t, svu<t0:uint:quarter>_t,
4627 sv<t0:int:quarter>_t). */
4628 struct ternary_uintq_intq_def
4629 : public ternary_resize2_base<function_resolver::QUARTER_SIZE,
4630 TYPE_unsigned, TYPE_signed>
4632 void
4633 build (function_builder &b, const function_group_info &group) const override
4635 b.add_overloaded_functions (group, MODE_none);
4636 build_all (b, "v0,v0,vqu0,vqs0", group, MODE_none);
4639 SHAPE (ternary_uintq_intq)
4641 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:uint:quarter>_t, sv<t0:int:quarter>_t,
4642 uint64_t)
4644 where the final argument is an integer constant expression in the range
4645 [0, 16 / sizeof (<t0>_t) - 1]. */
4646 struct ternary_uintq_intq_lane_def
4647 : public ternary_qq_lane_base<TYPE_unsigned, TYPE_signed>
4649 void
4650 build (function_builder &b, const function_group_info &group) const override
4652 b.add_overloaded_functions (group, MODE_none);
4653 build_all (b, "v0,v0,vqu0,vqs0,su64", group, MODE_none);
4656 SHAPE (ternary_uintq_intq_lane)
4658 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:uint:quarter>_t, sv<t0:int:quarter>_t)
4659 sv<t0>_t svfoo[_n_t0](sv<t0>_t, sv<t0:uint:quarter>_t,
4660 <t0:int:quarter>_t). */
4661 struct ternary_uintq_intq_opt_n_def
4662 : public ternary_resize2_opt_n_base<function_resolver::QUARTER_SIZE,
4663 TYPE_unsigned, TYPE_signed>
4665 void
4666 build (function_builder &b, const function_group_info &group) const override
4668 b.add_overloaded_functions (group, MODE_none);
4669 build_all (b, "v0,v0,vqu0,vqs0", group, MODE_none);
4670 build_all (b, "v0,v0,vqu0,sqs0", group, MODE_n);
4673 SHAPE (ternary_uintq_intq_opt_n)
4675 /* svbool_t svfoo[_<t0>](sv<t0>_t, sv<t0>_t, uint64_t)
4677 where the final argument is an integer constant expression in the
4678 range [0, 7]. */
4679 struct tmad_def : public overloaded_base<0>
4681 void
4682 build (function_builder &b, const function_group_info &group) const override
4684 b.add_overloaded_functions (group, MODE_none);
4685 build_all (b, "v0,v0,v0,su64", group, MODE_none);
4688 tree
4689 resolve (function_resolver &r) const override
4691 return r.resolve_uniform (2, 1);
4694 bool
4695 check (function_checker &c) const override
4697 return c.require_immediate_range (2, 0, 7);
4700 SHAPE (tmad)
4702 /* sv<t0>_t svfoo[_t0](sv<t0>_t)
4704 i.e. the standard shape for unary operations that operate on
4705 uniform types. */
4706 struct unary_def : public overloaded_base<0>
4708 void
4709 build (function_builder &b, const function_group_info &group) const override
4711 b.add_overloaded_functions (group, MODE_none);
4712 build_all (b, "t0,t0", group, MODE_none);
4715 tree
4716 resolve (function_resolver &r) const override
4718 return r.resolve_unary ();
4721 SHAPE (unary)
4723 /* sv<t0>_t svfoo_t0[_t1](sv<t1>_t)
4725 where the target type <t0> must be specified explicitly but the source
4726 type <t1> can be inferred. */
4727 struct unary_convert_def : public overloaded_base<1>
4729 void
4730 build (function_builder &b, const function_group_info &group) const override
4732 b.add_overloaded_functions (group, MODE_none);
4733 build_all (b, "c0,c1", group, MODE_none);
4736 tree
4737 resolve (function_resolver &r) const override
4739 return r.resolve_unary (r.type_suffix (0).tclass,
4740 r.type_suffix (0).element_bits);
4743 SHAPE (unary_convert)
4745 /* sv<t0>_t svfoo_t0[_t1](sv<t0>_t, sv<t1>_t)
4747 This is a version of unary_convert in which the even-indexed
4748 elements are passed in as a first parameter, before any governing
4749 predicate. */
4750 struct unary_convert_narrowt_def : public overloaded_base<1>
4752 bool
4753 has_merge_argument_p (const function_instance &, unsigned int) const override
4755 return true;
4758 void
4759 build (function_builder &b, const function_group_info &group) const override
4761 b.add_overloaded_functions (group, MODE_none);
4762 build_all (b, "v0,v1", group, MODE_none);
4765 tree
4766 resolve (function_resolver &r) const override
4768 return r.resolve_unary (r.type_suffix (0).tclass,
4769 r.type_suffix (0).element_bits, true);
4772 SHAPE (unary_convert_narrowt)
4774 /* sv<t0>_t svfoo_t0[_t1_g](sv<t0>_t, sv<t1>x<g_t, fpm_t)
4776 Similar to unary_convert_narrowt but for tuple arguments with support for
4777 modal floating point. */
4778 struct unary_convertxn_narrowt_def : public overloaded_base<1>
4780 bool
4781 explicit_group_suffix_p () const override
4783 return false;
4786 bool
4787 has_merge_argument_p (const function_instance &, unsigned int) const override
4789 return true;
4792 void
4793 build (function_builder &b, const function_group_info &group) const override
4795 b.add_overloaded_functions (group, MODE_none);
4796 build_all (b, "v0,v0,t1", group, MODE_none);
4799 tree
4800 resolve (function_resolver &r) const override
4802 gcc_assert(r.fpm_mode == FPM_set);
4803 sve_type type;
4804 if (!r.check_num_arguments (3)
4805 || !(type = r.infer_sve_type (1))
4806 || !r.require_scalar_type (2, "uint64_t"))
4807 return error_mark_node;
4809 return r.resolve_to (r.mode_suffix_id, type);
4812 SHAPE (unary_convertxn_narrowt)
4814 /* sv<t0>x<g0>_t svfoo_t0[_t1_g](sv<t1>x<g1>_t)
4816 where the target type <t0> must be specified explicitly but the
4817 source type <t1> can be inferred.
4819 Functions with a group suffix are unpredicated. For them:
4821 - If <t0> is N times wider than <t1>, the return value has N times
4822 more vectors than the argument.
4824 - If <t1> is N times wider than <t0>, the argument has N times
4825 more vectors than the return type. */
4826 struct unary_convertxn_def : public unary_convert_def
4828 bool explicit_group_suffix_p () const override { return false; }
4830 tree
4831 resolve (function_resolver &r) const override
4833 if (r.pred != PRED_none)
4834 return unary_convert_def::resolve (r);
4836 sve_type type;
4837 if (!r.check_num_arguments (1)
4838 || !(type = r.infer_sve_type (0)))
4839 return error_mark_node;
4841 return r.resolve_conversion (r.mode_suffix_id, type);
4844 SHAPE (unary_convertxn)
4846 /* sv<t0>_t svfoo_t0[_t1_g](sv<t1>x<g1>_t)
4848 where the target type <t0> must be specified explicitly but the
4849 source type <t1> can be inferred.
4851 Functions with a group suffix are unpredicated. */
4852 struct unary_convertxn_narrow_def : public unary_convert_def
4854 bool
4855 explicit_group_suffix_p () const override
4857 return false;
4860 void
4861 build (function_builder &b, const function_group_info &group) const override
4863 b.add_overloaded_functions (group, MODE_none);
4864 build_all (b, "v0,t1", group, MODE_none);
4867 tree
4868 resolve (function_resolver &r) const override
4870 gcc_assert(r.fpm_mode == FPM_set);
4871 sve_type type;
4872 if (!r.check_num_arguments (2)
4873 || !(type = r.infer_sve_type (0))
4874 || !r.require_scalar_type (1, "uint64_t"))
4875 return error_mark_node;
4877 return r.resolve_to (r.mode_suffix_id, type);
4880 SHAPE (unary_convertxn_narrow)
4882 /* sv<t0>_t svfoo_<t0>(sv<t0>_t, uint64_t)
4884 where the final argument is an integer constant expression in the
4885 range [0, 16 / sizeof (<t0>_t) - 1]. */
4886 struct unary_lane_def : public overloaded_base<0>
4888 void
4889 build (function_builder &b, const function_group_info &group) const override
4891 b.add_overloaded_functions (group, MODE_none);
4892 build_all (b, "v0,v0,su64", group, MODE_none);
4895 tree
4896 resolve (function_resolver &r) const override
4898 return r.resolve_uniform (1, 1);
4901 bool
4902 check (function_checker &c) const override
4904 return c.require_immediate_lane_index (1, 0);
4907 SHAPE (unary_lane)
4909 /* sv<t0>_t svfoo[_t0](sv<t0:half>_t). */
4910 struct unary_long_def : public overloaded_base<0>
4912 void
4913 build (function_builder &b, const function_group_info &group) const override
4915 b.add_overloaded_functions (group, MODE_none);
4916 build_all (b, "v0,vh0", group, MODE_none);
4919 tree
4920 resolve (function_resolver &r) const override
4922 unsigned int i, nargs;
4923 type_suffix_index type, result_type;
4924 if (!r.check_gp_argument (1, i, nargs)
4925 || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
4926 || (result_type = long_type_suffix (r, type)) == NUM_TYPE_SUFFIXES)
4927 return error_mark_node;
4929 if (tree res = r.lookup_form (r.mode_suffix_id, result_type))
4930 return res;
4932 return r.report_no_such_form (type);
4935 SHAPE (unary_long)
4937 /* sv<t0>_t svfoo[_n]_t0(<t0>_t). */
4938 struct unary_n_def : public overloaded_base<1>
4940 void
4941 build (function_builder &b, const function_group_info &group) const override
4943 /* The "_n" suffix is optional; the full name has it, but the short
4944 name doesn't. */
4945 build_all (b, "v0,s0", group, MODE_n, true);
4948 tree
4949 resolve (function_resolver &) const override
4951 /* The short forms just make "_n" implicit, so no resolution is needed. */
4952 gcc_unreachable ();
4955 SHAPE (unary_n)
4957 /* sv<t0:half>_t svfoo[_t0](sv<t0>_t). */
4958 typedef unary_narrowb_base<> unary_narrowb_def;
4959 SHAPE (unary_narrowb)
4961 /* sv<t0:half>_t svfoo[_t0](sv<t0:half>_t, sv<t0>_t). */
4962 typedef unary_narrowt_base<> unary_narrowt_def;
4963 SHAPE (unary_narrowt)
4965 /* sv<t0:uint:half>_t svfoo[_t0](sv<t0>_t). */
4966 typedef unary_narrowb_base<TYPE_unsigned> unary_narrowb_to_uint_def;
4967 SHAPE (unary_narrowb_to_uint)
4969 /* sv<t0:uint:half>_t svfoo[_t0](sv<t0:uint:half>_t, sv<t0>_t). */
4970 typedef unary_narrowt_base<TYPE_unsigned> unary_narrowt_to_uint_def;
4971 SHAPE (unary_narrowt_to_uint)
4973 /* svbool_t svfoo(svbool_t). */
4974 struct unary_pred_def : public nonoverloaded_base
4976 void
4977 build (function_builder &b, const function_group_info &group) const override
4979 build_all (b, "v0,v0", group, MODE_none);
4982 SHAPE (unary_pred)
4984 /* sv<t0:int>_t svfoo[_t0](sv<t0>_t)
4986 i.e. a version of "unary" in which the returned vector contains
4987 signed integers. */
4988 struct unary_to_int_def : public overloaded_base<0>
4990 void
4991 build (function_builder &b, const function_group_info &group) const override
4993 b.add_overloaded_functions (group, MODE_none);
4994 build_all (b, "vs0,v0", group, MODE_none);
4997 tree
4998 resolve (function_resolver &r) const override
5000 return r.resolve_unary (TYPE_signed);
5003 SHAPE (unary_to_int)
5005 /* sv<t0:uint>_t svfoo[_t0](sv<t0>_t)
5007 i.e. a version of "unary" in which the returned vector contains
5008 unsigned integers. */
5009 struct unary_to_uint_def : public overloaded_base<0>
5011 void
5012 build (function_builder &b, const function_group_info &group) const override
5014 b.add_overloaded_functions (group, MODE_none);
5015 build_all (b, "vu0,v0", group, MODE_none);
5018 tree
5019 resolve (function_resolver &r) const override
5021 return r.resolve_unary (TYPE_unsigned);
5024 SHAPE (unary_to_uint)
5026 /* sv<t0>_t svfoo[_t0](sv<t0:uint>_t)
5028 where <t0> always belongs a certain type class, and where <t0:uint>
5029 therefore uniquely determines <t0>. */
5030 struct unary_uint_def : public overloaded_base<0>
5032 void
5033 build (function_builder &b, const function_group_info &group) const override
5035 b.add_overloaded_functions (group, MODE_none);
5036 build_all (b, "v0,vu0", group, MODE_none);
5039 tree
5040 resolve (function_resolver &r) const override
5042 unsigned int i, nargs;
5043 type_suffix_index type;
5044 if (!r.check_gp_argument (1, i, nargs)
5045 || (type = r.infer_unsigned_vector_type (i)) == NUM_TYPE_SUFFIXES)
5046 return error_mark_node;
5048 /* Search for a valid suffix with the same number of bits as TYPE. */
5049 unsigned int element_bits = type_suffixes[type].element_bits;
5050 if (type_suffixes[type].unsigned_p)
5051 for (unsigned int j = 0; j < NUM_TYPE_SUFFIXES; ++j)
5052 if (type_suffixes[j].element_bits == element_bits)
5053 if (tree res = r.lookup_form (r.mode_suffix_id,
5054 type_suffix_index (j)))
5055 return res;
5057 return r.report_no_such_form (type);
5060 SHAPE (unary_uint)
5062 /* sv<t0>_t svfoo[_<t0>](sv<t0:half>_t)
5064 i.e. a version of "unary" in which the source elements are half the
5065 size of the destination elements, but have the same type class. */
5066 struct unary_widen_def : public overloaded_base<0>
5068 void
5069 build (function_builder &b, const function_group_info &group) const override
5071 b.add_overloaded_functions (group, MODE_none);
5072 build_all (b, "v0,vh0", group, MODE_none);
5075 tree
5076 resolve (function_resolver &r) const override
5078 unsigned int i, nargs;
5079 type_suffix_index type;
5080 if (!r.check_gp_argument (1, i, nargs)
5081 || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES)
5082 return error_mark_node;
5084 /* There is only a single form for predicates. */
5085 if (type == TYPE_SUFFIX_b)
5086 return r.resolve_to (r.mode_suffix_id, type);
5088 if (type_suffixes[type].integer_p
5089 && type_suffixes[type].element_bits < 64)
5091 type_suffix_index wide_suffix
5092 = find_type_suffix (type_suffixes[type].tclass,
5093 type_suffixes[type].element_bits * 2);
5094 if (tree res = r.lookup_form (r.mode_suffix_id, wide_suffix))
5095 return res;
5098 return r.report_no_such_form (type);
5101 SHAPE (unary_widen)
5103 /* void svfoo_t0[_t1](uint64_t, svbool_t, svbool_t, sv<t1>_t)
5105 where the first argument is a ZA tile. */
5106 struct unary_za_m_def : public overloaded_base<1>
5108 void
5109 build (function_builder &b, const function_group_info &group) const override
5111 b.add_overloaded_functions (group, MODE_none);
5112 build_all (b, "_,su64,vp,vp,t1", group, MODE_none);
5115 tree
5116 resolve (function_resolver &r) const override
5118 type_suffix_index type;
5119 if (!r.check_num_arguments (4)
5120 || !r.require_integer_immediate (0)
5121 || !r.require_vector_type (1, VECTOR_TYPE_svbool_t)
5122 || !r.require_vector_type (2, VECTOR_TYPE_svbool_t)
5123 || (type = r.infer_vector_type (3)) == NUM_TYPE_SUFFIXES)
5124 return error_mark_node;
5126 return r.resolve_to (r.mode_suffix_id, r.type_suffix_ids[0], type);
5129 bool
5130 check (function_checker &c) const override
5132 return c.require_immediate_range (0, 0, c.num_za_tiles () - 1);
5135 SHAPE (unary_za_m)
5137 /* void svfoo_t0[_t1]_g(uint32_t, sv<t1>x<g>_t). */
5138 struct unary_za_slice_def : public overloaded_base<1>
5140 void
5141 build (function_builder &b, const function_group_info &group) const override
5143 b.add_overloaded_functions (group, MODE_none);
5144 if (!za_group_is_pure_overload (group))
5145 build_all (b, "_,su32,t1", group, MODE_none);
5148 tree
5149 resolve (function_resolver &r) const override
5151 sve_type type;
5152 if (!r.check_num_arguments (2)
5153 || !r.require_scalar_type (0, "uint32_t")
5154 || !(type = r.infer_tuple_type (1)))
5155 return error_mark_node;
5157 return r.resolve_to (r.mode_suffix_id, type);
5160 SHAPE (unary_za_slice)
5162 /* sv<t0>x<g>_t svfoo[_t0_g](sv<t0>x<g>_t). */
5163 struct unaryxn_def : public unary_def
5165 bool explicit_group_suffix_p () const override { return false; }
5167 tree
5168 resolve (function_resolver &r) const override
5170 if (r.pred != PRED_none)
5171 return unary_def::resolve (r);
5173 sve_type type;
5174 if (!r.check_num_arguments (1)
5175 || !(type = r.infer_sve_type (0)))
5176 return error_mark_node;
5178 return r.resolve_to (r.mode_suffix_id, type);
5181 SHAPE (unaryxn)
5183 /* void svfoo_t0[_t1_g](uint64_t, uint32_t, sv<t1>x<g>_t). */
5184 struct write_za_def : public overloaded_base<1>
5186 void
5187 build (function_builder &b, const function_group_info &group) const override
5189 b.add_overloaded_functions (group, MODE_none);
5190 build_all (b, "_,su64,su32,t1", group, MODE_none);
5193 tree
5194 resolve (function_resolver &r) const override
5196 sve_type type;
5197 if (!r.check_num_arguments (3)
5198 || !r.require_integer_immediate (0)
5199 || !r.require_scalar_type (1, "uint32_t")
5200 || !(type = r.infer_tuple_type (2)))
5201 return error_mark_node;
5203 return r.resolve_to (r.mode_suffix_id, type);
5206 bool
5207 check (function_checker &c) const override
5209 return c.require_immediate_range (0, 0, c.num_za_tiles () - 1);
5212 SHAPE (write_za)
5214 /* void svfoo_t0[_t1](uint64_t, uint32_t, svbool_t, sv<t1>_t)
5216 where the first two fields form a (ZA tile, slice) pair. */
5217 struct write_za_m_def : public overloaded_base<1>
5219 void
5220 build (function_builder &b, const function_group_info &group) const override
5222 b.add_overloaded_functions (group, MODE_none);
5223 build_all (b, "_,su64,su32,vp,t1", group, MODE_none);
5226 tree
5227 resolve (function_resolver &r) const override
5229 type_suffix_index type;
5230 if (!r.check_num_arguments (4)
5231 || !r.require_integer_immediate (0)
5232 || !r.require_scalar_type (1, "uint32_t")
5233 || !r.require_vector_type (2, VECTOR_TYPE_svbool_t)
5234 || (type = r.infer_vector_type (3)) == NUM_TYPE_SUFFIXES)
5235 return error_mark_node;
5237 return r.resolve_to (r.mode_suffix_id, r.type_suffix_ids[0], type);
5240 bool
5241 check (function_checker &c) const override
5243 return c.require_immediate_range (0, 0, c.num_za_tiles () - 1);
5246 SHAPE (write_za_m)
5248 /* void svfoo_t0[_t1_g](uint32_t, sv<t1>x<g>_t). */
5249 struct write_za_slice_def : public overloaded_base<1>
5251 void
5252 build (function_builder &b, const function_group_info &group) const override
5254 b.add_overloaded_functions (group, MODE_none);
5255 build_all (b, "_,su32,t1", group, MODE_none);
5258 tree
5259 resolve (function_resolver &r) const override
5261 sve_type type;
5262 if (!r.check_num_arguments (2)
5263 || !r.require_scalar_type (0, "uint32_t")
5264 || !(type = r.infer_tuple_type (1)))
5265 return error_mark_node;
5267 return r.resolve_to (r.mode_suffix_id, type);
5270 SHAPE (write_za_slice)