xref: /netbsd-src/external/gpl3/gcc/dist/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc (revision 7d62b00eb9ad855ffcd7da46b41e23feb5476fac)
1 /* ACLE support for AArch64 SVE (function shapes)
2    Copyright (C) 2018-2020 Free Software Foundation, Inc.
3 
4    This file is part of GCC.
5 
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.
10 
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.
15 
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/>.  */
19 
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 
33 /* In the comments below, _t0 represents the first type suffix and _t1
34    represents the second.  Square brackets enclose characters that are
35    present in only the full name, not the overloaded name.  Governing
36    predicate arguments and predicate suffixes are not shown, since they
37    depend on the predication type, which is a separate piece of
38    information from the shape.
39 
40    Non-overloaded functions may have additional suffixes beyond the
41    ones shown, if those suffixes don't affect the types in the type
42    signature.  E.g. the predicate form of svtrn1 has a _b<bits> suffix,
43    but this does not affect the prototype, which is always
44    "svbool_t(svbool_t, svbool_t)".  */
45 
46 namespace aarch64_sve {
47 
48 /* Return a representation of "const T *".  */
49 static tree
50 build_const_pointer (tree t)
51 {
52   return build_pointer_type (build_qualified_type (t, TYPE_QUAL_CONST));
53 }
54 
55 /* If INSTANCE has a governing predicate, add it to the list of argument
56    types in ARGUMENT_TYPES.  RETURN_TYPE is the type returned by the
57    function.  */
58 static void
59 apply_predication (const function_instance &instance, tree return_type,
60 		   vec<tree> &argument_types)
61 {
62   if (instance.pred != PRED_none)
63     {
64       argument_types.quick_insert (0, get_svbool_t ());
65       /* For unary merge operations, the first argument is a vector with
66 	 the same type as the result.  For unary_convert_narrowt it also
67 	 provides the "bottom" half of active elements, and is present
68 	 for all types of predication.  */
69       if ((argument_types.length () == 2 && instance.pred == PRED_m)
70 	  || instance.shape == shapes::unary_convert_narrowt)
71 	argument_types.quick_insert (0, return_type);
72     }
73 }
74 
75 /* Parse and move past an element type in FORMAT and return it as a type
76    suffix.  The format is:
77 
78    [01]    - the element type in type suffix 0 or 1 of INSTANCE
79    f<bits> - a floating-point type with the given number of bits
80    f[01]   - a floating-point type with the same width as type suffix 0 or 1
81    B       - bfloat16_t
82    h<elt>  - a half-sized version of <elt>
83    p       - a predicate (represented as TYPE_SUFFIX_b)
84    q<elt>  - a quarter-sized version of <elt>
85    s<bits> - a signed type with the given number of bits
86    s[01]   - a signed type with the same width as type suffix 0 or 1
87    u<bits> - an unsigned type with the given number of bits
88    u[01]   - an unsigned type with the same width as type suffix 0 or 1
89    w<elt>  - a 64-bit version of <elt> if <elt> is integral, otherwise <elt>
90 
91    where <elt> is another element type.  */
92 static type_suffix_index
93 parse_element_type (const function_instance &instance, const char *&format)
94 {
95   int ch = *format++;
96 
97   if (ch == 'f' || ch == 's' || ch == 'u')
98     {
99       type_class_index tclass = (ch == 'f' ? TYPE_float
100 				 : ch == 's' ? TYPE_signed
101 				 : TYPE_unsigned);
102       char *end;
103       unsigned int bits = strtol (format, &end, 10);
104       format = end;
105       if (bits == 0 || bits == 1)
106 	bits = instance.type_suffix (bits).element_bits;
107       return find_type_suffix (tclass, bits);
108     }
109 
110   if (ch == 'w')
111     {
112       type_suffix_index suffix = parse_element_type (instance, format);
113       if (type_suffixes[suffix].integer_p)
114 	return find_type_suffix (type_suffixes[suffix].tclass, 64);
115       return suffix;
116     }
117 
118   if (ch == 'p')
119     return TYPE_SUFFIX_b;
120 
121   if (ch == 'B')
122     return TYPE_SUFFIX_bf16;
123 
124   if (ch == 'q')
125     {
126       type_suffix_index suffix = parse_element_type (instance, format);
127       return find_type_suffix (type_suffixes[suffix].tclass,
128 			       type_suffixes[suffix].element_bits / 4);
129     }
130 
131   if (ch == 'h')
132     {
133       type_suffix_index suffix = parse_element_type (instance, format);
134       /* Widening and narrowing doesn't change the type for predicates;
135 	 everything's still an svbool_t.  */
136       if (suffix == TYPE_SUFFIX_b)
137 	return suffix;
138       return find_type_suffix (type_suffixes[suffix].tclass,
139 			       type_suffixes[suffix].element_bits / 2);
140     }
141 
142   if (ch == '0' || ch == '1')
143     return instance.type_suffix_ids[ch - '0'];
144 
145   gcc_unreachable ();
146 }
147 
148 /* Read and return a type from FORMAT for function INSTANCE.  Advance
149    FORMAT beyond the type string.  The format is:
150 
151    _       - void
152    al      - array pointer for loads
153    ap      - array pointer for prefetches
154    as      - array pointer for stores
155    b       - base vector type (from a _<m0>base suffix)
156    d       - displacement vector type (from a _<m1>index or _<m1>offset suffix)
157    e<name> - an enum with the given name
158    s<elt>  - a scalar type with the given element suffix
159    t<elt>  - a vector or tuple type with given element suffix [*1]
160    v<elt>  - a vector with the given element suffix
161 
162    where <elt> has the format described above parse_element_type
163 
164    [*1] the vectors_per_tuple function indicates whether the type should
165         be a tuple, and if so, how many vectors it should contain.  */
166 static tree
167 parse_type (const function_instance &instance, const char *&format)
168 {
169   int ch = *format++;
170 
171   if (ch == '_')
172     return void_type_node;
173 
174   if (ch == 'a')
175     {
176       ch = *format++;
177       if (ch == 'l')
178 	return build_const_pointer (instance.memory_scalar_type ());
179       if (ch == 'p')
180 	return const_ptr_type_node;
181       if (ch == 's')
182 	return build_pointer_type (instance.memory_scalar_type ());
183       gcc_unreachable ();
184     }
185 
186   if (ch == 'b')
187     return instance.base_vector_type ();
188 
189   if (ch == 'd')
190     return instance.displacement_vector_type ();
191 
192   if (ch == 'e')
193     {
194       if (strncmp (format, "pattern", 7) == 0)
195 	{
196 	  format += 7;
197 	  return acle_svpattern;
198 	}
199       if (strncmp (format, "prfop", 5) == 0)
200 	{
201 	  format += 5;
202 	  return acle_svprfop;
203 	}
204       gcc_unreachable ();
205     }
206 
207   if (ch == 's')
208     {
209       type_suffix_index suffix = parse_element_type (instance, format);
210       return scalar_types[type_suffixes[suffix].vector_type];
211     }
212 
213   if (ch == 't')
214     {
215       type_suffix_index suffix = parse_element_type (instance, format);
216       vector_type_index vector_type = type_suffixes[suffix].vector_type;
217       unsigned int num_vectors = instance.vectors_per_tuple ();
218       return acle_vector_types[num_vectors - 1][vector_type];
219     }
220 
221   if (ch == 'v')
222     {
223       type_suffix_index suffix = parse_element_type (instance, format);
224       return acle_vector_types[0][type_suffixes[suffix].vector_type];
225     }
226 
227   gcc_unreachable ();
228 }
229 
230 /* Read and move past any argument count at FORMAT for the function
231    signature of INSTANCE.  The counts are:
232 
233    *q: one argument per element in a 128-bit quadword (as for svdupq)
234    *t: one argument per vector in a tuple (as for svcreate)
235 
236    Otherwise the count is 1.  */
237 static unsigned int
238 parse_count (const function_instance &instance, const char *&format)
239 {
240   if (format[0] == '*' && format[1] == 'q')
241     {
242       format += 2;
243       return instance.elements_per_vq (0);
244     }
245   if (format[0] == '*' && format[1] == 't')
246     {
247       format += 2;
248       return instance.vectors_per_tuple ();
249     }
250   return 1;
251 }
252 
253 /* Read a type signature for INSTANCE from FORMAT.  Add the argument types
254    to ARGUMENT_TYPES and return the return type.
255 
256    The format is a comma-separated list of types (as for parse_type),
257    with the first type being the return type and the rest being the
258    argument types.  Each argument type can be followed by an optional
259    count (as for parse_count).  */
260 static tree
261 parse_signature (const function_instance &instance, const char *format,
262 		 vec<tree> &argument_types)
263 {
264   tree return_type = parse_type (instance, format);
265   while (format[0] == ',')
266     {
267       format += 1;
268       tree argument_type = parse_type (instance, format);
269       unsigned int count = parse_count (instance, format);
270       for (unsigned int i = 0; i < count; ++i)
271 	argument_types.quick_push (argument_type);
272     }
273   gcc_assert (format[0] == 0);
274   return return_type;
275 }
276 
277 /* Add one function instance for GROUP, using mode suffix MODE_SUFFIX_ID,
278    the type suffixes at index TI and the predication suffix at index PI.
279    The other arguments are as for build_all.  */
280 static void
281 build_one (function_builder &b, const char *signature,
282 	   const function_group_info &group, mode_suffix_index mode_suffix_id,
283 	   unsigned int ti, unsigned int pi, bool force_direct_overloads)
284 {
285   /* Byte forms of svdupq take 16 arguments.  */
286   auto_vec<tree, 16> argument_types;
287   function_instance instance (group.base_name, *group.base, *group.shape,
288 			      mode_suffix_id, group.types[ti],
289 			      group.preds[pi]);
290   tree return_type = parse_signature (instance, signature, argument_types);
291   apply_predication (instance, return_type, argument_types);
292   b.add_unique_function (instance, return_type, argument_types,
293 			 group.required_extensions, force_direct_overloads);
294 }
295 
296 /* GROUP describes some sort of gather or scatter operation.  There are
297    two cases:
298 
299    - If the function has any type suffixes (as for loads and stores), the
300      first function type suffix specifies either a 32-bit or a 64-bit type,
301      which in turn selects either MODE32 or MODE64 as the addressing mode.
302      Add a function instance for every type and predicate combination
303      in GROUP for which the associated addressing mode is not MODE_none.
304 
305    - If the function has no type suffixes (as for prefetches), add one
306      MODE32 form and one MODE64 form for each predication type.
307 
308    The other arguments are as for build_all.  */
309 static void
310 build_32_64 (function_builder &b, const char *signature,
311 	     const function_group_info &group, mode_suffix_index mode32,
312 	     mode_suffix_index mode64, bool force_direct_overloads = false)
313 {
314   for (unsigned int pi = 0; group.preds[pi] != NUM_PREDS; ++pi)
315     if (group.types[0][0] == NUM_TYPE_SUFFIXES)
316       {
317 	gcc_assert (mode32 != MODE_none && mode64 != MODE_none);
318 	build_one (b, signature, group, mode32, 0, pi,
319 		   force_direct_overloads);
320 	build_one (b, signature, group, mode64, 0, pi,
321 		   force_direct_overloads);
322       }
323     else
324       for (unsigned int ti = 0; group.types[ti][0] != NUM_TYPE_SUFFIXES; ++ti)
325 	{
326 	  unsigned int bits = type_suffixes[group.types[ti][0]].element_bits;
327 	  gcc_assert (bits == 32 || bits == 64);
328 	  mode_suffix_index mode = bits == 32 ? mode32 : mode64;
329 	  if (mode != MODE_none)
330 	    build_one (b, signature, group, mode, ti, pi,
331 		       force_direct_overloads);
332 	}
333 }
334 
335 /* For every type and predicate combination in GROUP, add one function
336    that takes a scalar (pointer) base and a signed vector array index,
337    and another that instead takes an unsigned vector array index.
338    The vector array index has the same element size as the first
339    function type suffix.  SIGNATURE is as for build_all.  */
340 static void
341 build_sv_index (function_builder &b, const char *signature,
342 		const function_group_info &group)
343 {
344   build_32_64 (b, signature, group, MODE_s32index, MODE_s64index);
345   build_32_64 (b, signature, group, MODE_u32index, MODE_u64index);
346 }
347 
348 /* Like build_sv_index, but only handle 64-bit types.  */
349 static void
350 build_sv_index64 (function_builder &b, const char *signature,
351 		  const function_group_info &group)
352 {
353   build_32_64 (b, signature, group, MODE_none, MODE_s64index);
354   build_32_64 (b, signature, group, MODE_none, MODE_u64index);
355 }
356 
357 /* Like build_sv_index, but taking vector byte offsets instead of vector
358    array indices.  */
359 static void
360 build_sv_offset (function_builder &b, const char *signature,
361 		 const function_group_info &group)
362 {
363   build_32_64 (b, signature, group, MODE_s32offset, MODE_s64offset);
364   build_32_64 (b, signature, group, MODE_u32offset, MODE_u64offset);
365 }
366 
367 /* Like build_sv_offset, but exclude offsets that must be interpreted
368    as signed (i.e. s32offset).  */
369 static void
370 build_sv_uint_offset (function_builder &b, const char *signature,
371 		      const function_group_info &group)
372 {
373   build_32_64 (b, signature, group, MODE_none, MODE_s64offset);
374   build_32_64 (b, signature, group, MODE_u32offset, MODE_u64offset);
375 }
376 
377 /* For every type and predicate combination in GROUP, add a function
378    that takes a vector base address and no displacement.  The vector
379    base has the same element size as the first type suffix.
380 
381    The other arguments are as for build_all.  */
382 static void
383 build_v_base (function_builder &b, const char *signature,
384 	      const function_group_info &group,
385 	      bool force_direct_overloads = false)
386 {
387   build_32_64 (b, signature, group, MODE_u32base, MODE_u64base,
388 	       force_direct_overloads);
389 }
390 
391 /* Like build_v_base, but for functions that also take a scalar array
392    index.  */
393 static void
394 build_vs_index (function_builder &b, const char *signature,
395 		const function_group_info &group,
396 		bool force_direct_overloads = false)
397 {
398   build_32_64 (b, signature, group, MODE_u32base_index, MODE_u64base_index,
399 	       force_direct_overloads);
400 }
401 
402 /* Like build_v_base, but for functions that also take a scalar byte
403    offset.  */
404 static void
405 build_vs_offset (function_builder &b, const char *signature,
406 		 const function_group_info &group,
407 		 bool force_direct_overloads = false)
408 {
409   build_32_64 (b, signature, group, MODE_u32base_offset, MODE_u64base_offset,
410 	       force_direct_overloads);
411 }
412 
413 /* Add a function instance for every type and predicate combination
414    in GROUP.  Take the function base name from GROUP and the mode suffix
415    from MODE_SUFFIX_ID.  Use SIGNATURE to construct the function signature
416    without a governing predicate, then use apply_predication to add in the
417    predicate.  FORCE_DIRECT_OVERLOADS is true if there is a one-to-one
418    mapping between "short" and "full" names, and if standard overload
419    resolution therefore isn't necessary.  */
420 static void
421 build_all (function_builder &b, const char *signature,
422 	   const function_group_info &group, mode_suffix_index mode_suffix_id,
423 	   bool force_direct_overloads = false)
424 {
425   for (unsigned int pi = 0; group.preds[pi] != NUM_PREDS; ++pi)
426     for (unsigned int ti = 0;
427 	 ti == 0 || group.types[ti][0] != NUM_TYPE_SUFFIXES; ++ti)
428       build_one (b, signature, group, mode_suffix_id, ti, pi,
429 		 force_direct_overloads);
430 }
431 
432 /* TYPE is the largest type suffix associated with the arguments of R,
433    but the result is twice as wide.  Return the associated type suffix
434    if it exists, otherwise report an appropriate error and return
435    NUM_TYPE_SUFFIXES.  */
436 static type_suffix_index
437 long_type_suffix (function_resolver &r, type_suffix_index type)
438 {
439   unsigned int element_bits = type_suffixes[type].element_bits;
440   if (type_suffixes[type].integer_p && element_bits < 64)
441     return find_type_suffix (type_suffixes[type].tclass, element_bits * 2);
442 
443   r.report_no_such_form (type);
444   return NUM_TYPE_SUFFIXES;
445 }
446 
447 /* Declare the function shape NAME, pointing it to an instance
448    of class <NAME>_def.  */
449 #define SHAPE(NAME) \
450   static CONSTEXPR const NAME##_def NAME##_obj; \
451   namespace shapes { const function_shape *const NAME = &NAME##_obj; }
452 
453 /* Base class for functions that are not overloaded.  */
454 struct nonoverloaded_base : public function_shape
455 {
456   bool
457   explicit_type_suffix_p (unsigned int) const OVERRIDE
458   {
459     return true;
460   }
461 
462   tree
463   resolve (function_resolver &) const OVERRIDE
464   {
465     gcc_unreachable ();
466   }
467 };
468 
469 /* Base class for overloaded functions.  Bit N of EXPLICIT_MASK is true
470    if type suffix N appears in the overloaded name.  */
471 template<unsigned int EXPLICIT_MASK>
472 struct overloaded_base : public function_shape
473 {
474   bool
475   explicit_type_suffix_p (unsigned int i) const OVERRIDE
476   {
477     return (EXPLICIT_MASK >> i) & 1;
478   }
479 };
480 
481 /* Base class for adr_index and adr_offset.  */
482 struct adr_base : public overloaded_base<0>
483 {
484   /* The function takes two arguments: a vector base and a vector displacement
485      (either an index or an offset).  Resolve based on them both.  */
486   tree
487   resolve (function_resolver &r) const OVERRIDE
488   {
489     unsigned int i, nargs;
490     mode_suffix_index mode;
491     if (!r.check_gp_argument (2, i, nargs)
492 	|| (mode = r.resolve_adr_address (0)) == MODE_none)
493       return error_mark_node;
494 
495     return r.resolve_to (mode);
496   };
497 };
498 
499 /* Base class for narrowing bottom binary functions that take an
500    immediate second operand.  The result is half the size of input
501    and has class CLASS.  */
502 template<type_class_index CLASS = function_resolver::SAME_TYPE_CLASS>
503 struct binary_imm_narrowb_base : public overloaded_base<0>
504 {
505   void
506   build (function_builder &b, const function_group_info &group) const OVERRIDE
507   {
508     b.add_overloaded_functions (group, MODE_n);
509     STATIC_ASSERT (CLASS == function_resolver::SAME_TYPE_CLASS
510 		   || CLASS == TYPE_unsigned);
511     if (CLASS == TYPE_unsigned)
512       build_all (b, "vhu0,v0,su64", group, MODE_n);
513     else
514       build_all (b, "vh0,v0,su64", group, MODE_n);
515   }
516 
517   tree
518   resolve (function_resolver &r) const OVERRIDE
519   {
520     return r.resolve_uniform (1, 1);
521   }
522 };
523 
524 /* The top equivalent of binary_imm_narrowb_base.  It takes three arguments,
525    with the first being the values of the even elements, which are typically
526    the result of the narrowb operation.  */
527 template<type_class_index CLASS = function_resolver::SAME_TYPE_CLASS>
528 struct binary_imm_narrowt_base : public overloaded_base<0>
529 {
530   void
531   build (function_builder &b, const function_group_info &group) const OVERRIDE
532   {
533     b.add_overloaded_functions (group, MODE_n);
534     STATIC_ASSERT (CLASS == function_resolver::SAME_TYPE_CLASS
535 		   || CLASS == TYPE_unsigned);
536     if (CLASS == TYPE_unsigned)
537       build_all (b, "vhu0,vhu0,v0,su64", group, MODE_n);
538     else
539       build_all (b, "vh0,vh0,v0,su64", group, MODE_n);
540   }
541 
542   tree
543   resolve (function_resolver &r) const OVERRIDE
544   {
545     unsigned int i, nargs;
546     type_suffix_index type;
547     if (!r.check_gp_argument (3, i, nargs)
548 	|| (type = r.infer_vector_type (i + 1)) == NUM_TYPE_SUFFIXES
549 	|| !r.require_derived_vector_type (i, i + 1, type, CLASS, r.HALF_SIZE)
550 	|| !r.require_integer_immediate (i + 2))
551       return error_mark_node;
552 
553     return r.resolve_to (r.mode_suffix_id, type);
554   }
555 };
556 
557 /* Base class for long (i.e. narrow op narrow -> wide) binary functions
558    that take an immediate second operand.  The type suffix specifies
559    the wider type.  */
560 struct binary_imm_long_base : public overloaded_base<0>
561 {
562   void
563   build (function_builder &b, const function_group_info &group) const OVERRIDE
564   {
565     b.add_overloaded_functions (group, MODE_n);
566     build_all (b, "v0,vh0,su64", group, MODE_n);
567   }
568 
569   tree
570   resolve (function_resolver &r) const OVERRIDE
571   {
572     unsigned int i, nargs;
573     type_suffix_index type, result_type;
574     if (!r.check_gp_argument (2, i, nargs)
575 	|| (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
576 	|| !r.require_integer_immediate (i + 1)
577 	|| (result_type = long_type_suffix (r, type)) == NUM_TYPE_SUFFIXES)
578       return error_mark_node;
579 
580     if (tree res = r.lookup_form (r.mode_suffix_id, result_type))
581       return res;
582 
583     return r.report_no_such_form (type);
584   }
585 };
586 
587 /* Base class for inc_dec and inc_dec_pat.  */
588 struct inc_dec_base : public overloaded_base<0>
589 {
590   CONSTEXPR inc_dec_base (bool pat_p) : m_pat_p (pat_p) {}
591 
592   /* Resolve based on the first argument only, which must be either a
593      scalar or a vector.  If it's a scalar, it must be a 32-bit or
594      64-bit integer.  */
595   tree
596   resolve (function_resolver &r) const
597   {
598     unsigned int i, nargs;
599     if (!r.check_gp_argument (m_pat_p ? 3 : 2, i, nargs)
600 	|| !r.require_vector_or_scalar_type (i))
601       return error_mark_node;
602 
603     mode_suffix_index mode;
604     type_suffix_index type;
605     if (r.scalar_argument_p (i))
606       {
607 	mode = MODE_n;
608 	type = r.infer_integer_scalar_type (i);
609       }
610     else
611       {
612 	mode = MODE_none;
613 	type = r.infer_vector_type (i);
614       }
615     if (type == NUM_TYPE_SUFFIXES)
616       return error_mark_node;
617 
618     for (++i; i < nargs; ++i)
619       if (!r.require_integer_immediate (i))
620 	return error_mark_node;
621 
622     return r.resolve_to (mode, type);
623   }
624 
625   bool
626   check (function_checker &c) const OVERRIDE
627   {
628     return c.require_immediate_range (m_pat_p ? 2 : 1, 1, 16);
629   }
630 
631   bool m_pat_p;
632 };
633 
634 /* Base class for load and load_replicate.  */
635 struct load_contiguous_base : public overloaded_base<0>
636 {
637   /* Resolve a call based purely on a pointer argument.  The other arguments
638      are a governing predicate and (for MODE_vnum) a vnum offset.  */
639   tree
640   resolve (function_resolver &r) const OVERRIDE
641   {
642     bool vnum_p = r.mode_suffix_id == MODE_vnum;
643     gcc_assert (r.mode_suffix_id == MODE_none || vnum_p);
644 
645     unsigned int i, nargs;
646     type_suffix_index type;
647     if (!r.check_gp_argument (vnum_p ? 2 : 1, i, nargs)
648 	|| (type = r.infer_pointer_type (i)) == NUM_TYPE_SUFFIXES
649 	|| (vnum_p && !r.require_scalar_type (i + 1, "int64_t")))
650       return error_mark_node;
651 
652     return r.resolve_to (r.mode_suffix_id, type);
653   }
654 };
655 
656 /* Base class for gather loads that take a scalar base and a vector
657    displacement (either an offset or an index).  */
658 struct load_gather_sv_base : public overloaded_base<0>
659 {
660   tree
661   resolve (function_resolver &r) const OVERRIDE
662   {
663     unsigned int i, nargs;
664     mode_suffix_index mode;
665     type_suffix_index type;
666     if (!r.check_gp_argument (2, i, nargs)
667 	|| (type = r.infer_pointer_type (i, true)) == NUM_TYPE_SUFFIXES
668 	|| (mode = r.resolve_sv_displacement (i + 1, type, true),
669 	    mode == MODE_none))
670       return error_mark_node;
671 
672     return r.resolve_to (mode, type);
673   }
674 };
675 
676 /* Base class for load_ext_gather_index and load_ext_gather_offset,
677    which differ only in the units of the displacement.  */
678 struct load_ext_gather_base : public overloaded_base<1>
679 {
680   /* Resolve a gather load that takes one of:
681 
682      - a scalar pointer base and a vector displacement
683      - a vector base with no displacement or
684      - a vector base and a scalar displacement
685 
686      The function has an explicit type suffix that determines the type
687      of the loaded data.  */
688   tree
689   resolve (function_resolver &r) const OVERRIDE
690   {
691     /* No resolution is needed for a vector base with no displacement;
692        there's a one-to-one mapping between short and long names.  */
693     gcc_assert (r.displacement_units () != UNITS_none);
694 
695     type_suffix_index type = r.type_suffix_ids[0];
696 
697     unsigned int i, nargs;
698     mode_suffix_index mode;
699     if (!r.check_gp_argument (2, i, nargs)
700 	|| (mode = r.resolve_gather_address (i, type, true)) == MODE_none)
701       return error_mark_node;
702 
703     return r.resolve_to (mode, type);
704   }
705 };
706 
707 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:quarter>_t,
708 		       sv<t0:quarter>_t)  (for integer t0)
709    sv<t0>_t svmmla[_t0](sv<t0>_t, sv<t0>_t, sv<t0>_t)  (for floating-point t0)
710 
711    The functions act like the equivalent of "ternary_qq" for integer elements
712    and normal vector-only ternary functions for floating-point elements.  */
713 struct mmla_def : public overloaded_base<0>
714 {
715   void
716   build (function_builder &b, const function_group_info &group) const OVERRIDE
717   {
718     b.add_overloaded_functions (group, MODE_none);
719     /* svmmla is distributed over several extensions.  Allow the common
720        denominator to define the overloaded svmmla function without
721        defining any specific versions.  */
722     if (group.types[0][0] != NUM_TYPE_SUFFIXES)
723       {
724 	if (type_suffixes[group.types[0][0]].float_p)
725 	  build_all (b, "v0,v0,v0,v0", group, MODE_none);
726 	else
727 	  build_all (b, "v0,v0,vq0,vq0", group, MODE_none);
728       }
729   }
730 
731   tree
732   resolve (function_resolver &r) const OVERRIDE
733   {
734     unsigned int i, nargs;
735     type_suffix_index type;
736     if (!r.check_gp_argument (3, i, nargs)
737 	|| (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES)
738       return error_mark_node;
739 
740     /* Make sure that the function exists now, since not all forms
741        follow a set pattern after this point.  */
742     tree res = r.resolve_to (r.mode_suffix_id, type);
743     if (res == error_mark_node)
744       return res;
745 
746     bool float_p = type_suffixes[type].float_p;
747     unsigned int modifier = float_p ? r.SAME_SIZE : r.QUARTER_SIZE;
748     if (!r.require_derived_vector_type (i + 1, i, type, r.SAME_TYPE_CLASS,
749 					modifier)
750 	|| !r.require_derived_vector_type (i + 2, i, type, r.SAME_TYPE_CLASS,
751 					   modifier))
752       return error_mark_node;
753 
754     return res;
755   }
756 };
757 SHAPE (mmla)
758 
759 /* Base class for prefetch_gather_index and prefetch_gather_offset,
760    which differ only in the units of the displacement.  */
761 struct prefetch_gather_base : public overloaded_base<0>
762 {
763   /* Resolve a gather prefetch that takes one of:
764 
765      - a scalar pointer base (const void *) and a vector displacement
766      - a vector base with no displacement or
767      - a vector base and a scalar displacement
768 
769      The prefetch operation is the final argument.  This is purely a
770      mode-based resolution; there are no type suffixes.  */
771   tree
772   resolve (function_resolver &r) const OVERRIDE
773   {
774     bool has_displacement_p = r.displacement_units () != UNITS_none;
775 
776     unsigned int i, nargs;
777     mode_suffix_index mode;
778     if (!r.check_gp_argument (has_displacement_p ? 3 : 2, i, nargs)
779 	|| (mode = r.resolve_gather_address (i, NUM_TYPE_SUFFIXES,
780 					     false)) == MODE_none
781 	|| !r.require_integer_immediate (nargs - 1))
782       return error_mark_node;
783 
784     return r.resolve_to (mode);
785   }
786 };
787 
788 /* Wraps BASE to provide a narrowing shift right function.  Argument N
789    is an immediate shift amount in the range [1, sizeof(<t0>_t) * 4].  */
790 template<typename BASE, unsigned int N>
791 struct shift_right_imm_narrow_wrapper : public BASE
792 {
793   bool
794   check (function_checker &c) const OVERRIDE
795   {
796     unsigned int bits = c.type_suffix (0).element_bits / 2;
797     return c.require_immediate_range (N, 1, bits);
798   }
799 };
800 
801 /* Base class for store_scatter_index and store_scatter_offset,
802    which differ only in the units of the displacement.  */
803 struct store_scatter_base : public overloaded_base<0>
804 {
805   /* Resolve a scatter store that takes one of:
806 
807      - a scalar pointer base and a vector displacement
808      - a vector base with no displacement or
809      - a vector base and a scalar displacement
810 
811      The stored data is the final argument, and it determines the
812      type suffix.  */
813   tree
814   resolve (function_resolver &r) const OVERRIDE
815   {
816     bool has_displacement_p = r.displacement_units () != UNITS_none;
817 
818     unsigned int i, nargs;
819     mode_suffix_index mode;
820     type_suffix_index type;
821     if (!r.check_gp_argument (has_displacement_p ? 3 : 2, i, nargs)
822 	|| (type = r.infer_sd_vector_type (nargs - 1)) == NUM_TYPE_SUFFIXES
823 	|| (mode = r.resolve_gather_address (i, type, false)) == MODE_none)
824       return error_mark_node;
825 
826     return r.resolve_to (mode, type);
827   }
828 };
829 
830 /* Base class for ternary operations in which the final argument is an
831    immediate shift amount.  The derived class should check the range.  */
832 struct ternary_shift_imm_base : public overloaded_base<0>
833 {
834   void
835   build (function_builder &b, const function_group_info &group) const OVERRIDE
836   {
837     b.add_overloaded_functions (group, MODE_n);
838     build_all (b, "v0,v0,v0,su64", group, MODE_n);
839   }
840 
841   tree
842   resolve (function_resolver &r) const OVERRIDE
843   {
844     return r.resolve_uniform (2, 1);
845   }
846 };
847 
848 /* Base class for ternary operations in which the first argument has the
849    same element type as the result, and in which the second and third
850    arguments have an element type that is derived the first.
851 
852    MODIFIER is the number of element bits in the second and third
853    arguments, or a function_resolver modifier that says how this
854    precision is derived from the first argument's elements.
855 
856    TYPE_CLASS2 and TYPE_CLASS3 are the type classes of the second and
857    third arguments, or function_resolver::SAME_TYPE_CLASS if the type
858    class is the same as the first argument.  */
859 template<unsigned int MODIFIER,
860 	 type_class_index TYPE_CLASS2 = function_resolver::SAME_TYPE_CLASS,
861 	 type_class_index TYPE_CLASS3 = function_resolver::SAME_TYPE_CLASS>
862 struct ternary_resize2_opt_n_base : public overloaded_base<0>
863 {
864   tree
865   resolve (function_resolver &r) const OVERRIDE
866   {
867     unsigned int i, nargs;
868     type_suffix_index type;
869     if (!r.check_gp_argument (3, i, nargs)
870 	|| (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
871 	|| !r.require_derived_vector_type (i + 1, i, type, TYPE_CLASS2,
872 					   MODIFIER))
873       return error_mark_node;
874 
875     return r.finish_opt_n_resolution (i + 2, i, type, TYPE_CLASS3, MODIFIER);
876   }
877 };
878 
879 /* Like ternary_resize2_opt_n_base, but for functions that don't take
880    a final scalar argument.  */
881 template<unsigned int MODIFIER,
882 	 type_class_index TYPE_CLASS2 = function_resolver::SAME_TYPE_CLASS,
883 	 type_class_index TYPE_CLASS3 = function_resolver::SAME_TYPE_CLASS>
884 struct ternary_resize2_base : public overloaded_base<0>
885 {
886   tree
887   resolve (function_resolver &r) const OVERRIDE
888   {
889     unsigned int i, nargs;
890     type_suffix_index type;
891     if (!r.check_gp_argument (3, i, nargs)
892 	|| (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
893 	|| !r.require_derived_vector_type (i + 1, i, type, TYPE_CLASS2,
894 					   MODIFIER)
895 	|| !r.require_derived_vector_type (i + 2, i, type, TYPE_CLASS3,
896 					   MODIFIER))
897       return error_mark_node;
898 
899     return r.resolve_to (r.mode_suffix_id, type);
900   }
901 };
902 
903 /* Like ternary_resize2_opt_n_base, but for functions that take a final
904    lane argument.  */
905 template<unsigned int MODIFIER,
906 	 type_class_index TYPE_CLASS2 = function_resolver::SAME_TYPE_CLASS,
907 	 type_class_index TYPE_CLASS3 = function_resolver::SAME_TYPE_CLASS>
908 struct ternary_resize2_lane_base : public overloaded_base<0>
909 {
910   tree
911   resolve (function_resolver &r) const OVERRIDE
912   {
913     unsigned int i, nargs;
914     type_suffix_index type;
915     if (!r.check_gp_argument (4, i, nargs)
916 	|| (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
917 	|| !r.require_derived_vector_type (i + 1, i, type, TYPE_CLASS2,
918 					   MODIFIER)
919 	|| !r.require_derived_vector_type (i + 2, i, type, TYPE_CLASS3,
920 					   MODIFIER)
921 	|| !r.require_integer_immediate (i + 3))
922       return error_mark_node;
923 
924     return r.resolve_to (r.mode_suffix_id, type);
925   }
926 };
927 
928 /* A specialization of ternary_resize2_lane_base for bfloat16 elements,
929    indexed in groups of N elements.  */
930 template<unsigned int N>
931 struct ternary_bfloat_lane_base
932   : public ternary_resize2_lane_base<16, TYPE_bfloat, TYPE_bfloat>
933 {
934   void
935   build (function_builder &b, const function_group_info &group) const OVERRIDE
936   {
937     b.add_overloaded_functions (group, MODE_none);
938     build_all (b, "v0,v0,vB,vB,su64", group, MODE_none);
939   }
940 
941   bool
942   check (function_checker &c) const OVERRIDE
943   {
944     return c.require_immediate_lane_index (3, N);
945   }
946 };
947 
948 /* A specialization of ternary_resize2_lane_base for quarter-sized
949    elements.  */
950 template<type_class_index TYPE_CLASS2 = function_resolver::SAME_TYPE_CLASS,
951 	 type_class_index TYPE_CLASS3 = function_resolver::SAME_TYPE_CLASS>
952 struct ternary_qq_lane_base
953   : public ternary_resize2_lane_base<function_resolver::QUARTER_SIZE,
954 				     TYPE_CLASS2, TYPE_CLASS3>
955 {
956   bool
957   check (function_checker &c) const OVERRIDE
958   {
959     return c.require_immediate_lane_index (3, 4);
960   }
961 };
962 
963 /* Base class for narrowing bottom unary functions.  The result is half
964    the size of input and has class CLASS.  */
965 template<type_class_index CLASS = function_resolver::SAME_TYPE_CLASS>
966 struct unary_narrowb_base : public overloaded_base<0>
967 {
968   void
969   build (function_builder &b, const function_group_info &group) const OVERRIDE
970   {
971     b.add_overloaded_functions (group, MODE_none);
972     STATIC_ASSERT (CLASS == function_resolver::SAME_TYPE_CLASS
973 		   || CLASS == TYPE_unsigned);
974     if (CLASS == TYPE_unsigned)
975       build_all (b, "vhu0,v0", group, MODE_none);
976     else
977       build_all (b, "vh0,v0", group, MODE_none);
978   }
979 
980   tree
981   resolve (function_resolver &r) const OVERRIDE
982   {
983     return r.resolve_unary (CLASS, r.HALF_SIZE);
984   }
985 };
986 
987 /* The top equivalent of unary_imm_narrowb_base.  All forms take the values
988    of the even elements as an extra argument, before any governing predicate.
989    These even elements are typically the result of the narrowb operation.  */
990 template<type_class_index CLASS = function_resolver::SAME_TYPE_CLASS>
991 struct unary_narrowt_base : public overloaded_base<0>
992 {
993   void
994   build (function_builder &b, const function_group_info &group) const OVERRIDE
995   {
996     b.add_overloaded_functions (group, MODE_none);
997     STATIC_ASSERT (CLASS == function_resolver::SAME_TYPE_CLASS
998 		   || CLASS == TYPE_unsigned);
999     if (CLASS == TYPE_unsigned)
1000       build_all (b, "vhu0,vhu0,v0", group, MODE_none);
1001     else
1002       build_all (b, "vh0,vh0,v0", group, MODE_none);
1003   }
1004 
1005   tree
1006   resolve (function_resolver &r) const OVERRIDE
1007   {
1008     unsigned int i, nargs;
1009     type_suffix_index type;
1010     if (!r.check_gp_argument (2, i, nargs)
1011 	|| (type = r.infer_vector_type (i + 1)) == NUM_TYPE_SUFFIXES
1012 	|| !r.require_derived_vector_type (i, i + 1, type, CLASS, r.HALF_SIZE))
1013       return error_mark_node;
1014 
1015     return r.resolve_to (r.mode_suffix_id, type);
1016   }
1017 };
1018 
1019 /* sv<m0>_t svfoo[_m0base]_[m1]index(sv<m0>_t, sv<m1>_t)
1020 
1021    for all valid combinations of vector base type <m0> and vector
1022    displacement type <m1>.  */
1023 struct adr_index_def : public adr_base
1024 {
1025   void
1026   build (function_builder &b, const function_group_info &group) const OVERRIDE
1027   {
1028     b.add_overloaded_functions (group, MODE_index);
1029     build_all (b, "b,b,d", group, MODE_u32base_s32index);
1030     build_all (b, "b,b,d", group, MODE_u32base_u32index);
1031     build_all (b, "b,b,d", group, MODE_u64base_s64index);
1032     build_all (b, "b,b,d", group, MODE_u64base_u64index);
1033   }
1034 };
1035 SHAPE (adr_index)
1036 
1037 /* sv<m0>_t svfoo[_m0base]_[m1]offset(sv<m0>_t, sv<m1>_t).
1038 
1039    for all valid combinations of vector base type <m0> and vector
1040    displacement type <m1>.  */
1041 struct adr_offset_def : public adr_base
1042 {
1043   void
1044   build (function_builder &b, const function_group_info &group) const OVERRIDE
1045   {
1046     b.add_overloaded_functions (group, MODE_offset);
1047     build_all (b, "b,b,d", group, MODE_u32base_s32offset);
1048     build_all (b, "b,b,d", group, MODE_u32base_u32offset);
1049     build_all (b, "b,b,d", group, MODE_u64base_s64offset);
1050     build_all (b, "b,b,d", group, MODE_u64base_u64offset);
1051   }
1052 };
1053 SHAPE (adr_offset)
1054 
1055 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0>_t)
1056 
1057    i.e. a binary operation with uniform types, but with no scalar form.  */
1058 struct binary_def : public overloaded_base<0>
1059 {
1060   void
1061   build (function_builder &b, const function_group_info &group) const OVERRIDE
1062   {
1063     b.add_overloaded_functions (group, MODE_none);
1064     build_all (b, "v0,v0,v0", group, MODE_none);
1065   }
1066 
1067   tree
1068   resolve (function_resolver &r) const OVERRIDE
1069   {
1070     return r.resolve_uniform (2);
1071   }
1072 };
1073 SHAPE (binary)
1074 
1075 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:int>_t)
1076    sv<t0>_t svfoo[_n_t0](sv<t0>_t, <t0:int>_t).
1077 
1078    i.e. a version of the standard binary shape binary_opt_n in which
1079    the final argument is always a signed integer.  */
1080 struct binary_int_opt_n_def : public overloaded_base<0>
1081 {
1082   void
1083   build (function_builder &b, const function_group_info &group) const OVERRIDE
1084   {
1085     b.add_overloaded_functions (group, MODE_none);
1086     build_all (b, "v0,v0,vs0", group, MODE_none);
1087     build_all (b, "v0,v0,ss0", group, MODE_n);
1088   }
1089 
1090   tree
1091   resolve (function_resolver &r) const OVERRIDE
1092   {
1093     unsigned int i, nargs;
1094     type_suffix_index type;
1095     if (!r.check_gp_argument (2, i, nargs)
1096 	|| (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES)
1097       return error_mark_node;
1098 
1099     return r.finish_opt_n_resolution (i + 1, i, type, TYPE_signed);
1100   }
1101 };
1102 SHAPE (binary_int_opt_n)
1103 
1104 /* sv<t0>_t svfoo_<t0>(sv<t0>_t, sv<t0>_t, uint64_t)
1105 
1106    where the final argument is an integer constant expression in the
1107    range [0, 16 / sizeof (<t0>_t) - 1].  */
1108 struct binary_lane_def : public overloaded_base<0>
1109 {
1110   void
1111   build (function_builder &b, const function_group_info &group) const OVERRIDE
1112   {
1113     b.add_overloaded_functions (group, MODE_none);
1114     build_all (b, "v0,v0,v0,su64", group, MODE_none);
1115   }
1116 
1117   tree
1118   resolve (function_resolver &r) const OVERRIDE
1119   {
1120     return r.resolve_uniform (2, 1);
1121   }
1122 
1123   bool
1124   check (function_checker &c) const OVERRIDE
1125   {
1126     return c.require_immediate_lane_index (2);
1127   }
1128 };
1129 SHAPE (binary_lane)
1130 
1131 /* sv<t0>_t svfoo[_t0](sv<t0:half>_t, sv<t0:half>_t, uint64_t).
1132 
1133    where the final argument is an integer constant expression in the
1134    range [0, 32 / sizeof (<t0>_t) - 1].  */
1135 struct binary_long_lane_def : public overloaded_base<0>
1136 {
1137   void
1138   build (function_builder &b, const function_group_info &group) const OVERRIDE
1139   {
1140     b.add_overloaded_functions (group, MODE_none);
1141     build_all (b, "v0,vh0,vh0,su64", group, MODE_none);
1142   }
1143 
1144   tree
1145   resolve (function_resolver &r) const OVERRIDE
1146   {
1147     unsigned int i, nargs;
1148     type_suffix_index type, result_type;
1149     if (!r.check_gp_argument (3, i, nargs)
1150 	|| (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
1151 	|| !r.require_matching_vector_type (i + 1, type)
1152 	|| !r.require_integer_immediate (i + 2)
1153 	|| (result_type = long_type_suffix (r, type)) == NUM_TYPE_SUFFIXES)
1154       return error_mark_node;
1155 
1156     if (tree res = r.lookup_form (r.mode_suffix_id, result_type))
1157       return res;
1158 
1159     return r.report_no_such_form (type);
1160   }
1161 
1162   bool
1163   check (function_checker &c) const OVERRIDE
1164   {
1165     return c.require_immediate_lane_index (2);
1166   }
1167 };
1168 SHAPE (binary_long_lane)
1169 
1170 /* sv<t0>_t svfoo[_t0](sv<t0:half>_t, sv<t0:half>_t)
1171    sv<t0>_t svfoo[_n_t0](sv<t0:half>_t, <t0:half>_t).  */
1172 struct binary_long_opt_n_def : public overloaded_base<0>
1173 {
1174   void
1175   build (function_builder &b, const function_group_info &group) const OVERRIDE
1176   {
1177     b.add_overloaded_functions (group, MODE_none);
1178     build_all (b, "v0,vh0,vh0", group, MODE_none);
1179     build_all (b, "v0,vh0,sh0", group, MODE_n);
1180   }
1181 
1182   tree
1183   resolve (function_resolver &r) const OVERRIDE
1184   {
1185     unsigned int i, nargs;
1186     type_suffix_index type, result_type;
1187     if (!r.check_gp_argument (2, i, nargs)
1188 	|| (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
1189 	|| (result_type = long_type_suffix (r, type)) == NUM_TYPE_SUFFIXES)
1190       return error_mark_node;
1191 
1192     return r.finish_opt_n_resolution (i + 1, i, type, r.SAME_TYPE_CLASS,
1193 				      r.SAME_SIZE, result_type);
1194   }
1195 };
1196 SHAPE (binary_long_opt_n)
1197 
1198 /* sv<t0>_t svfoo[_n_t0](sv<t0>_t, <t0>_t).
1199 
1200    i.e. a binary operation in which the final argument is always a scalar
1201    rather than a vector.  */
1202 struct binary_n_def : public overloaded_base<0>
1203 {
1204   void
1205   build (function_builder &b, const function_group_info &group) const OVERRIDE
1206   {
1207     b.add_overloaded_functions (group, MODE_n);
1208     build_all (b, "v0,v0,s0", group, MODE_n);
1209   }
1210 
1211   tree
1212   resolve (function_resolver &r) const OVERRIDE
1213   {
1214     unsigned int i, nargs;
1215     type_suffix_index type;
1216     if (!r.check_gp_argument (2, i, nargs)
1217 	|| (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
1218 	|| !r.require_derived_scalar_type (i + 1, r.SAME_TYPE_CLASS))
1219       return error_mark_node;
1220 
1221     return r.resolve_to (r.mode_suffix_id, type);
1222   }
1223 };
1224 SHAPE (binary_n)
1225 
1226 /* sv<t0:half>_t svfoo[_t0](sv<t0>_t, sv<t0>_t)
1227    sv<t0:half>_t svfoo[_n_t0](sv<t0>_t, <t0>_t)
1228 
1229    i.e. a version of binary_opt_n in which the output elements are half the
1230    width of the input elements.  */
1231 struct binary_narrowb_opt_n_def : public overloaded_base<0>
1232 {
1233   void
1234   build (function_builder &b, const function_group_info &group) const OVERRIDE
1235   {
1236     b.add_overloaded_functions (group, MODE_none);
1237     build_all (b, "vh0,v0,v0", group, MODE_none);
1238     build_all (b, "vh0,v0,s0", group, MODE_n);
1239   }
1240 
1241   tree
1242   resolve (function_resolver &r) const OVERRIDE
1243   {
1244     return r.resolve_uniform_opt_n (2);
1245   }
1246 };
1247 SHAPE (binary_narrowb_opt_n)
1248 
1249 /* sv<t0:half>_t svfoo[_t0](sv<t0:half>_t, sv<t0>_t, sv<t0>_t)
1250    sv<t0:half>_t svfoo[_n_t0](sv<t0:half>_t, sv<t0>_t, <t0>_t)
1251 
1252    This is the "top" counterpart to binary_narrowb_opt_n.  */
1253 struct binary_narrowt_opt_n_def : public overloaded_base<0>
1254 {
1255   void
1256   build (function_builder &b, const function_group_info &group) const OVERRIDE
1257   {
1258     b.add_overloaded_functions (group, MODE_none);
1259     build_all (b, "vh0,vh0,v0,v0", group, MODE_none);
1260     build_all (b, "vh0,vh0,v0,s0", group, MODE_n);
1261   }
1262 
1263   tree
1264   resolve (function_resolver &r) const OVERRIDE
1265   {
1266     unsigned int i, nargs;
1267     type_suffix_index type;
1268     if (!r.check_gp_argument (3, i, nargs)
1269 	|| (type = r.infer_vector_type (i + 1)) == NUM_TYPE_SUFFIXES
1270 	|| !r.require_derived_vector_type (i, i + 1, type, r.SAME_TYPE_CLASS,
1271 					   r.HALF_SIZE))
1272       return error_mark_node;
1273 
1274     return r.finish_opt_n_resolution (i + 2, i + 1, type);
1275   }
1276 };
1277 SHAPE (binary_narrowt_opt_n)
1278 
1279 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0>_t)
1280    sv<t0>_t svfoo[_n_t0](sv<t0>_t, <t0>_t)
1281 
1282    i.e. the standard shape for binary operations that operate on
1283    uniform types.  */
1284 struct binary_opt_n_def : public overloaded_base<0>
1285 {
1286   void
1287   build (function_builder &b, const function_group_info &group) const OVERRIDE
1288   {
1289     b.add_overloaded_functions (group, MODE_none);
1290     build_all (b, "v0,v0,v0", group, MODE_none);
1291     /* _b functions do not have an _n form, but are classified as
1292        binary_opt_n so that they can be overloaded with vector
1293        functions.  */
1294     if (group.types[0][0] == TYPE_SUFFIX_b)
1295       gcc_assert (group.types[0][1] == NUM_TYPE_SUFFIXES);
1296     else
1297       build_all (b, "v0,v0,s0", group, MODE_n);
1298   }
1299 
1300   tree
1301   resolve (function_resolver &r) const OVERRIDE
1302   {
1303     return r.resolve_uniform_opt_n (2);
1304   }
1305 };
1306 SHAPE (binary_opt_n)
1307 
1308 /* svbool_t svfoo(svbool_t, svbool_t).  */
1309 struct binary_pred_def : public nonoverloaded_base
1310 {
1311   void
1312   build (function_builder &b, const function_group_info &group) const OVERRIDE
1313   {
1314     build_all (b, "v0,v0,v0", group, MODE_none);
1315   }
1316 };
1317 SHAPE (binary_pred)
1318 
1319 /* sv<t0>_t svfoo[_<t0>](sv<t0>_t, sv<t0>_t, uint64_t)
1320 
1321    where the final argument must be 90 or 270.  */
1322 struct binary_rotate_def : public overloaded_base<0>
1323 {
1324   void
1325   build (function_builder &b, const function_group_info &group) const OVERRIDE
1326   {
1327     b.add_overloaded_functions (group, MODE_none);
1328     build_all (b, "v0,v0,v0,su64", group, MODE_none);
1329   }
1330 
1331   tree
1332   resolve (function_resolver &r) const OVERRIDE
1333   {
1334     return r.resolve_uniform (2, 1);
1335   }
1336 
1337   bool
1338   check (function_checker &c) const OVERRIDE
1339   {
1340     return c.require_immediate_either_or (2, 90, 270);
1341   }
1342 };
1343 SHAPE (binary_rotate)
1344 
1345 /* sv<t0>_t svfoo_t0(<t0>_t, <t0>_t)
1346 
1347    i.e. a binary function that takes two scalars and returns a vector.
1348    An explicit type suffix is required.  */
1349 struct binary_scalar_def : public nonoverloaded_base
1350 {
1351   void
1352   build (function_builder &b, const function_group_info &group) const OVERRIDE
1353   {
1354     build_all (b, "v0,s0,s0", group, MODE_none);
1355   }
1356 };
1357 SHAPE (binary_scalar)
1358 
1359 /* sv<t0:uint>_t svfoo[_t0](sv<t0>_t, sv<t0>_t).
1360 
1361    i.e. a version of "binary" that returns unsigned integers.  */
1362 struct binary_to_uint_def : public overloaded_base<0>
1363 {
1364   void
1365   build (function_builder &b, const function_group_info &group) const OVERRIDE
1366   {
1367     b.add_overloaded_functions (group, MODE_none);
1368     build_all (b, "vu0,v0,v0", group, MODE_none);
1369   }
1370 
1371   tree
1372   resolve (function_resolver &r) const OVERRIDE
1373   {
1374     return r.resolve_uniform (2);
1375   }
1376 };
1377 SHAPE (binary_to_uint)
1378 
1379 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:uint>_t)
1380 
1381    i.e. a version of "binary" in which the final argument is always an
1382    unsigned integer.  */
1383 struct binary_uint_def : public overloaded_base<0>
1384 {
1385   void
1386   build (function_builder &b, const function_group_info &group) const OVERRIDE
1387   {
1388     b.add_overloaded_functions (group, MODE_none);
1389     build_all (b, "v0,v0,vu0", group, MODE_none);
1390   }
1391 
1392   tree
1393   resolve (function_resolver &r) const OVERRIDE
1394   {
1395     unsigned int i, nargs;
1396     type_suffix_index type;
1397     if (!r.check_gp_argument (2, i, nargs)
1398 	|| (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
1399 	|| !r.require_derived_vector_type (i + 1, i, type, TYPE_unsigned))
1400       return error_mark_node;
1401 
1402     return r.resolve_to (r.mode_suffix_id, type);
1403   }
1404 };
1405 SHAPE (binary_uint)
1406 
1407 /* sv<t0>_t svfoo[_t0](sv<t0>_t, <t0:uint>_t)
1408 
1409    i.e. a version of binary_n in which the final argument is always an
1410    unsigned integer.  */
1411 struct binary_uint_n_def : public overloaded_base<0>
1412 {
1413   void
1414   build (function_builder &b, const function_group_info &group) const OVERRIDE
1415   {
1416     b.add_overloaded_functions (group, MODE_none);
1417     build_all (b, "v0,v0,su0", group, MODE_none);
1418   }
1419 
1420   tree
1421   resolve (function_resolver &r) const OVERRIDE
1422   {
1423     unsigned int i, nargs;
1424     type_suffix_index type;
1425     if (!r.check_gp_argument (2, i, nargs)
1426 	|| (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
1427 	|| !r.require_derived_scalar_type (i + 1, TYPE_unsigned))
1428       return error_mark_node;
1429 
1430     return r.resolve_to (r.mode_suffix_id, type);
1431   }
1432 };
1433 SHAPE (binary_uint_n)
1434 
1435 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:uint>_t)
1436    sv<t0>_t svfoo[_n_t0](sv<t0>_t, <t0:uint>_t)
1437 
1438    i.e. a version of the standard binary shape binary_opt_n in which
1439    the final argument is always an unsigned integer.  */
1440 struct binary_uint_opt_n_def : public overloaded_base<0>
1441 {
1442   void
1443   build (function_builder &b, const function_group_info &group) const OVERRIDE
1444   {
1445     b.add_overloaded_functions (group, MODE_none);
1446     build_all (b, "v0,v0,vu0", group, MODE_none);
1447     build_all (b, "v0,v0,su0", group, MODE_n);
1448   }
1449 
1450   tree
1451   resolve (function_resolver &r) const OVERRIDE
1452   {
1453     unsigned int i, nargs;
1454     type_suffix_index type;
1455     if (!r.check_gp_argument (2, i, nargs)
1456 	|| (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES)
1457       return error_mark_node;
1458 
1459     return r.finish_opt_n_resolution (i + 1, i, type, TYPE_unsigned);
1460   }
1461 };
1462 SHAPE (binary_uint_opt_n)
1463 
1464 /* sv<t0>_t svfoo[_t0](sv<t0>_t, uint64_t).
1465 
1466    i.e. a version of binary_n in which the final argument is always
1467    a 64-bit unsigned integer.  */
1468 struct binary_uint64_n_def : public overloaded_base<0>
1469 {
1470   void
1471   build (function_builder &b, const function_group_info &group) const OVERRIDE
1472   {
1473     b.add_overloaded_functions (group, MODE_none);
1474     build_all (b, "v0,v0,su64", group, MODE_none);
1475   }
1476 
1477   tree
1478   resolve (function_resolver &r) const OVERRIDE
1479   {
1480     unsigned int i, nargs;
1481     type_suffix_index type;
1482     if (!r.check_gp_argument (2, i, nargs)
1483 	|| (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
1484 	|| !r.require_scalar_type (i + 1, "uint64_t"))
1485       return error_mark_node;
1486 
1487     return r.resolve_to (r.mode_suffix_id, type);
1488   }
1489 };
1490 SHAPE (binary_uint64_n)
1491 
1492 /* sv<t0>_t svfoo[_t0](sv<t0>_t, svuint64_t)
1493    sv<t0>_t svfoo[_n_t0](sv<t0>_t, uint64_t)
1494 
1495    i.e. a version of the standard binary shape binary_opt_n in which
1496    the final argument is always a uint64_t.  */
1497 struct binary_uint64_opt_n_def : public overloaded_base<0>
1498 {
1499   void
1500   build (function_builder &b, const function_group_info &group) const OVERRIDE
1501   {
1502     b.add_overloaded_functions (group, MODE_none);
1503     build_all (b, "v0,v0,vu64", group, MODE_none);
1504     build_all (b, "v0,v0,su64", group, MODE_n);
1505   }
1506 
1507   tree
1508   resolve (function_resolver &r) const OVERRIDE
1509   {
1510     unsigned int i, nargs;
1511     type_suffix_index type;
1512     if (!r.check_gp_argument (2, i, nargs)
1513 	|| (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES)
1514       return error_mark_node;
1515 
1516     return r.finish_opt_n_resolution (i + 1, i, type, TYPE_unsigned, 64);
1517   }
1518 };
1519 SHAPE (binary_uint64_opt_n)
1520 
1521 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:half>_t).  */
1522 struct binary_wide_def : public overloaded_base<0>
1523 {
1524   void
1525   build (function_builder &b, const function_group_info &group) const OVERRIDE
1526   {
1527     b.add_overloaded_functions (group, MODE_none);
1528     build_all (b, "v0,v0,vh0", group, MODE_none);
1529   }
1530 
1531   tree
1532   resolve (function_resolver &r) const OVERRIDE
1533   {
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_vector_type (i + 1, i, type, r.SAME_TYPE_CLASS,
1539 					   r.HALF_SIZE))
1540       return error_mark_node;
1541 
1542     return r.resolve_to (r.mode_suffix_id, type);
1543   }
1544 };
1545 SHAPE (binary_wide)
1546 
1547 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:half>_t)
1548    sv<t0>_t svfoo[_n_t0](sv<t0>_t, <t0:half>_t).  */
1549 struct binary_wide_opt_n_def : public overloaded_base<0>
1550 {
1551   void
1552   build (function_builder &b, const function_group_info &group) const OVERRIDE
1553   {
1554     b.add_overloaded_functions (group, MODE_none);
1555     build_all (b, "v0,v0,vh0", group, MODE_none);
1556     build_all (b, "v0,v0,sh0", group, MODE_n);
1557   }
1558 
1559   tree
1560   resolve (function_resolver &r) const OVERRIDE
1561   {
1562     unsigned int i, nargs;
1563     type_suffix_index type;
1564     if (!r.check_gp_argument (2, i, nargs)
1565 	|| (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES)
1566       return error_mark_node;
1567 
1568     return r.finish_opt_n_resolution (i + 1, i, type, r.SAME_TYPE_CLASS,
1569 				      r.HALF_SIZE);
1570   }
1571 };
1572 SHAPE (binary_wide_opt_n)
1573 
1574 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0>_t)
1575    <t0>_t svfoo[_n_t0](<t0>_t, sv<t0>_t).  */
1576 struct clast_def : public overloaded_base<0>
1577 {
1578   void
1579   build (function_builder &b, const function_group_info &group) const OVERRIDE
1580   {
1581     b.add_overloaded_functions (group, MODE_none);
1582     build_all (b, "v0,v0,v0", group, MODE_none);
1583     build_all (b, "s0,s0,v0", group, MODE_n);
1584   }
1585 
1586   tree
1587   resolve (function_resolver &r) const OVERRIDE
1588   {
1589     unsigned int i, nargs;
1590     if (!r.check_gp_argument (2, i, nargs)
1591 	|| !r.require_vector_or_scalar_type (i))
1592       return error_mark_node;
1593 
1594     if (r.scalar_argument_p (i))
1595       {
1596 	type_suffix_index type;
1597 	if (!r.require_derived_scalar_type (i, r.SAME_TYPE_CLASS)
1598 	    || (type = r.infer_vector_type (i + 1)) == NUM_TYPE_SUFFIXES)
1599 	  return error_mark_node;
1600 	return r.resolve_to (MODE_n, type);
1601       }
1602     else
1603       {
1604 	type_suffix_index type;
1605 	if ((type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
1606 	    || !r.require_matching_vector_type (i + 1, type))
1607 	  return error_mark_node;
1608 	return r.resolve_to (MODE_none, type);
1609       }
1610   }
1611 };
1612 SHAPE (clast)
1613 
1614 /* svbool_t svfoo[_t0](sv<t0>_t, sv<t0>_t).  */
1615 struct compare_def : public overloaded_base<0>
1616 {
1617   void
1618   build (function_builder &b, const function_group_info &group) const OVERRIDE
1619   {
1620     b.add_overloaded_functions (group, MODE_none);
1621     build_all (b, "vp,v0,v0", group, MODE_none);
1622   }
1623 
1624   tree
1625   resolve (function_resolver &r) const OVERRIDE
1626   {
1627     return r.resolve_uniform (2);
1628   }
1629 };
1630 SHAPE (compare)
1631 
1632 /* svbool_t svfoo[_t0](sv<t0>_t, sv<t0>_t)
1633    svbool_t svfoo[_n_t0](sv<t0>_t, <t0>_t)
1634 
1635    i.e. a comparison between two vectors, or between a vector and a scalar.  */
1636 struct compare_opt_n_def : public overloaded_base<0>
1637 {
1638   void
1639   build (function_builder &b, const function_group_info &group) const OVERRIDE
1640   {
1641     b.add_overloaded_functions (group, MODE_none);
1642     build_all (b, "vp,v0,v0", group, MODE_none);
1643     build_all (b, "vp,v0,s0", group, MODE_n);
1644   }
1645 
1646   tree
1647   resolve (function_resolver &r) const OVERRIDE
1648   {
1649     return r.resolve_uniform_opt_n (2);
1650   }
1651 };
1652 SHAPE (compare_opt_n)
1653 
1654 /* svbool_t svfoo[_t0](const <t0>_t *, const <t0>_t *).  */
1655 struct compare_ptr_def : public overloaded_base<0>
1656 {
1657   void
1658   build (function_builder &b, const function_group_info &group) const OVERRIDE
1659   {
1660     b.add_overloaded_functions (group, MODE_none);
1661     build_all (b, "vp,al,al", group, MODE_none);
1662   }
1663 
1664   tree
1665   resolve (function_resolver &r) const OVERRIDE
1666   {
1667     unsigned int i, nargs;
1668     type_suffix_index type;
1669     if (!r.check_gp_argument (2, i, nargs)
1670 	|| (type = r.infer_pointer_type (i)) == NUM_TYPE_SUFFIXES
1671 	|| !r.require_matching_pointer_type (i + 1, i, type))
1672       return error_mark_node;
1673 
1674     return r.resolve_to (r.mode_suffix_id, type);
1675   }
1676 };
1677 SHAPE (compare_ptr)
1678 
1679 /* svbool_t svfoo_t0[_t1](<t1>_t, <t1>_t)
1680 
1681    where _t0 is a _b<bits> suffix that describes the predicate result.
1682    There is no direct relationship between the element sizes of _t0
1683    and _t1.  */
1684 struct compare_scalar_def : public overloaded_base<1>
1685 {
1686   void
1687   build (function_builder &b, const function_group_info &group) const OVERRIDE
1688   {
1689     b.add_overloaded_functions (group, MODE_none);
1690     build_all (b, "vp,s1,s1", group, MODE_none);
1691   }
1692 
1693   tree
1694   resolve (function_resolver &r) const OVERRIDE
1695   {
1696     unsigned int i, nargs;
1697     type_suffix_index type;
1698     if (!r.check_gp_argument (2, i, nargs)
1699 	|| (type = r.infer_integer_scalar_type (i)) == NUM_TYPE_SUFFIXES
1700 	|| !r.require_matching_integer_scalar_type (i + 1, i, type))
1701       return error_mark_node;
1702 
1703     return r.resolve_to (r.mode_suffix_id, r.type_suffix_ids[0], type);
1704   }
1705 };
1706 SHAPE (compare_scalar)
1707 
1708 /* svbool_t svfoo[_t0](sv<t0>_t, svint64_t)  (for signed t0)
1709    svbool_t svfoo[_n_t0](sv<t0>_t, int64_t)  (for signed t0)
1710    svbool_t svfoo[_t0](sv<t0>_t, svuint64_t)  (for unsigned t0)
1711    svbool_t svfoo[_n_t0](sv<t0>_t, uint64_t)  (for unsigned t0)
1712 
1713    i.e. a comparison in which the second argument is 64 bits.  */
1714 struct compare_wide_opt_n_def : public overloaded_base<0>
1715 {
1716   void
1717   build (function_builder &b, const function_group_info &group) const OVERRIDE
1718   {
1719     b.add_overloaded_functions (group, MODE_none);
1720     build_all (b, "vp,v0,vw0", group, MODE_none);
1721     build_all (b, "vp,v0,sw0", group, MODE_n);
1722   }
1723 
1724   tree
1725   resolve (function_resolver &r) const OVERRIDE
1726   {
1727     unsigned int i, nargs;
1728     type_suffix_index type;
1729     if (!r.check_gp_argument (2, i, nargs)
1730 	|| (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES)
1731       return error_mark_node;
1732 
1733     return r.finish_opt_n_resolution (i + 1, i, type, r.SAME_TYPE_CLASS, 64);
1734   }
1735 };
1736 SHAPE (compare_wide_opt_n)
1737 
1738 /* uint64_t svfoo().  */
1739 struct count_inherent_def : public nonoverloaded_base
1740 {
1741   void
1742   build (function_builder &b, const function_group_info &group) const OVERRIDE
1743   {
1744     build_all (b, "su64", group, MODE_none);
1745   }
1746 };
1747 SHAPE (count_inherent)
1748 
1749 /* uint64_t svfoo(enum svpattern).  */
1750 struct count_pat_def : public nonoverloaded_base
1751 {
1752   void
1753   build (function_builder &b, const function_group_info &group) const OVERRIDE
1754   {
1755     build_all (b, "su64,epattern", group, MODE_none);
1756   }
1757 };
1758 SHAPE (count_pat)
1759 
1760 /* uint64_t svfoo(svbool_t).  */
1761 struct count_pred_def : public nonoverloaded_base
1762 {
1763   void
1764   build (function_builder &b, const function_group_info &group) const OVERRIDE
1765   {
1766     build_all (b, "su64,vp", group, MODE_none);
1767   }
1768 };
1769 SHAPE (count_pred)
1770 
1771 /* uint64_t svfoo[_t0](sv<t0>_t).  */
1772 struct count_vector_def : public overloaded_base<0>
1773 {
1774   void
1775   build (function_builder &b, const function_group_info &group) const OVERRIDE
1776   {
1777     b.add_overloaded_functions (group, MODE_none);
1778     build_all (b, "su64,v0", group, MODE_none);
1779   }
1780 
1781   tree
1782   resolve (function_resolver &r) const OVERRIDE
1783   {
1784     return r.resolve_uniform (1);
1785   }
1786 };
1787 SHAPE (count_vector)
1788 
1789 /* sv<t0>xN_t svfoo[_t0](sv<t0>_t, ..., sv<t0>_t)
1790 
1791    where there are N arguments in total.  */
1792 struct create_def : public overloaded_base<0>
1793 {
1794   void
1795   build (function_builder &b, const function_group_info &group) const OVERRIDE
1796   {
1797     b.add_overloaded_functions (group, MODE_none);
1798     build_all (b, "t0,v0*t", group, MODE_none);
1799   }
1800 
1801   tree
1802   resolve (function_resolver &r) const OVERRIDE
1803   {
1804     return r.resolve_uniform (r.vectors_per_tuple ());
1805   }
1806 };
1807 SHAPE (create)
1808 
1809 /* sv<t0>_t svfoo[_n]_t0(<t0>_t, ..., <t0>_t)
1810 
1811    where there are enough arguments to fill 128 bits of data (or to
1812    control 128 bits of data in the case of predicates).  */
1813 struct dupq_def : public overloaded_base<1>
1814 {
1815   void
1816   build (function_builder &b, const function_group_info &group) const OVERRIDE
1817   {
1818     /* The "_n" suffix is optional; the full name has it, but the short
1819        name doesn't.  */
1820     build_all (b, "v0,s0*q", group, MODE_n, true);
1821   }
1822 
1823   tree
1824   resolve (function_resolver &) const OVERRIDE
1825   {
1826     /* The short forms just make "_n" implicit, so no resolution is needed.  */
1827     gcc_unreachable ();
1828   }
1829 };
1830 SHAPE (dupq)
1831 
1832 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0>_t, uint64_t)
1833 
1834    where the final argument is an integer constant expression that when
1835    multiplied by the number of bytes in t0 is in the range [0, 255].  */
1836 struct ext_def : public overloaded_base<0>
1837 {
1838   void
1839   build (function_builder &b, const function_group_info &group) const OVERRIDE
1840   {
1841     b.add_overloaded_functions (group, MODE_none);
1842     build_all (b, "v0,v0,v0,su64", group, MODE_none);
1843   }
1844 
1845   tree
1846   resolve (function_resolver &r) const OVERRIDE
1847   {
1848     return r.resolve_uniform (2, 1);
1849   }
1850 
1851   bool
1852   check (function_checker &c) const OVERRIDE
1853   {
1854     unsigned int bytes = c.type_suffix (0).element_bytes;
1855     return c.require_immediate_range (2, 0, 256 / bytes - 1);
1856   }
1857 };
1858 SHAPE (ext)
1859 
1860 /* <t0>_t svfoo[_t0](<t0>_t, sv<t0>_t).  */
1861 struct fold_left_def : public overloaded_base<0>
1862 {
1863   void
1864   build (function_builder &b, const function_group_info &group) const OVERRIDE
1865   {
1866     b.add_overloaded_functions (group, MODE_none);
1867     build_all (b, "s0,s0,v0", group, MODE_none);
1868   }
1869 
1870   tree
1871   resolve (function_resolver &r) const OVERRIDE
1872   {
1873     unsigned int i, nargs;
1874     type_suffix_index type;
1875     if (!r.check_gp_argument (2, i, nargs)
1876 	|| !r.require_derived_scalar_type (i, r.SAME_TYPE_CLASS)
1877 	|| (type = r.infer_vector_type (i + 1)) == NUM_TYPE_SUFFIXES)
1878       return error_mark_node;
1879 
1880     return r.resolve_to (r.mode_suffix_id, type);
1881   }
1882 };
1883 SHAPE (fold_left)
1884 
1885 /* sv<t0>_t svfoo[_t0](sv<t0>xN_t, uint64_t)
1886 
1887    where the final argument is an integer constant expression in
1888    the range [0, N - 1].  */
1889 struct get_def : public overloaded_base<0>
1890 {
1891   void
1892   build (function_builder &b, const function_group_info &group) const OVERRIDE
1893   {
1894     b.add_overloaded_functions (group, MODE_none);
1895     build_all (b, "v0,t0,su64", group, MODE_none);
1896   }
1897 
1898   tree
1899   resolve (function_resolver &r) const OVERRIDE
1900   {
1901     unsigned int i, nargs;
1902     type_suffix_index type;
1903     if (!r.check_gp_argument (2, i, nargs)
1904 	|| (type = r.infer_tuple_type (i)) == NUM_TYPE_SUFFIXES
1905 	|| !r.require_integer_immediate (i + 1))
1906       return error_mark_node;
1907 
1908     return r.resolve_to (r.mode_suffix_id, type);
1909   }
1910 
1911   bool
1912   check (function_checker &c) const OVERRIDE
1913   {
1914     unsigned int nvectors = c.vectors_per_tuple ();
1915     return c.require_immediate_range (1, 0, nvectors - 1);
1916   }
1917 };
1918 SHAPE (get)
1919 
1920 /* sv<t0>_t svfoo[_t0](sv<t0>_t, uint64_t)
1921    <t0>_t svfoo[_n_t0](<t0>_t, uint64_t)
1922 
1923    where the t0 in the vector form is a signed or unsigned integer
1924    whose size is tied to the [bhwd] suffix of "svfoo".  */
1925 struct inc_dec_def : public inc_dec_base
1926 {
1927   CONSTEXPR inc_dec_def () : inc_dec_base (false) {}
1928 
1929   void
1930   build (function_builder &b, const function_group_info &group) const OVERRIDE
1931   {
1932     b.add_overloaded_functions (group, MODE_none);
1933     /* These functions are unusual in that the type suffixes for
1934        the scalar and vector forms are not related.  The vector
1935        form always has exactly two potential suffixes while the
1936        scalar form always has four.  */
1937     if (group.types[2][0] == NUM_TYPE_SUFFIXES)
1938       build_all (b, "v0,v0,su64", group, MODE_none);
1939     else
1940       build_all (b, "s0,s0,su64", group, MODE_n);
1941   }
1942 };
1943 SHAPE (inc_dec)
1944 
1945 /* sv<t0>_t svfoo[_t0](sv<t0>_t, enum svpattern, uint64_t)
1946    <t0>_t svfoo[_n_t0](<t0>_t, enum svpattern, uint64_t)
1947 
1948    where the t0 in the vector form is a signed or unsigned integer
1949    whose size is tied to the [bhwd] suffix of "svfoo".  */
1950 struct inc_dec_pat_def : public inc_dec_base
1951 {
1952   CONSTEXPR inc_dec_pat_def () : inc_dec_base (true) {}
1953 
1954   void
1955   build (function_builder &b, const function_group_info &group) const OVERRIDE
1956   {
1957     b.add_overloaded_functions (group, MODE_none);
1958     /* These functions are unusual in that the type suffixes for
1959        the scalar and vector forms are not related.  The vector
1960        form always has exactly two potential suffixes while the
1961        scalar form always has four.  */
1962     if (group.types[2][0] == NUM_TYPE_SUFFIXES)
1963       build_all (b, "v0,v0,epattern,su64", group, MODE_none);
1964     else
1965       build_all (b, "s0,s0,epattern,su64", group, MODE_n);
1966   }
1967 };
1968 SHAPE (inc_dec_pat)
1969 
1970 /* sv<t0>_t svfoo[_t0](sv<t0>_t, svbool_t).  */
1971 struct inc_dec_pred_def : public overloaded_base<0>
1972 {
1973   void
1974   build (function_builder &b, const function_group_info &group) const OVERRIDE
1975   {
1976     b.add_overloaded_functions (group, MODE_none);
1977     build_all (b, "v0,v0,vp", group, MODE_none);
1978   }
1979 
1980   tree
1981   resolve (function_resolver &r) const OVERRIDE
1982   {
1983     unsigned int i, nargs;
1984     type_suffix_index type;
1985     if (!r.check_gp_argument (2, i, nargs)
1986 	|| (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
1987 	|| !r.require_vector_type (i + 1, VECTOR_TYPE_svbool_t))
1988       return error_mark_node;
1989 
1990     return r.resolve_to (r.mode_suffix_id, type);
1991   }
1992 };
1993 SHAPE (inc_dec_pred)
1994 
1995 /* <t0>_t svfoo[_n_t0]_t1(<t0>_t, svbool_t)
1996 
1997    where _t1 is a _b<bits> suffix that describes the svbool_t argument.  */
1998 struct inc_dec_pred_scalar_def : public overloaded_base<2>
1999 {
2000   void
2001   build (function_builder &b, const function_group_info &group) const OVERRIDE
2002   {
2003     b.add_overloaded_functions (group, MODE_n);
2004     build_all (b, "s0,s0,vp", group, MODE_n);
2005   }
2006 
2007   tree
2008   resolve (function_resolver &r) const OVERRIDE
2009   {
2010     unsigned int i, nargs;
2011     type_suffix_index type;
2012     if (!r.check_gp_argument (2, i, nargs)
2013 	|| (type = r.infer_integer_scalar_type (i)) == NUM_TYPE_SUFFIXES
2014 	|| !r.require_vector_type (i + 1, VECTOR_TYPE_svbool_t))
2015       return error_mark_node;
2016 
2017     return r.resolve_to (r.mode_suffix_id, type, r.type_suffix_ids[1]);
2018   }
2019 };
2020 SHAPE (inc_dec_pred_scalar)
2021 
2022 /* sv<t0>[xN]_t svfoo_t0().  */
2023 struct inherent_def : public nonoverloaded_base
2024 {
2025   void
2026   build (function_builder &b, const function_group_info &group) const OVERRIDE
2027   {
2028     build_all (b, "t0", group, MODE_none);
2029   }
2030 };
2031 SHAPE (inherent)
2032 
2033 /* svbool_t svfoo[_b]().  */
2034 struct inherent_b_def : public overloaded_base<0>
2035 {
2036   void
2037   build (function_builder &b, const function_group_info &group) const OVERRIDE
2038   {
2039     /* The "_b" suffix is optional; the full name has it, but the short
2040        name doesn't.  */
2041     build_all (b, "v0", group, MODE_none, true);
2042   }
2043 
2044   tree
2045   resolve (function_resolver &) const OVERRIDE
2046   {
2047     /* The short forms just make "_b" implicit, so no resolution is needed.  */
2048     gcc_unreachable ();
2049   }
2050 };
2051 SHAPE (inherent_b)
2052 
2053 /* sv<t0>[xN]_t svfoo[_t0](const <t0>_t *)
2054    sv<t0>[xN]_t svfoo_vnum[_t0](const <t0>_t *, int64_t).  */
2055 struct load_def : public load_contiguous_base
2056 {
2057   void
2058   build (function_builder &b, const function_group_info &group) const OVERRIDE
2059   {
2060     b.add_overloaded_functions (group, MODE_none);
2061     b.add_overloaded_functions (group, MODE_vnum);
2062     build_all (b, "t0,al", group, MODE_none);
2063     build_all (b, "t0,al,ss64", group, MODE_vnum);
2064   }
2065 };
2066 SHAPE (load)
2067 
2068 /* sv<t0>_t svfoo_t0(const <X>_t *)
2069    sv<t0>_t svfoo_vnum_t0(const <X>_t *, int64_t)
2070 
2071    where <X> is determined by the function base name.  */
2072 struct load_ext_def : public nonoverloaded_base
2073 {
2074   void
2075   build (function_builder &b, const function_group_info &group) const OVERRIDE
2076   {
2077     build_all (b, "t0,al", group, MODE_none);
2078     build_all (b, "t0,al,ss64", group, MODE_vnum);
2079   }
2080 };
2081 SHAPE (load_ext)
2082 
2083 /* sv<t0>_t svfoo_[s32]index_t0(const <X>_t *, svint32_t)
2084    sv<t0>_t svfoo_[s64]index_t0(const <X>_t *, svint64_t)
2085    sv<t0>_t svfoo_[u32]index_t0(const <X>_t *, svuint32_t)
2086    sv<t0>_t svfoo_[u64]index_t0(const <X>_t *, svuint64_t)
2087 
2088    sv<t0>_t svfoo[_u32base]_index_t0(svuint32_t, int64_t)
2089    sv<t0>_t svfoo[_u64base]_index_t0(svuint64_t, int64_t)
2090 
2091    where <X> is determined by the function base name.  */
2092 struct load_ext_gather_index_def : public load_ext_gather_base
2093 {
2094   void
2095   build (function_builder &b, const function_group_info &group) const OVERRIDE
2096   {
2097     b.add_overloaded_functions (group, MODE_index);
2098     build_sv_index (b, "t0,al,d", group);
2099     build_vs_index (b, "t0,b,ss64", group);
2100   }
2101 };
2102 SHAPE (load_ext_gather_index)
2103 
2104 /* sv<t0>_t svfoo_[s64]index_t0(const <X>_t *, svint64_t)
2105    sv<t0>_t svfoo_[u64]index_t0(const <X>_t *, svuint64_t)
2106 
2107    sv<t0>_t svfoo[_u32base]_index_t0(svuint32_t, int64_t)
2108    sv<t0>_t svfoo[_u64base]_index_t0(svuint64_t, int64_t)
2109 
2110    where <X> is determined by the function base name.  This is
2111    load_ext_gather_index that doesn't support 32-bit vector indices.  */
2112 struct load_ext_gather_index_restricted_def : public load_ext_gather_base
2113 {
2114   void
2115   build (function_builder &b, const function_group_info &group) const OVERRIDE
2116   {
2117     b.add_overloaded_functions (group, MODE_index);
2118     build_sv_index64 (b, "t0,al,d", group);
2119     build_vs_index (b, "t0,b,ss64", group);
2120   }
2121 };
2122 SHAPE (load_ext_gather_index_restricted)
2123 
2124 /* sv<t0>_t svfoo_[s32]offset_t0(const <X>_t *, svint32_t)
2125    sv<t0>_t svfoo_[s64]offset_t0(const <X>_t *, svint64_t)
2126    sv<t0>_t svfoo_[u32]offset_t0(const <X>_t *, svuint32_t)
2127    sv<t0>_t svfoo_[u64]offset_t0(const <X>_t *, svuint64_t)
2128 
2129    sv<t0>_t svfoo[_u32base]_t0(svuint32_t)
2130    sv<t0>_t svfoo[_u64base]_t0(svuint64_t)
2131 
2132    sv<t0>_t svfoo[_u32base]_offset_t0(svuint32_t, int64_t)
2133    sv<t0>_t svfoo[_u64base]_offset_t0(svuint64_t, int64_t)
2134 
2135    where <X> is determined by the function base name.  */
2136 struct load_ext_gather_offset_def : public load_ext_gather_base
2137 {
2138   void
2139   build (function_builder &b, const function_group_info &group) const OVERRIDE
2140   {
2141     b.add_overloaded_functions (group, MODE_offset);
2142     build_sv_offset (b, "t0,al,d", group);
2143     build_v_base (b, "t0,b", group, true);
2144     build_vs_offset (b, "t0,b,ss64", group);
2145   }
2146 };
2147 SHAPE (load_ext_gather_offset)
2148 
2149 /* sv<t0>_t svfoo_[s64]offset_t0(const <X>_t *, svint64_t)
2150    sv<t0>_t svfoo_[u32]offset_t0(const <X>_t *, svuint32_t)
2151    sv<t0>_t svfoo_[u64]offset_t0(const <X>_t *, svuint64_t)
2152 
2153    sv<t0>_t svfoo[_u32base]_t0(svuint32_t)
2154    sv<t0>_t svfoo[_u64base]_t0(svuint64_t)
2155 
2156    sv<t0>_t svfoo[_u32base]_offset_t0(svuint32_t, int64_t)
2157    sv<t0>_t svfoo[_u64base]_offset_t0(svuint64_t, int64_t)
2158 
2159    where <X> is determined by the function base name.  This is
2160    load_ext_gather_offset without the s32 vector offset form.  */
2161 struct load_ext_gather_offset_restricted_def : public load_ext_gather_base
2162 {
2163   void
2164   build (function_builder &b, const function_group_info &group) const OVERRIDE
2165   {
2166     b.add_overloaded_functions (group, MODE_offset);
2167     build_sv_uint_offset (b, "t0,al,d", group);
2168     build_v_base (b, "t0,b", group, true);
2169     build_vs_offset (b, "t0,b,ss64", group);
2170   }
2171 };
2172 SHAPE (load_ext_gather_offset_restricted)
2173 
2174 /* sv<t0>_t svfoo_[s32]index[_t0](const <t0>_t *, svint32_t)
2175    sv<t0>_t svfoo_[s64]index[_t0](const <t0>_t *, svint64_t)
2176    sv<t0>_t svfoo_[u32]index[_t0](const <t0>_t *, svuint32_t)
2177    sv<t0>_t svfoo_[u64]index[_t0](const <t0>_t *, svuint64_t)
2178 
2179    sv<t0>_t svfoo_[s32]offset[_t0](const <t0>_t *, svint32_t)
2180    sv<t0>_t svfoo_[s64]offset[_t0](const <t0>_t *, svint64_t)
2181    sv<t0>_t svfoo_[u32]offset[_t0](const <t0>_t *, svuint32_t)
2182    sv<t0>_t svfoo_[u64]offset[_t0](const <t0>_t *, svuint64_t).  */
2183 struct load_gather_sv_def : public load_gather_sv_base
2184 {
2185   void
2186   build (function_builder &b, const function_group_info &group) const OVERRIDE
2187   {
2188     b.add_overloaded_functions (group, MODE_index);
2189     b.add_overloaded_functions (group, MODE_offset);
2190     build_sv_index (b, "t0,al,d", group);
2191     build_sv_offset (b, "t0,al,d", group);
2192   }
2193 };
2194 SHAPE (load_gather_sv)
2195 
2196 /* sv<t0>_t svfoo_[u32]index[_t0](const <t0>_t *, svuint32_t)
2197    sv<t0>_t svfoo_[u64]index[_t0](const <t0>_t *, svuint64_t)
2198 
2199    sv<t0>_t svfoo_[s64]offset[_t0](const <t0>_t *, svint64_t)
2200    sv<t0>_t svfoo_[u32]offset[_t0](const <t0>_t *, svuint32_t)
2201    sv<t0>_t svfoo_[u64]offset[_t0](const <t0>_t *, svuint64_t)
2202 
2203    This is load_gather_sv without the 32-bit vector index forms and
2204    without the s32 vector offset form.  */
2205 struct load_gather_sv_restricted_def : public load_gather_sv_base
2206 {
2207   void
2208   build (function_builder &b, const function_group_info &group) const OVERRIDE
2209   {
2210     b.add_overloaded_functions (group, MODE_index);
2211     b.add_overloaded_functions (group, MODE_offset);
2212     build_sv_index64 (b, "t0,al,d", group);
2213     build_sv_uint_offset (b, "t0,al,d", group);
2214   }
2215 };
2216 SHAPE (load_gather_sv_restricted)
2217 
2218 /* sv<t0>_t svfoo[_u32base]_t0(svuint32_t)
2219    sv<t0>_t svfoo[_u64base]_t0(svuint64_t)
2220 
2221    sv<t0>_t svfoo[_u32base]_index_t0(svuint32_t, int64_t)
2222    sv<t0>_t svfoo[_u64base]_index_t0(svuint64_t, int64_t)
2223 
2224    sv<t0>_t svfoo[_u32base]_offset_t0(svuint32_t, int64_t)
2225    sv<t0>_t svfoo[_u64base]_offset_t0(svuint64_t, int64_t).  */
2226 struct load_gather_vs_def : public overloaded_base<1>
2227 {
2228   void
2229   build (function_builder &b, const function_group_info &group) const OVERRIDE
2230   {
2231     /* The base vector mode is optional; the full name has it but the
2232        short name doesn't.  There is no ambiguity with SHAPE_load_gather_sv
2233        because the latter uses an implicit type suffix.  */
2234     build_v_base (b, "t0,b", group, true);
2235     build_vs_index (b, "t0,b,ss64", group, true);
2236     build_vs_offset (b, "t0,b,ss64", group, true);
2237   }
2238 
2239   tree
2240   resolve (function_resolver &) const OVERRIDE
2241   {
2242     /* The short name just makes the base vector mode implicit;
2243        no resolution is needed.  */
2244     gcc_unreachable ();
2245   }
2246 };
2247 SHAPE (load_gather_vs)
2248 
2249 /* sv<t0>_t svfoo[_t0](const <t0>_t *)
2250 
2251    The only difference from "load" is that this shape has no vnum form.  */
2252 struct load_replicate_def : public load_contiguous_base
2253 {
2254   void
2255   build (function_builder &b, const function_group_info &group) const OVERRIDE
2256   {
2257     b.add_overloaded_functions (group, MODE_none);
2258     build_all (b, "t0,al", group, MODE_none);
2259   }
2260 };
2261 SHAPE (load_replicate)
2262 
2263 /* svbool_t svfoo(enum svpattern).  */
2264 struct pattern_pred_def : public nonoverloaded_base
2265 {
2266   void
2267   build (function_builder &b, const function_group_info &group) const OVERRIDE
2268   {
2269     build_all (b, "vp,epattern", group, MODE_none);
2270   }
2271 };
2272 SHAPE (pattern_pred)
2273 
2274 /* void svfoo(const void *, svprfop)
2275    void svfoo_vnum(const void *, int64_t, svprfop).  */
2276 struct prefetch_def : public nonoverloaded_base
2277 {
2278   void
2279   build (function_builder &b, const function_group_info &group) const OVERRIDE
2280   {
2281     build_all (b, "_,ap,eprfop", group, MODE_none);
2282     build_all (b, "_,ap,ss64,eprfop", group, MODE_vnum);
2283   }
2284 };
2285 SHAPE (prefetch)
2286 
2287 /* void svfoo_[s32]index(const void *, svint32_t, svprfop)
2288    void svfoo_[s64]index(const void *, svint64_t, svprfop)
2289    void svfoo_[u32]index(const void *, svuint32_t, svprfop)
2290    void svfoo_[u64]index(const void *, svuint64_t, svprfop)
2291 
2292    void svfoo[_u32base](svuint32_t, svprfop)
2293    void svfoo[_u64base](svuint64_t, svprfop)
2294 
2295    void svfoo[_u32base]_index(svuint32_t, int64_t, svprfop)
2296    void svfoo[_u64base]_index(svuint64_t, int64_t, svprfop).  */
2297 struct prefetch_gather_index_def : public prefetch_gather_base
2298 {
2299   void
2300   build (function_builder &b, const function_group_info &group) const OVERRIDE
2301   {
2302     b.add_overloaded_functions (group, MODE_none);
2303     b.add_overloaded_functions (group, MODE_index);
2304     build_sv_index (b, "_,ap,d,eprfop", group);
2305     build_v_base (b, "_,b,eprfop", group);
2306     build_vs_index (b, "_,b,ss64,eprfop", group);
2307   }
2308 };
2309 SHAPE (prefetch_gather_index)
2310 
2311 /* void svfoo_[s32]offset(const void *, svint32_t, svprfop)
2312    void svfoo_[s64]offset(const void *, svint64_t, svprfop)
2313    void svfoo_[u32]offset(const void *, svuint32_t, svprfop)
2314    void svfoo_[u64]offset(const void *, svuint64_t, svprfop)
2315 
2316    void svfoo[_u32base](svuint32_t, svprfop)
2317    void svfoo[_u64base](svuint64_t, svprfop)
2318 
2319    void svfoo[_u32base]_offset(svuint32_t, int64_t, svprfop)
2320    void svfoo[_u64base]_offset(svuint64_t, int64_t, svprfop).  */
2321 struct prefetch_gather_offset_def : public prefetch_gather_base
2322 {
2323   void
2324   build (function_builder &b, const function_group_info &group) const OVERRIDE
2325   {
2326     b.add_overloaded_functions (group, MODE_none);
2327     b.add_overloaded_functions (group, MODE_offset);
2328     build_sv_offset (b, "_,ap,d,eprfop", group);
2329     build_v_base (b, "_,b,eprfop", group);
2330     build_vs_offset (b, "_,b,ss64,eprfop", group);
2331   }
2332 };
2333 SHAPE (prefetch_gather_offset)
2334 
2335 /* bool svfoo(svbool_t).  */
2336 struct ptest_def : public nonoverloaded_base
2337 {
2338   void
2339   build (function_builder &b, const function_group_info &group) const OVERRIDE
2340   {
2341     build_all (b, "sp,vp", group, MODE_none);
2342   }
2343 };
2344 SHAPE (ptest)
2345 
2346 /* svbool_t svfoo().  */
2347 struct rdffr_def : public nonoverloaded_base
2348 {
2349   void
2350   build (function_builder &b, const function_group_info &group) const OVERRIDE
2351   {
2352     build_all (b, "vp", group, MODE_none);
2353   }
2354 };
2355 SHAPE (rdffr)
2356 
2357 /* <t0>_t svfoo[_t0](sv<t0>_t).  */
2358 struct reduction_def : public overloaded_base<0>
2359 {
2360   void
2361   build (function_builder &b, const function_group_info &group) const OVERRIDE
2362   {
2363     b.add_overloaded_functions (group, MODE_none);
2364     build_all (b, "s0,v0", group, MODE_none);
2365   }
2366 
2367   tree
2368   resolve (function_resolver &r) const OVERRIDE
2369   {
2370     return r.resolve_uniform (1);
2371   }
2372 };
2373 SHAPE (reduction)
2374 
2375 /* int64_t svfoo[_t0](sv<t0>_t)  (for signed t0)
2376    uint64_t svfoo[_t0](sv<t0>_t)  (for unsigned t0)
2377    <t0>_t svfoo[_t0](sv<t0>_t)  (for floating-point t0)
2378 
2379    i.e. a version of "reduction" in which the return type for integers
2380    always has 64 bits.  */
2381 struct reduction_wide_def : public overloaded_base<0>
2382 {
2383   void
2384   build (function_builder &b, const function_group_info &group) const OVERRIDE
2385   {
2386     b.add_overloaded_functions (group, MODE_none);
2387     build_all (b, "sw0,v0", group, MODE_none);
2388   }
2389 
2390   tree
2391   resolve (function_resolver &r) const OVERRIDE
2392   {
2393     return r.resolve_uniform (1);
2394   }
2395 };
2396 SHAPE (reduction_wide)
2397 
2398 /* sv<t0>xN_t svfoo[_t0](sv<t0>xN_t, uint64_t, sv<t0>_t)
2399 
2400    where the second argument is an integer constant expression in the
2401    range [0, N - 1].  */
2402 struct set_def : public overloaded_base<0>
2403 {
2404   void
2405   build (function_builder &b, const function_group_info &group) const OVERRIDE
2406   {
2407     b.add_overloaded_functions (group, MODE_none);
2408     build_all (b, "t0,t0,su64,v0", group, MODE_none);
2409   }
2410 
2411   tree
2412   resolve (function_resolver &r) const OVERRIDE
2413   {
2414     unsigned int i, nargs;
2415     type_suffix_index type;
2416     if (!r.check_gp_argument (3, i, nargs)
2417 	|| (type = r.infer_tuple_type (i)) == NUM_TYPE_SUFFIXES
2418 	|| !r.require_integer_immediate (i + 1)
2419 	|| !r.require_derived_vector_type (i + 2, i, type))
2420       return error_mark_node;
2421 
2422     return r.resolve_to (r.mode_suffix_id, type);
2423   }
2424 
2425   bool
2426   check (function_checker &c) const OVERRIDE
2427   {
2428     unsigned int nvectors = c.vectors_per_tuple ();
2429     return c.require_immediate_range (1, 0, nvectors - 1);
2430   }
2431 };
2432 SHAPE (set)
2433 
2434 /* void svfoo().  */
2435 struct setffr_def : public nonoverloaded_base
2436 {
2437   void
2438   build (function_builder &b, const function_group_info &group) const OVERRIDE
2439   {
2440     build_all (b, "_", group, MODE_none);
2441   }
2442 };
2443 SHAPE (setffr)
2444 
2445 /* sv<t0>_t svfoo[_n_t0])(sv<t0>_t, uint64_t)
2446 
2447    where the final argument must be an integer constant expression in the
2448    range [0, sizeof (<t0>_t) * 8 - 1].  */
2449 struct shift_left_imm_def : public overloaded_base<0>
2450 {
2451   void
2452   build (function_builder &b, const function_group_info &group) const OVERRIDE
2453   {
2454     b.add_overloaded_functions (group, MODE_n);
2455     build_all (b, "v0,v0,su64", group, MODE_n);
2456   }
2457 
2458   tree
2459   resolve (function_resolver &r) const OVERRIDE
2460   {
2461     return r.resolve_uniform (1, 1);
2462   }
2463 
2464   bool
2465   check (function_checker &c) const OVERRIDE
2466   {
2467     unsigned int bits = c.type_suffix (0).element_bits;
2468     return c.require_immediate_range (1, 0, bits - 1);
2469   }
2470 };
2471 SHAPE (shift_left_imm)
2472 
2473 /* sv<t0>_t svfoo[_n_t0])(sv<t0:half>_t, uint64_t)
2474 
2475    where the final argument must be an integer constant expression in the
2476    range [0, sizeof (<t0>_t) * 4 - 1].  */
2477 struct shift_left_imm_long_def : public binary_imm_long_base
2478 {
2479   bool
2480   check (function_checker &c) const OVERRIDE
2481   {
2482     unsigned int bits = c.type_suffix (0).element_bits / 2;
2483     return c.require_immediate_range (1, 0, bits - 1);
2484   }
2485 };
2486 SHAPE (shift_left_imm_long)
2487 
2488 /* sv<t0:uint>_t svfoo[_n_t0])(sv<t0>_t, uint64_t)
2489 
2490    where the final argument must be an integer constant expression in the
2491    range [0, sizeof (<t0>_t) * 8 - 1].  */
2492 struct shift_left_imm_to_uint_def : public shift_left_imm_def
2493 {
2494   void
2495   build (function_builder &b, const function_group_info &group) const OVERRIDE
2496   {
2497     b.add_overloaded_functions (group, MODE_n);
2498     build_all (b, "vu0,v0,su64", group, MODE_n);
2499   }
2500 };
2501 SHAPE (shift_left_imm_to_uint)
2502 
2503 /* sv<t0>_t svfoo[_n_t0])(sv<t0>_t, uint64_t)
2504 
2505    where the final argument must be an integer constant expression in the
2506    range [1, sizeof (<t0>_t) * 8].  */
2507 struct shift_right_imm_def : public overloaded_base<0>
2508 {
2509   void
2510   build (function_builder &b, const function_group_info &group) const OVERRIDE
2511   {
2512     b.add_overloaded_functions (group, MODE_n);
2513     build_all (b, "v0,v0,su64", group, MODE_n);
2514   }
2515 
2516   tree
2517   resolve (function_resolver &r) const OVERRIDE
2518   {
2519     return r.resolve_uniform (1, 1);
2520   }
2521 
2522   bool
2523   check (function_checker &c) const OVERRIDE
2524   {
2525     unsigned int bits = c.type_suffix (0).element_bits;
2526     return c.require_immediate_range (1, 1, bits);
2527   }
2528 };
2529 SHAPE (shift_right_imm)
2530 
2531 /* sv<t0:half>_t svfoo[_n_t0])(sv<t0>_t, uint64_t)
2532 
2533    where the final argument must be an integer constant expression in the
2534    range [1, sizeof (<t0>_t) * 4].  */
2535 typedef shift_right_imm_narrow_wrapper<binary_imm_narrowb_base<>, 1>
2536   shift_right_imm_narrowb_def;
2537 SHAPE (shift_right_imm_narrowb)
2538 
2539 /* sv<t0:half>_t svfoo[_n_t0])(sv<t0:half>_t, sv<t0>_t, uint64_t)
2540 
2541    where the final argument must be an integer constant expression in the
2542    range [1, sizeof (<t0>_t) * 4].  */
2543 typedef shift_right_imm_narrow_wrapper<binary_imm_narrowt_base<>, 2>
2544   shift_right_imm_narrowt_def;
2545 SHAPE (shift_right_imm_narrowt)
2546 
2547 /* sv<t0:uint:half>_t svfoo[_n_t0])(sv<t0>_t, uint64_t)
2548 
2549    where the final argument must be an integer constant expression in the
2550    range [1, sizeof (<t0>_t) * 4].  */
2551 typedef binary_imm_narrowb_base<TYPE_unsigned>
2552   binary_imm_narrowb_base_unsigned;
2553 typedef shift_right_imm_narrow_wrapper<binary_imm_narrowb_base_unsigned, 1>
2554   shift_right_imm_narrowb_to_uint_def;
2555 SHAPE (shift_right_imm_narrowb_to_uint)
2556 
2557 /* sv<t0:uint:half>_t svfoo[_n_t0])(sv<t0:uint:half>_t, sv<t0>_t, uint64_t)
2558 
2559    where the final argument must be an integer constant expression in the
2560    range [1, sizeof (<t0>_t) * 4].  */
2561 typedef binary_imm_narrowt_base<TYPE_unsigned>
2562   binary_imm_narrowt_base_unsigned;
2563 typedef shift_right_imm_narrow_wrapper<binary_imm_narrowt_base_unsigned, 2>
2564   shift_right_imm_narrowt_to_uint_def;
2565 SHAPE (shift_right_imm_narrowt_to_uint)
2566 
2567 /* void svfoo[_t0](<X>_t *, sv<t0>[xN]_t)
2568    void svfoo_vnum[_t0](<X>_t *, int64_t, sv<t0>[xN]_t)
2569 
2570    where <X> might be tied to <t0> (for non-truncating stores) or might
2571    depend on the function base name (for truncating stores).  */
2572 struct store_def : public overloaded_base<0>
2573 {
2574   void
2575   build (function_builder &b, const function_group_info &group) const OVERRIDE
2576   {
2577     b.add_overloaded_functions (group, MODE_none);
2578     b.add_overloaded_functions (group, MODE_vnum);
2579     build_all (b, "_,as,t0", group, MODE_none);
2580     build_all (b, "_,as,ss64,t0", group, MODE_vnum);
2581   }
2582 
2583   tree
2584   resolve (function_resolver &r) const OVERRIDE
2585   {
2586     bool vnum_p = r.mode_suffix_id == MODE_vnum;
2587     gcc_assert (r.mode_suffix_id == MODE_none || vnum_p);
2588 
2589     unsigned int i, nargs;
2590     type_suffix_index type;
2591     if (!r.check_gp_argument (vnum_p ? 3 : 2, i, nargs)
2592 	|| !r.require_pointer_type (i)
2593 	|| (vnum_p && !r.require_scalar_type (i + 1, "int64_t"))
2594 	|| ((type = r.infer_tuple_type (nargs - 1)) == NUM_TYPE_SUFFIXES))
2595       return error_mark_node;
2596 
2597     return r.resolve_to (r.mode_suffix_id, type);
2598   }
2599 };
2600 SHAPE (store)
2601 
2602 /* void svfoo_[s32]index[_t0](<X>_t *, svint32_t, sv<t0>_t)
2603    void svfoo_[s64]index[_t0](<X>_t *, svint64_t, sv<t0>_t)
2604    void svfoo_[u32]index[_t0](<X>_t *, svuint32_t, sv<t0>_t)
2605    void svfoo_[u64]index[_t0](<X>_t *, svuint64_t, sv<t0>_t)
2606 
2607    void svfoo[_u32base]_index[_t0](svuint32_t, int64_t, sv<t0>_t)
2608    void svfoo[_u64base]_index[_t0](svuint64_t, int64_t, sv<t0>_t)
2609 
2610    where <X> might be tied to <t0> (for non-truncating stores) or might
2611    depend on the function base name (for truncating stores).  */
2612 struct store_scatter_index_def : public store_scatter_base
2613 {
2614   void
2615   build (function_builder &b, const function_group_info &group) const OVERRIDE
2616   {
2617     b.add_overloaded_functions (group, MODE_index);
2618     build_sv_index (b, "_,as,d,t0", group);
2619     build_vs_index (b, "_,b,ss64,t0", group);
2620   }
2621 };
2622 SHAPE (store_scatter_index)
2623 
2624 /* void svfoo_[s64]index[_t0](<X>_t *, svint64_t, sv<t0>_t)
2625    void svfoo_[u64]index[_t0](<X>_t *, svuint64_t, sv<t0>_t)
2626 
2627    void svfoo[_u32base]_index[_t0](svuint32_t, int64_t, sv<t0>_t)
2628    void svfoo[_u64base]_index[_t0](svuint64_t, int64_t, sv<t0>_t)
2629 
2630    i.e. a version of store_scatter_index that doesn't support 32-bit
2631    vector indices.  */
2632 struct store_scatter_index_restricted_def : public store_scatter_base
2633 {
2634   void
2635   build (function_builder &b, const function_group_info &group) const OVERRIDE
2636   {
2637     b.add_overloaded_functions (group, MODE_index);
2638     build_sv_index64 (b, "_,as,d,t0", group);
2639     build_vs_index (b, "_,b,ss64,t0", group);
2640   }
2641 };
2642 SHAPE (store_scatter_index_restricted)
2643 
2644 /* void svfoo_[s32]offset[_t0](<X>_t *, svint32_t, sv<t0>_t)
2645    void svfoo_[s64]offset[_t0](<X>_t *, svint64_t, sv<t0>_t)
2646    void svfoo_[u32]offset[_t0](<X>_t *, svuint32_t, sv<t0>_t)
2647    void svfoo_[u64]offset[_t0](<X>_t *, svuint64_t, sv<t0>_t)
2648 
2649    void svfoo[_u32base_t0](svuint32_t, sv<t0>_t)
2650    void svfoo[_u64base_t0](svuint64_t, sv<t0>_t)
2651 
2652    void svfoo[_u32base]_offset[_t0](svuint32_t, int64_t, sv<t0>_t)
2653    void svfoo[_u64base]_offset[_t0](svuint64_t, int64_t, sv<t0>_t)
2654 
2655    where <X> might be tied to <t0> (for non-truncating stores) or might
2656    depend on the function base name (for truncating stores).  */
2657 struct store_scatter_offset_def : public store_scatter_base
2658 {
2659   void
2660   build (function_builder &b, const function_group_info &group) const OVERRIDE
2661   {
2662     b.add_overloaded_functions (group, MODE_none);
2663     b.add_overloaded_functions (group, MODE_offset);
2664     build_sv_offset (b, "_,as,d,t0", group);
2665     build_v_base (b, "_,b,t0", group);
2666     build_vs_offset (b, "_,b,ss64,t0", group);
2667   }
2668 };
2669 SHAPE (store_scatter_offset)
2670 
2671 /* void svfoo_[s64]offset[_t0](<X>_t *, svint64_t, sv<t0>_t)
2672    void svfoo_[u32]offset[_t0](<X>_t *, svuint32_t, sv<t0>_t)
2673    void svfoo_[u64]offset[_t0](<X>_t *, svuint64_t, sv<t0>_t)
2674 
2675    void svfoo[_u32base_t0](svuint32_t, sv<t0>_t)
2676    void svfoo[_u64base_t0](svuint64_t, sv<t0>_t)
2677 
2678    void svfoo[_u32base]_offset[_t0](svuint32_t, int64_t, sv<t0>_t)
2679    void svfoo[_u64base]_offset[_t0](svuint64_t, int64_t, sv<t0>_t)
2680 
2681    i.e. a version of store_scatter_offset that doesn't support svint32_t
2682    offsets.  */
2683 struct store_scatter_offset_restricted_def : public store_scatter_base
2684 {
2685   void
2686   build (function_builder &b, const function_group_info &group) const OVERRIDE
2687   {
2688     b.add_overloaded_functions (group, MODE_none);
2689     b.add_overloaded_functions (group, MODE_offset);
2690     build_sv_uint_offset (b, "_,as,d,t0", group);
2691     build_v_base (b, "_,b,t0", group);
2692     build_vs_offset (b, "_,b,ss64,t0", group);
2693   }
2694 };
2695 SHAPE (store_scatter_offset_restricted)
2696 
2697 /* sv<t0>_t svfoo[_t0](sv<t0>xN_t, sv<t0:uint>_t).  */
2698 struct tbl_tuple_def : public overloaded_base<0>
2699 {
2700   void
2701   build (function_builder &b, const function_group_info &group) const OVERRIDE
2702   {
2703     b.add_overloaded_functions (group, MODE_none);
2704     build_all (b, "v0,t0,vu0", group, MODE_none);
2705   }
2706 
2707   tree
2708   resolve (function_resolver &r) const OVERRIDE
2709   {
2710     unsigned int i, nargs;
2711     type_suffix_index type;
2712     if (!r.check_gp_argument (2, i, nargs)
2713 	|| (type = r.infer_tuple_type (i)) == NUM_TYPE_SUFFIXES
2714 	|| !r.require_derived_vector_type (i + 1, i, type, TYPE_unsigned))
2715       return error_mark_node;
2716 
2717     return r.resolve_to (r.mode_suffix_id, type);
2718   }
2719 };
2720 SHAPE (tbl_tuple)
2721 
2722 /* sv<t0>_t svfoo[_t0](sv<t0>_t, svbfloatt16_t, svbfloat16_t).  */
2723 struct ternary_bfloat_def
2724   : public ternary_resize2_base<16, TYPE_bfloat, TYPE_bfloat>
2725 {
2726   void
2727   build (function_builder &b, const function_group_info &group) const OVERRIDE
2728   {
2729     b.add_overloaded_functions (group, MODE_none);
2730     build_all (b, "v0,v0,vB,vB", group, MODE_none);
2731   }
2732 };
2733 SHAPE (ternary_bfloat)
2734 
2735 /* sv<t0>_t svfoo[_t0](sv<t0>_t, svbfloat16_t, svbfloat16_t, uint64_t)
2736 
2737    where the final argument is an integer constant expression in the range
2738    [0, 7].  */
2739 typedef ternary_bfloat_lane_base<1> ternary_bfloat_lane_def;
2740 SHAPE (ternary_bfloat_lane)
2741 
2742 /* sv<t0>_t svfoo[_t0](sv<t0>_t, svbfloat16_t, svbfloat16_t, uint64_t)
2743 
2744    where the final argument is an integer constant expression in the range
2745    [0, 3].  */
2746 typedef ternary_bfloat_lane_base<2> ternary_bfloat_lanex2_def;
2747 SHAPE (ternary_bfloat_lanex2)
2748 
2749 /* sv<t0>_t svfoo[_t0](sv<t0>_t, svbfloatt16_t, svbfloat16_t)
2750    sv<t0>_t svfoo[_n_t0](sv<t0>_t, svbfloat16_t, bfloat16_t).  */
2751 struct ternary_bfloat_opt_n_def
2752   : public ternary_resize2_opt_n_base<16, TYPE_bfloat, TYPE_bfloat>
2753 {
2754   void
2755   build (function_builder &b, const function_group_info &group) const OVERRIDE
2756   {
2757     b.add_overloaded_functions (group, MODE_none);
2758     build_all (b, "v0,v0,vB,vB", group, MODE_none);
2759     build_all (b, "v0,v0,vB,sB", group, MODE_n);
2760   }
2761 };
2762 SHAPE (ternary_bfloat_opt_n)
2763 
2764 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:int:quarter>_t, sv<t0:uint:quarter>_t,
2765 		       uint64_t)
2766 
2767    where the final argument is an integer constant expression in the range
2768    [0, 16 / sizeof (<t0>_t) - 1].  */
2769 struct ternary_intq_uintq_lane_def
2770   : public ternary_qq_lane_base<TYPE_signed, TYPE_unsigned>
2771 {
2772   void
2773   build (function_builder &b, const function_group_info &group) const OVERRIDE
2774   {
2775     b.add_overloaded_functions (group, MODE_none);
2776     build_all (b, "v0,v0,vqs0,vqu0,su64", group, MODE_none);
2777   }
2778 };
2779 SHAPE (ternary_intq_uintq_lane)
2780 
2781 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:int:quarter>_t, sv<t0:uint:quarter>_t)
2782    sv<t0>_t svfoo[_n_t0](sv<t0>_t, sv<t0:int:quarter>_t,
2783 			 <t0:uint:quarter>_t).  */
2784 struct ternary_intq_uintq_opt_n_def
2785   : public ternary_resize2_opt_n_base<function_resolver::QUARTER_SIZE,
2786 				      TYPE_signed, TYPE_unsigned>
2787 {
2788   void
2789   build (function_builder &b, const function_group_info &group) const OVERRIDE
2790   {
2791     b.add_overloaded_functions (group, MODE_none);
2792     build_all (b, "v0,v0,vqs0,vqu0", group, MODE_none);
2793     build_all (b, "v0,v0,vqs0,squ0", group, MODE_n);
2794   }
2795 };
2796 SHAPE (ternary_intq_uintq_opt_n)
2797 
2798 /* svbool_t svfoo[_<t0>](sv<t0>_t, sv<t0>_t, sv<t0>_t, uint64_t)
2799 
2800    where the final argument is an integer constant expression in the
2801    range [0, 16 / sizeof (<t0>_t) - 1].  */
2802 struct ternary_lane_def : public overloaded_base<0>
2803 {
2804   void
2805   build (function_builder &b, const function_group_info &group) const OVERRIDE
2806   {
2807     b.add_overloaded_functions (group, MODE_none);
2808     build_all (b, "v0,v0,v0,v0,su64", group, MODE_none);
2809   }
2810 
2811   tree
2812   resolve (function_resolver &r) const OVERRIDE
2813   {
2814     return r.resolve_uniform (3, 1);
2815   }
2816 
2817   bool
2818   check (function_checker &c) const OVERRIDE
2819   {
2820     return c.require_immediate_lane_index (3);
2821   }
2822 };
2823 SHAPE (ternary_lane)
2824 
2825 /* svbool_t svfoo[_<t0>](sv<t0>_t, sv<t0>_t, sv<t0>_t, uint64_t, uint64_t)
2826 
2827    where the penultimate argument is an integer constant expression in
2828    the range [0, 8 / sizeof (<t0>_t) - 1] and where the final argument
2829    is an integer constant expression in {0, 90, 180, 270}.  */
2830 struct ternary_lane_rotate_def : public overloaded_base<0>
2831 {
2832   void
2833   build (function_builder &b, const function_group_info &group) const OVERRIDE
2834   {
2835     b.add_overloaded_functions (group, MODE_none);
2836     build_all (b, "v0,v0,v0,v0,su64,su64", group, MODE_none);
2837   }
2838 
2839   tree
2840   resolve (function_resolver &r) const OVERRIDE
2841   {
2842     return r.resolve_uniform (3, 2);
2843   }
2844 
2845   bool
2846   check (function_checker &c) const OVERRIDE
2847   {
2848     return (c.require_immediate_lane_index (3, 2)
2849 	    && c.require_immediate_one_of (4, 0, 90, 180, 270));
2850   }
2851 };
2852 SHAPE (ternary_lane_rotate)
2853 
2854 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:half>_t, sv<t0:half>_t, uint64_t)
2855 
2856    where the final argument is an integer constant expression in the range
2857    [0, 32 / sizeof (<t0>_t) - 1].  */
2858 struct ternary_long_lane_def
2859   : public ternary_resize2_lane_base<function_resolver::HALF_SIZE>
2860 {
2861   void
2862   build (function_builder &b, const function_group_info &group) const OVERRIDE
2863   {
2864     b.add_overloaded_functions (group, MODE_none);
2865     build_all (b, "v0,v0,vh0,vh0,su64", group, MODE_none);
2866   }
2867 
2868   bool
2869   check (function_checker &c) const OVERRIDE
2870   {
2871     return c.require_immediate_lane_index (3);
2872   }
2873 };
2874 SHAPE (ternary_long_lane)
2875 
2876 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:half>_t, sv<t0:half>_t)
2877    sv<t0>_t svfoo[_n_t0](sv<t0>_t, sv<t0:half>_t, <t0:half>_t)
2878 
2879    i.e. a version of the standard ternary shape ternary_opt_n in which
2880    the element type of the last two arguments is the half-sized
2881    equivalent of <t0>.  */
2882 struct ternary_long_opt_n_def
2883   : public ternary_resize2_opt_n_base<function_resolver::HALF_SIZE>
2884 {
2885   void
2886   build (function_builder &b, const function_group_info &group) const OVERRIDE
2887   {
2888     b.add_overloaded_functions (group, MODE_none);
2889     build_all (b, "v0,v0,vh0,vh0", group, MODE_none);
2890     build_all (b, "v0,v0,vh0,sh0", group, MODE_n);
2891   }
2892 };
2893 SHAPE (ternary_long_opt_n)
2894 
2895 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0>_t, sv<t0>_t)
2896    sv<t0>_t svfoo[_n_t0](sv<t0>_t, sv<t0>_t, <t0>_t)
2897 
2898    i.e. the standard shape for ternary operations that operate on
2899    uniform types.  */
2900 struct ternary_opt_n_def : public overloaded_base<0>
2901 {
2902   void
2903   build (function_builder &b, const function_group_info &group) const OVERRIDE
2904   {
2905     b.add_overloaded_functions (group, MODE_none);
2906     build_all (b, "v0,v0,v0,v0", group, MODE_none);
2907     build_all (b, "v0,v0,v0,s0", group, MODE_n);
2908   }
2909 
2910   tree
2911   resolve (function_resolver &r) const OVERRIDE
2912   {
2913     return r.resolve_uniform_opt_n (3);
2914   }
2915 };
2916 SHAPE (ternary_opt_n)
2917 
2918 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:quarter>_t, sv<t0:quarter>_t, uint64_t)
2919 
2920    where the final argument is an integer constant expression in the range
2921    [0, 16 / sizeof (<t0>_t) - 1].  */
2922 struct ternary_qq_lane_def : public ternary_qq_lane_base<>
2923 {
2924   void
2925   build (function_builder &b, const function_group_info &group) const OVERRIDE
2926   {
2927     b.add_overloaded_functions (group, MODE_none);
2928     build_all (b, "v0,v0,vq0,vq0,su64", group, MODE_none);
2929   }
2930 };
2931 SHAPE (ternary_qq_lane)
2932 
2933 /* svbool_t svfoo[_<t0>](sv<t0>_t, sv<t0:quarter>_t, sv<t0:quarter>_t,
2934 			 uint64_t)
2935 
2936    where the final argument is an integer constant expression in
2937    {0, 90, 180, 270}.  */
2938 struct ternary_qq_lane_rotate_def : public overloaded_base<0>
2939 {
2940   void
2941   build (function_builder &b, const function_group_info &group) const OVERRIDE
2942   {
2943     b.add_overloaded_functions (group, MODE_none);
2944     build_all (b, "v0,v0,vq0,vq0,su64,su64", group, MODE_none);
2945   }
2946 
2947   tree
2948   resolve (function_resolver &r) const OVERRIDE
2949   {
2950     unsigned int i, nargs;
2951     type_suffix_index type;
2952     if (!r.check_gp_argument (5, i, nargs)
2953 	|| (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
2954 	|| !r.require_derived_vector_type (i + 1, i, type, r.SAME_TYPE_CLASS,
2955 					   r.QUARTER_SIZE)
2956 	|| !r.require_derived_vector_type (i + 2, i, type, r.SAME_TYPE_CLASS,
2957 					   r.QUARTER_SIZE)
2958 	|| !r.require_integer_immediate (i + 3)
2959 	|| !r.require_integer_immediate (i + 4))
2960       return error_mark_node;
2961 
2962     return r.resolve_to (r.mode_suffix_id, type);
2963   }
2964 
2965   bool
2966   check (function_checker &c) const OVERRIDE
2967   {
2968     return (c.require_immediate_lane_index (3, 4)
2969 	    && c.require_immediate_one_of (4, 0, 90, 180, 270));
2970   }
2971 };
2972 SHAPE (ternary_qq_lane_rotate)
2973 
2974 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:quarter>_t, sv<t0:quarter>_t)
2975    sv<t0>_t svfoo[_n_t0](sv<t0>_t, sv<t0:quarter>_t, <t0:quarter>_t)
2976 
2977    i.e. a version of the standard ternary shape ternary_opt_n in which
2978    the element type of the last two arguments is the quarter-sized
2979    equivalent of <t0>.  */
2980 struct ternary_qq_opt_n_def
2981   : public ternary_resize2_opt_n_base<function_resolver::QUARTER_SIZE>
2982 {
2983   void
2984   build (function_builder &b, const function_group_info &group) const OVERRIDE
2985   {
2986     b.add_overloaded_functions (group, MODE_none);
2987     build_all (b, "v0,v0,vq0,vq0", group, MODE_none);
2988     build_all (b, "v0,v0,vq0,sq0", group, MODE_n);
2989   }
2990 };
2991 SHAPE (ternary_qq_opt_n)
2992 
2993 /* svbool_t svfoo[_<t0>](sv<t0>_t, sv<t0:quarter>_t, sv<t0:quarter>_t,
2994 			 uint64_t)
2995 
2996    where the final argument is an integer constant expression in
2997    {0, 90, 180, 270}.  */
2998 struct ternary_qq_rotate_def : public overloaded_base<0>
2999 {
3000   void
3001   build (function_builder &b, const function_group_info &group) const OVERRIDE
3002   {
3003     b.add_overloaded_functions (group, MODE_none);
3004     build_all (b, "v0,v0,vq0,vq0,su64", group, MODE_none);
3005   }
3006 
3007   tree
3008   resolve (function_resolver &r) const OVERRIDE
3009   {
3010     unsigned int i, nargs;
3011     type_suffix_index type;
3012     if (!r.check_gp_argument (4, i, nargs)
3013 	|| (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
3014 	|| !r.require_derived_vector_type (i + 1, i, type, r.SAME_TYPE_CLASS,
3015 					   r.QUARTER_SIZE)
3016 	|| !r.require_derived_vector_type (i + 2, i, type, r.SAME_TYPE_CLASS,
3017 					   r.QUARTER_SIZE)
3018 	|| !r.require_integer_immediate (i + 3))
3019       return error_mark_node;
3020 
3021     return r.resolve_to (r.mode_suffix_id, type);
3022   }
3023 
3024   bool
3025   check (function_checker &c) const OVERRIDE
3026   {
3027     return c.require_immediate_one_of (3, 0, 90, 180, 270);
3028   }
3029 };
3030 SHAPE (ternary_qq_rotate)
3031 
3032 /* svbool_t svfoo[_<t0>](sv<t0>_t, sv<t0>_t, sv<t0>_t, uint64_t)
3033 
3034    where the final argument is an integer constant expression in
3035    {0, 90, 180, 270}.  */
3036 struct ternary_rotate_def : public overloaded_base<0>
3037 {
3038   void
3039   build (function_builder &b, const function_group_info &group) const OVERRIDE
3040   {
3041     b.add_overloaded_functions (group, MODE_none);
3042     build_all (b, "v0,v0,v0,v0,su64", group, MODE_none);
3043   }
3044 
3045   tree
3046   resolve (function_resolver &r) const OVERRIDE
3047   {
3048     return r.resolve_uniform (3, 1);
3049   }
3050 
3051   bool
3052   check (function_checker &c) const OVERRIDE
3053   {
3054     return c.require_immediate_one_of (3, 0, 90, 180, 270);
3055   }
3056 };
3057 SHAPE (ternary_rotate)
3058 
3059 /* sv<t0>_t svfoo[_n_t0])(sv<t0>_t, sv<t0>_t, uint64_t)
3060 
3061    where the final argument must be an integer constant expression in the
3062    range [0, sizeof (<t0>_t) * 8 - 1].  */
3063 struct ternary_shift_left_imm_def : public ternary_shift_imm_base
3064 {
3065   bool
3066   check (function_checker &c) const OVERRIDE
3067   {
3068     unsigned int bits = c.type_suffix (0).element_bits;
3069     return c.require_immediate_range (2, 0, bits - 1);
3070   }
3071 };
3072 SHAPE (ternary_shift_left_imm)
3073 
3074 /* sv<t0>_t svfoo[_n_t0])(sv<t0>_t, sv<t0>_t, uint64_t)
3075 
3076    where the final argument must be an integer constant expression in the
3077    range [1, sizeof (<t0>_t) * 8].  */
3078 struct ternary_shift_right_imm_def : public ternary_shift_imm_base
3079 {
3080   bool
3081   check (function_checker &c) const OVERRIDE
3082   {
3083     unsigned int bits = c.type_suffix (0).element_bits;
3084     return c.require_immediate_range (2, 1, bits);
3085   }
3086 };
3087 SHAPE (ternary_shift_right_imm)
3088 
3089 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0>_t, sv<t0:uint>_t).  */
3090 struct ternary_uint_def : public overloaded_base<0>
3091 {
3092   void
3093   build (function_builder &b, const function_group_info &group) const OVERRIDE
3094   {
3095     b.add_overloaded_functions (group, MODE_none);
3096     build_all (b, "v0,v0,v0,vu0", group, MODE_none);
3097   }
3098 
3099   tree
3100   resolve (function_resolver &r) const OVERRIDE
3101   {
3102     unsigned int i, nargs;
3103     type_suffix_index type;
3104     if (!r.check_gp_argument (3, i, nargs)
3105 	|| (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
3106 	|| !r.require_matching_vector_type (i + 1, type)
3107 	|| !r.require_derived_vector_type (i + 2, i, type, TYPE_unsigned))
3108       return error_mark_node;
3109 
3110     return r.resolve_to (r.mode_suffix_id, type);
3111   }
3112 };
3113 SHAPE (ternary_uint)
3114 
3115 /* sv<t0>_t svfoo[_t0](sv<t0>_t, svu<t0:uint:quarter>_t,
3116 		       sv<t0:int:quarter>_t).  */
3117 struct ternary_uintq_intq_def
3118   : public ternary_resize2_base<function_resolver::QUARTER_SIZE,
3119 				TYPE_unsigned, TYPE_signed>
3120 {
3121   void
3122   build (function_builder &b, const function_group_info &group) const OVERRIDE
3123   {
3124     b.add_overloaded_functions (group, MODE_none);
3125     build_all (b, "v0,v0,vqu0,vqs0", group, MODE_none);
3126   }
3127 };
3128 SHAPE (ternary_uintq_intq)
3129 
3130 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:uint:quarter>_t, sv<t0:int:quarter>_t,
3131 		       uint64_t)
3132 
3133    where the final argument is an integer constant expression in the range
3134    [0, 16 / sizeof (<t0>_t) - 1].  */
3135 struct ternary_uintq_intq_lane_def
3136   : public ternary_qq_lane_base<TYPE_unsigned, TYPE_signed>
3137 {
3138   void
3139   build (function_builder &b, const function_group_info &group) const OVERRIDE
3140   {
3141     b.add_overloaded_functions (group, MODE_none);
3142     build_all (b, "v0,v0,vqu0,vqs0,su64", group, MODE_none);
3143   }
3144 };
3145 SHAPE (ternary_uintq_intq_lane)
3146 
3147 /* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:uint:quarter>_t, sv<t0:int:quarter>_t)
3148    sv<t0>_t svfoo[_n_t0](sv<t0>_t, sv<t0:uint:quarter>_t,
3149 			 <t0:int:quarter>_t).  */
3150 struct ternary_uintq_intq_opt_n_def
3151   : public ternary_resize2_opt_n_base<function_resolver::QUARTER_SIZE,
3152 				      TYPE_unsigned, TYPE_signed>
3153 {
3154   void
3155   build (function_builder &b, const function_group_info &group) const OVERRIDE
3156   {
3157     b.add_overloaded_functions (group, MODE_none);
3158     build_all (b, "v0,v0,vqu0,vqs0", group, MODE_none);
3159     build_all (b, "v0,v0,vqu0,sqs0", group, MODE_n);
3160   }
3161 };
3162 SHAPE (ternary_uintq_intq_opt_n)
3163 
3164 /* svbool_t svfoo[_<t0>](sv<t0>_t, sv<t0>_t, uint64_t)
3165 
3166    where the final argument is an integer constant expression in the
3167    range [0, 7].  */
3168 struct tmad_def : public overloaded_base<0>
3169 {
3170   void
3171   build (function_builder &b, const function_group_info &group) const OVERRIDE
3172   {
3173     b.add_overloaded_functions (group, MODE_none);
3174     build_all (b, "v0,v0,v0,su64", group, MODE_none);
3175   }
3176 
3177   tree
3178   resolve (function_resolver &r) const OVERRIDE
3179   {
3180     return r.resolve_uniform (2, 1);
3181   }
3182 
3183   bool
3184   check (function_checker &c) const OVERRIDE
3185   {
3186     return c.require_immediate_range (2, 0, 7);
3187   }
3188 };
3189 SHAPE (tmad)
3190 
3191 /* sv<t0>_t svfoo[_t0](sv<t0>_t)
3192 
3193    i.e. the standard shape for unary operations that operate on
3194    uniform types.  */
3195 struct unary_def : public overloaded_base<0>
3196 {
3197   void
3198   build (function_builder &b, const function_group_info &group) const OVERRIDE
3199   {
3200     b.add_overloaded_functions (group, MODE_none);
3201     build_all (b, "v0,v0", group, MODE_none);
3202   }
3203 
3204   tree
3205   resolve (function_resolver &r) const OVERRIDE
3206   {
3207     return r.resolve_unary ();
3208   }
3209 };
3210 SHAPE (unary)
3211 
3212 /* sv<t0>_t svfoo_t0[_t1](sv<t1>_t)
3213 
3214    where the target type <t0> must be specified explicitly but the source
3215    type <t1> can be inferred.  */
3216 struct unary_convert_def : public overloaded_base<1>
3217 {
3218   void
3219   build (function_builder &b, const function_group_info &group) const OVERRIDE
3220   {
3221     b.add_overloaded_functions (group, MODE_none);
3222     build_all (b, "v0,v1", group, MODE_none);
3223   }
3224 
3225   tree
3226   resolve (function_resolver &r) const OVERRIDE
3227   {
3228     return r.resolve_unary (r.type_suffix (0).tclass,
3229 			    r.type_suffix (0).element_bits);
3230   }
3231 };
3232 SHAPE (unary_convert)
3233 
3234 /* sv<t0>_t svfoo_t0[_t1](sv<t0>_t, sv<t1>_t)
3235 
3236    This is a version of unary_convert in which the even-indexed
3237    elements are passed in as a first parameter, before any governing
3238    predicate.  */
3239 struct unary_convert_narrowt_def : public overloaded_base<1>
3240 {
3241   void
3242   build (function_builder &b, const function_group_info &group) const OVERRIDE
3243   {
3244     b.add_overloaded_functions (group, MODE_none);
3245     build_all (b, "v0,v1", group, MODE_none);
3246   }
3247 
3248   tree
3249   resolve (function_resolver &r) const OVERRIDE
3250   {
3251     return r.resolve_unary (r.type_suffix (0).tclass,
3252 			    r.type_suffix (0).element_bits, true);
3253   }
3254 };
3255 SHAPE (unary_convert_narrowt)
3256 
3257 /* sv<t0>_t svfoo[_t0](sv<t0:half>_t).  */
3258 struct unary_long_def : public overloaded_base<0>
3259 {
3260   void
3261   build (function_builder &b, const function_group_info &group) const OVERRIDE
3262   {
3263     b.add_overloaded_functions (group, MODE_none);
3264     build_all (b, "v0,vh0", group, MODE_none);
3265   }
3266 
3267   tree
3268   resolve (function_resolver &r) const OVERRIDE
3269   {
3270     unsigned int i, nargs;
3271     type_suffix_index type, result_type;
3272     if (!r.check_gp_argument (1, i, nargs)
3273 	|| (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
3274 	|| (result_type = long_type_suffix (r, type)) == NUM_TYPE_SUFFIXES)
3275       return error_mark_node;
3276 
3277     if (tree res = r.lookup_form (r.mode_suffix_id, result_type))
3278       return res;
3279 
3280     return r.report_no_such_form (type);
3281   }
3282 };
3283 SHAPE (unary_long)
3284 
3285 /* sv<t0>_t svfoo[_n]_t0(<t0>_t).  */
3286 struct unary_n_def : public overloaded_base<1>
3287 {
3288   void
3289   build (function_builder &b, const function_group_info &group) const OVERRIDE
3290   {
3291     /* The "_n" suffix is optional; the full name has it, but the short
3292        name doesn't.  */
3293     build_all (b, "v0,s0", group, MODE_n, true);
3294   }
3295 
3296   tree
3297   resolve (function_resolver &) const OVERRIDE
3298   {
3299     /* The short forms just make "_n" implicit, so no resolution is needed.  */
3300     gcc_unreachable ();
3301   }
3302 };
3303 SHAPE (unary_n)
3304 
3305 /* sv<t0:half>_t svfoo[_t0](sv<t0>_t).  */
3306 typedef unary_narrowb_base<> unary_narrowb_def;
3307 SHAPE (unary_narrowb)
3308 
3309 /* sv<t0:half>_t svfoo[_t0](sv<t0:half>_t, sv<t0>_t).  */
3310 typedef unary_narrowt_base<> unary_narrowt_def;
3311 SHAPE (unary_narrowt)
3312 
3313 /* sv<t0:uint:half>_t svfoo[_t0](sv<t0>_t).  */
3314 typedef unary_narrowb_base<TYPE_unsigned> unary_narrowb_to_uint_def;
3315 SHAPE (unary_narrowb_to_uint)
3316 
3317 /* sv<t0:uint:half>_t svfoo[_t0](sv<t0:uint:half>_t, sv<t0>_t).  */
3318 typedef unary_narrowt_base<TYPE_unsigned> unary_narrowt_to_uint_def;
3319 SHAPE (unary_narrowt_to_uint)
3320 
3321 /* svbool_t svfoo(svbool_t).  */
3322 struct unary_pred_def : public nonoverloaded_base
3323 {
3324   void
3325   build (function_builder &b, const function_group_info &group) const OVERRIDE
3326   {
3327     build_all (b, "v0,v0", group, MODE_none);
3328   }
3329 };
3330 SHAPE (unary_pred)
3331 
3332 /* sv<t0:int>_t svfoo[_t0](sv<t0>_t)
3333 
3334    i.e. a version of "unary" in which the returned vector contains
3335    signed integers.  */
3336 struct unary_to_int_def : public overloaded_base<0>
3337 {
3338   void
3339   build (function_builder &b, const function_group_info &group) const OVERRIDE
3340   {
3341     b.add_overloaded_functions (group, MODE_none);
3342     build_all (b, "vs0,v0", group, MODE_none);
3343   }
3344 
3345   tree
3346   resolve (function_resolver &r) const OVERRIDE
3347   {
3348     return r.resolve_unary (TYPE_signed);
3349   }
3350 };
3351 SHAPE (unary_to_int)
3352 
3353 /* sv<t0:uint>_t svfoo[_t0](sv<t0>_t)
3354 
3355    i.e. a version of "unary" in which the returned vector contains
3356    unsigned integers.  */
3357 struct unary_to_uint_def : public overloaded_base<0>
3358 {
3359   void
3360   build (function_builder &b, const function_group_info &group) const OVERRIDE
3361   {
3362     b.add_overloaded_functions (group, MODE_none);
3363     build_all (b, "vu0,v0", group, MODE_none);
3364   }
3365 
3366   tree
3367   resolve (function_resolver &r) const OVERRIDE
3368   {
3369     return r.resolve_unary (TYPE_unsigned);
3370   }
3371 };
3372 SHAPE (unary_to_uint)
3373 
3374 /* sv<t0>_t svfoo[_t0](sv<t0:uint>_t)
3375 
3376    where <t0> always belongs a certain type class, and where <t0:uint>
3377    therefore uniquely determines <t0>.  */
3378 struct unary_uint_def : public overloaded_base<0>
3379 {
3380   void
3381   build (function_builder &b, const function_group_info &group) const OVERRIDE
3382   {
3383     b.add_overloaded_functions (group, MODE_none);
3384     build_all (b, "v0,vu0", group, MODE_none);
3385   }
3386 
3387   tree
3388   resolve (function_resolver &r) const OVERRIDE
3389   {
3390     unsigned int i, nargs;
3391     type_suffix_index type;
3392     if (!r.check_gp_argument (1, i, nargs)
3393 	|| (type = r.infer_unsigned_vector_type (i)) == NUM_TYPE_SUFFIXES)
3394       return error_mark_node;
3395 
3396     /* Search for a valid suffix with the same number of bits as TYPE.  */
3397     unsigned int element_bits = type_suffixes[type].element_bits;
3398     if (type_suffixes[type].unsigned_p)
3399       for (unsigned int j = 0; j < NUM_TYPE_SUFFIXES; ++j)
3400 	if (type_suffixes[j].element_bits == element_bits)
3401 	  if (tree res = r.lookup_form (r.mode_suffix_id,
3402 					type_suffix_index (j)))
3403 	    return res;
3404 
3405     return r.report_no_such_form (type);
3406   }
3407 };
3408 SHAPE (unary_uint)
3409 
3410 /* sv<t0>_t svfoo[_<t0>](sv<t0:half>_t)
3411 
3412    i.e. a version of "unary" in which the source elements are half the
3413    size of the destination elements, but have the same type class.  */
3414 struct unary_widen_def : public overloaded_base<0>
3415 {
3416   void
3417   build (function_builder &b, const function_group_info &group) const OVERRIDE
3418   {
3419     b.add_overloaded_functions (group, MODE_none);
3420     build_all (b, "v0,vh0", group, MODE_none);
3421   }
3422 
3423   tree
3424   resolve (function_resolver &r) const OVERRIDE
3425   {
3426     unsigned int i, nargs;
3427     type_suffix_index type;
3428     if (!r.check_gp_argument (1, i, nargs)
3429 	|| (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES)
3430       return error_mark_node;
3431 
3432     /* There is only a single form for predicates.  */
3433     if (type == TYPE_SUFFIX_b)
3434       return r.resolve_to (r.mode_suffix_id, type);
3435 
3436     if (type_suffixes[type].integer_p
3437 	&& type_suffixes[type].element_bits < 64)
3438       {
3439 	type_suffix_index wide_suffix
3440 	  = find_type_suffix (type_suffixes[type].tclass,
3441 			      type_suffixes[type].element_bits * 2);
3442 	if (tree res = r.lookup_form (r.mode_suffix_id, wide_suffix))
3443 	  return res;
3444       }
3445 
3446     return r.report_no_such_form (type);
3447   }
3448 };
3449 SHAPE (unary_widen)
3450 
3451 }
3452