]> gcc.gnu.org Git - gcc.git/blob - gcc/config/arm/arm-mve-builtins-shapes.cc
arm: [MVE intrinsics] Add support for void and load/store pointers as argument types.
[gcc.git] / gcc / config / arm / arm-mve-builtins-shapes.cc
1 /* ACLE support for Arm MVE (function shapes)
2 Copyright (C) 2023 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 "memmodel.h"
27 #include "insn-codes.h"
28 #include "optabs.h"
29 #include "arm-mve-builtins.h"
30 #include "arm-mve-builtins-shapes.h"
31
32 /* In the comments below, _t0 represents the first type suffix
33 (e.g. "_s8") and _t1 represents the second. T0/T1 represent the
34 type full names (e.g. int8x16_t). Square brackets enclose
35 characters that are present in only the full name, not the
36 overloaded name. Governing predicate arguments and predicate
37 suffixes are not shown, since they depend on the predication type,
38 which is a separate piece of information from the shape. */
39
40 namespace arm_mve {
41
42 /* Return a representation of "const T *". */
43 static tree
44 build_const_pointer (tree t)
45 {
46 return build_pointer_type (build_qualified_type (t, TYPE_QUAL_CONST));
47 }
48
49 /* If INSTANCE has a predicate, add it to the list of argument types
50 in ARGUMENT_TYPES. RETURN_TYPE is the type returned by the
51 function. */
52 static void
53 apply_predication (const function_instance &instance, tree return_type,
54 vec<tree> &argument_types)
55 {
56 if (instance.pred != PRED_none)
57 {
58 /* When predicate is PRED_m, insert a first argument
59 ("inactive") with the same type as return_type. */
60 if (instance.has_inactive_argument ())
61 argument_types.quick_insert (0, return_type);
62 argument_types.quick_push (get_mve_pred16_t ());
63 }
64 }
65
66 /* Parse and move past an element type in FORMAT and return it as a type
67 suffix. The format is:
68
69 [01] - the element type in type suffix 0 or 1 of INSTANCE.
70 h<elt> - a half-sized version of <elt>
71 p<elt> - a poly type with the same width as <elt>
72 s<bits> - a signed type with the given number of bits
73 s[01] - a signed type with the same width as type suffix 0 or 1
74 u<bits> - an unsigned type with the given number of bits
75 u[01] - an unsigned type with the same width as type suffix 0 or 1
76 U<elt> - an unsigned type with the double width as <elt>
77 w<elt> - a double-sized version of <elt>
78 x<bits> - a type with the given number of bits and same signedness
79 as the next argument.
80
81 Future intrinsics will extend this format. */
82 static type_suffix_index
83 parse_element_type (const function_instance &instance, const char *&format)
84 {
85 int ch = *format++;
86
87
88 if (ch == 's' || ch == 'u')
89 {
90 type_class_index tclass = (ch == 's' ? TYPE_signed
91 : TYPE_unsigned);
92 char *end;
93 unsigned int bits = strtol (format, &end, 10);
94 format = end;
95 if (bits == 0 || bits == 1)
96 bits = instance.type_suffix (bits).element_bits;
97 return find_type_suffix (tclass, bits);
98 }
99
100 if (ch == 'h')
101 {
102 type_suffix_index suffix = parse_element_type (instance, format);
103 return find_type_suffix (type_suffixes[suffix].tclass,
104 type_suffixes[suffix].element_bits / 2);
105 }
106
107 if (ch == 'w')
108 {
109 type_suffix_index suffix = parse_element_type (instance, format);
110 return find_type_suffix (type_suffixes[suffix].tclass,
111 type_suffixes[suffix].element_bits * 2);
112 }
113
114 if (ch == 'U')
115 {
116 type_suffix_index suffix = parse_element_type (instance, format);
117 return find_type_suffix (TYPE_unsigned,
118 type_suffixes[suffix].element_bits * 2);
119 }
120
121 if (ch == 'p')
122 {
123 type_suffix_index suffix = parse_element_type (instance, format);
124 return find_type_suffix (TYPE_poly,
125 type_suffixes[suffix].element_bits);
126 }
127
128 if (ch == 'x')
129 {
130 const char *next = format;
131 next = strstr (format, ",");
132 next+=2;
133 type_suffix_index suffix = parse_element_type (instance, next);
134 type_class_index tclass = type_suffixes[suffix].tclass;
135 char *end;
136 unsigned int bits = strtol (format, &end, 10);
137 format = end;
138 return find_type_suffix (tclass, bits);
139 }
140
141 if (ch == '0' || ch == '1')
142 return instance.type_suffix_ids[ch - '0'];
143
144 gcc_unreachable ();
145 }
146
147 /* Read and return a type from FORMAT for function INSTANCE. Advance
148 FORMAT beyond the type string. The format is:
149
150 _ - void
151 al - array pointer for loads
152 as - array pointer for stores
153 p - predicates with type mve_pred16_t
154 s<elt> - a scalar type with the given element suffix
155 t<elt> - a vector or tuple type with given element suffix [*1]
156 v<elt> - a vector with the given element suffix
157
158 where <elt> has the format described above parse_element_type.
159
160 Future intrinsics will extend this format.
161
162 [*1] the vectors_per_tuple function indicates whether the type should
163 be a tuple, and if so, how many vectors it should contain. */
164 static tree
165 parse_type (const function_instance &instance, const char *&format)
166 {
167 int ch = *format++;
168
169
170 if (ch == '_')
171 return void_type_node;
172
173 if (ch == 'a')
174 {
175 ch = *format++;
176 if (ch == 'l')
177 return build_const_pointer (instance.memory_scalar_type ());
178 if (ch == 's') {
179 return build_pointer_type (instance.memory_scalar_type ());
180 }
181 gcc_unreachable ();
182 }
183
184 if (ch == 'p')
185 return get_mve_pred16_t ();
186
187 if (ch == 's')
188 {
189 type_suffix_index suffix = parse_element_type (instance, format);
190 return scalar_types[type_suffixes[suffix].vector_type];
191 }
192
193 if (ch == 't')
194 {
195 type_suffix_index suffix = parse_element_type (instance, format);
196 vector_type_index vector_type = type_suffixes[suffix].vector_type;
197 unsigned int num_vectors = instance.vectors_per_tuple ();
198 return acle_vector_types[num_vectors - 1][vector_type];
199 }
200
201 if (ch == 'v')
202 {
203 type_suffix_index suffix = parse_element_type (instance, format);
204 return acle_vector_types[0][type_suffixes[suffix].vector_type];
205 }
206
207 gcc_unreachable ();
208 }
209
210 /* Read a type signature for INSTANCE from FORMAT. Add the argument
211 types to ARGUMENT_TYPES and return the return type. Assert there
212 are no more than MAX_ARGS arguments.
213
214 The format is a comma-separated list of types (as for parse_type),
215 with the first type being the return type and the rest being the
216 argument types. */
217 static tree
218 parse_signature (const function_instance &instance, const char *format,
219 vec<tree> &argument_types, unsigned int max_args)
220 {
221 tree return_type = parse_type (instance, format);
222 unsigned int args = 0;
223 while (format[0] == ',')
224 {
225 gcc_assert (args < max_args);
226 format += 1;
227 tree argument_type = parse_type (instance, format);
228 argument_types.quick_push (argument_type);
229 args += 1;
230 }
231 gcc_assert (format[0] == 0);
232 return return_type;
233 }
234
235 /* Add one function instance for GROUP, using mode suffix MODE_SUFFIX_ID,
236 the type suffixes at index TI and the predication suffix at index PI.
237 The other arguments are as for build_all. */
238 static void
239 build_one (function_builder &b, const char *signature,
240 const function_group_info &group, mode_suffix_index mode_suffix_id,
241 unsigned int ti, unsigned int pi, bool preserve_user_namespace,
242 bool force_direct_overloads)
243 {
244 /* Current functions take at most five arguments. Match
245 parse_signature parameter below. */
246 auto_vec<tree, 5> argument_types;
247 function_instance instance (group.base_name, *group.base, *group.shape,
248 mode_suffix_id, group.types[ti],
249 group.preds[pi]);
250 tree return_type = parse_signature (instance, signature, argument_types, 5);
251 apply_predication (instance, return_type, argument_types);
252 b.add_unique_function (instance, return_type, argument_types,
253 preserve_user_namespace, group.requires_float,
254 force_direct_overloads);
255 }
256
257 /* Add a function instance for every type and predicate combination in
258 GROUP, except if requested to use only the predicates listed in
259 RESTRICT_TO_PREDS. Take the function base name from GROUP and the
260 mode suffix from MODE_SUFFIX_ID. Use SIGNATURE to construct the
261 function signature, then use apply_predication to add in the
262 predicate. */
263 static void
264 build_all (function_builder &b, const char *signature,
265 const function_group_info &group, mode_suffix_index mode_suffix_id,
266 bool preserve_user_namespace,
267 bool force_direct_overloads = false,
268 const predication_index *restrict_to_preds = NULL)
269 {
270 for (unsigned int pi = 0; group.preds[pi] != NUM_PREDS; ++pi)
271 {
272 unsigned int pi2 = 0;
273
274 if (restrict_to_preds)
275 for (; restrict_to_preds[pi2] != NUM_PREDS; ++pi2)
276 if (restrict_to_preds[pi2] == group.preds[pi])
277 break;
278
279 if (restrict_to_preds == NULL || restrict_to_preds[pi2] != NUM_PREDS)
280 for (unsigned int ti = 0;
281 ti == 0 || group.types[ti][0] != NUM_TYPE_SUFFIXES; ++ti)
282 build_one (b, signature, group, mode_suffix_id, ti, pi,
283 preserve_user_namespace, force_direct_overloads);
284 }
285 }
286
287 /* Add a function instance for every type and predicate combination in
288 GROUP, except if requested to use only the predicates listed in
289 RESTRICT_TO_PREDS, and only for 16-bit and 32-bit integers. Take
290 the function base name from GROUP and the mode suffix from
291 MODE_SUFFIX_ID. Use SIGNATURE to construct the function signature,
292 then use apply_predication to add in the predicate. */
293 static void
294 build_16_32 (function_builder &b, const char *signature,
295 const function_group_info &group, mode_suffix_index mode_suffix_id,
296 bool preserve_user_namespace,
297 bool force_direct_overloads = false,
298 const predication_index *restrict_to_preds = NULL)
299 {
300 for (unsigned int pi = 0; group.preds[pi] != NUM_PREDS; ++pi)
301 {
302 unsigned int pi2 = 0;
303
304 if (restrict_to_preds)
305 for (; restrict_to_preds[pi2] != NUM_PREDS; ++pi2)
306 if (restrict_to_preds[pi2] == group.preds[pi])
307 break;
308
309 if (restrict_to_preds == NULL || restrict_to_preds[pi2] != NUM_PREDS)
310 for (unsigned int ti = 0;
311 ti == 0 || group.types[ti][0] != NUM_TYPE_SUFFIXES; ++ti)
312 {
313 unsigned int element_bits = type_suffixes[group.types[ti][0]].element_bits;
314 type_class_index tclass = type_suffixes[group.types[ti][0]].tclass;
315 if ((tclass == TYPE_signed || tclass == TYPE_unsigned)
316 && (element_bits == 16 || element_bits == 32))
317 build_one (b, signature, group, mode_suffix_id, ti, pi,
318 preserve_user_namespace, force_direct_overloads);
319 }
320 }
321 }
322
323 /* Declare the function shape NAME, pointing it to an instance
324 of class <NAME>_def. */
325 #define SHAPE(NAME) \
326 static CONSTEXPR const NAME##_def NAME##_obj; \
327 namespace shapes { const function_shape *const NAME = &NAME##_obj; }
328
329 /* Base class for functions that are not overloaded. */
330 struct nonoverloaded_base : public function_shape
331 {
332 bool
333 explicit_type_suffix_p (unsigned int, enum predication_index, enum mode_suffix_index) const override
334 {
335 return true;
336 }
337
338 bool
339 explicit_mode_suffix_p (enum predication_index, enum mode_suffix_index) const override
340 {
341 return true;
342 }
343
344 bool
345 skip_overload_p (enum predication_index, enum mode_suffix_index) const override
346 {
347 return false;
348 }
349
350 tree
351 resolve (function_resolver &) const override
352 {
353 gcc_unreachable ();
354 }
355 };
356
357 /* Base class for overloaded functions. Bit N of EXPLICIT_MASK is true
358 if type suffix N appears in the overloaded name. */
359 template<unsigned int EXPLICIT_MASK>
360 struct overloaded_base : public function_shape
361 {
362 bool
363 explicit_type_suffix_p (unsigned int i, enum predication_index, enum mode_suffix_index) const override
364 {
365 return (EXPLICIT_MASK >> i) & 1;
366 }
367
368 bool
369 explicit_mode_suffix_p (enum predication_index, enum mode_suffix_index) const override
370 {
371 return false;
372 }
373
374 bool
375 skip_overload_p (enum predication_index, enum mode_suffix_index) const override
376 {
377 return false;
378 }
379 };
380
381 /* <T0>_t vfoo[_t0](<T0>_t, <T0>_t)
382
383 i.e. the standard shape for binary operations that operate on
384 uniform types.
385
386 Example: vandq.
387 int8x16_t [__arm_]vandq[_s8](int8x16_t a, int8x16_t b)
388 int8x16_t [__arm_]vandq_m[_s8](int8x16_t inactive, int8x16_t a, int8x16_t b, mve_pred16_t p)
389 int8x16_t [__arm_]vandq_x[_s8](int8x16_t a, int8x16_t b, mve_pred16_t p) */
390 struct binary_def : public overloaded_base<0>
391 {
392 void
393 build (function_builder &b, const function_group_info &group,
394 bool preserve_user_namespace) const override
395 {
396 b.add_overloaded_functions (group, MODE_none, preserve_user_namespace);
397 build_all (b, "v0,v0,v0", group, MODE_none, preserve_user_namespace);
398 }
399
400 tree
401 resolve (function_resolver &r) const override
402 {
403 return r.resolve_uniform (2);
404 }
405 };
406 SHAPE (binary)
407
408 /* <[u]int32>_t vfoo[_<t0>](<T0>_t, <T0>_t)
409
410 i.e. the shape for binary operations that operate on a pair of
411 vectors and produce an int32_t or an uint32_t depending on the
412 signedness of the input elements.
413
414 Example: vmladavq.
415 int32_t [__arm_]vmladavq[_s16](int16x8_t m1, int16x8_t m2)
416 int32_t [__arm_]vmladavq_p[_s16](int16x8_t m1, int16x8_t m2, mve_pred16_t p) */
417 struct binary_acc_int32_def : public overloaded_base<0>
418 {
419 void
420 build (function_builder &b, const function_group_info &group,
421 bool preserve_user_namespace) const override
422 {
423 b.add_overloaded_functions (group, MODE_none, preserve_user_namespace);
424 build_all (b, "sx32,v0,v0", group, MODE_none, preserve_user_namespace);
425 }
426
427 tree
428 resolve (function_resolver &r) const override
429 {
430 return r.resolve_uniform (2);
431 }
432 };
433 SHAPE (binary_acc_int32)
434
435 /* <[u]int64>_t vfoo[_<t0>](<T0>_t, <T0>_t)
436
437 Example: vmlaldavq.
438 int64_t [__arm_]vmlaldavq[_s16](int16x8_t m1, int16x8_t m2)
439 int64_t [__arm_]vmlaldavq_p[_s16](int16x8_t m1, int16x8_t m2, mve_pred16_t p) */
440 struct binary_acc_int64_def : public overloaded_base<0>
441 {
442 void
443 build (function_builder &b, const function_group_info &group,
444 bool preserve_user_namespace) const override
445 {
446 b.add_overloaded_functions (group, MODE_none, preserve_user_namespace);
447 build_all (b, "sx64,v0,v0", group, MODE_none, preserve_user_namespace);
448 }
449
450 tree
451 resolve (function_resolver &r) const override
452 {
453 return r.resolve_uniform (2);
454 }
455 };
456 SHAPE (binary_acc_int64)
457
458 /* <[u]int32>_t vfoo[_<t0>]([u]int32_t, <T0>_t, <T0>_t)
459
460 Example: vmladavaq.
461 int32_t [__arm_]vmladavaq[_s16](int32_t add, int16x8_t m1, int16x8_t m2)
462 int32_t [__arm_]vmladavaq_p[_s16](int32_t add, int16x8_t m1, int16x8_t m2, mve_pred16_t p) */
463 struct binary_acca_int32_def : public overloaded_base<0>
464 {
465 void
466 build (function_builder &b, const function_group_info &group,
467 bool preserve_user_namespace) const override
468 {
469 b.add_overloaded_functions (group, MODE_none, preserve_user_namespace);
470 build_all (b, "sx32,sx32,v0,v0", group, MODE_none, preserve_user_namespace);
471 }
472
473 tree
474 resolve (function_resolver &r) const override
475 {
476 unsigned int i, nargs;
477 type_suffix_index type;
478 if (!r.check_gp_argument (3, i, nargs)
479 || (type = r.infer_vector_type (1)) == NUM_TYPE_SUFFIXES)
480 return error_mark_node;
481
482 unsigned int last_arg = i + 1;
483 for (i = 1; i < last_arg; i++)
484 if (!r.require_matching_vector_type (i, type))
485 return error_mark_node;
486
487 if (!r.require_integer_immediate (0))
488 return error_mark_node;
489
490 return r.resolve_to (r.mode_suffix_id, type);
491 }
492 };
493 SHAPE (binary_acca_int32)
494
495 /* [u]int64_t vfoo[_<t0>]([u]int64_t, <T0>_t, <T0>_t)
496
497 Example: vmlaldavaq.
498 int64_t [__arm_]vmlaldavaq[_s16](int64_t add, int16x8_t m1, int16x8_t m2)
499 int64_t [__arm_]vmlaldavaq_p[_s16](int64_t add, int16x8_t m1, int16x8_t m2, mve_pred16_t p) */
500 struct binary_acca_int64_def : public overloaded_base<0>
501 {
502 void
503 build (function_builder &b, const function_group_info &group,
504 bool preserve_user_namespace) const override
505 {
506 b.add_overloaded_functions (group, MODE_none, preserve_user_namespace);
507 build_all (b, "sx64,sx64,v0,v0", group, MODE_none, preserve_user_namespace);
508 }
509
510 tree
511 resolve (function_resolver &r) const override
512 {
513 unsigned int i, nargs;
514 type_suffix_index type;
515 if (!r.check_gp_argument (3, i, nargs)
516 || (type = r.infer_vector_type (1)) == NUM_TYPE_SUFFIXES)
517 return error_mark_node;
518
519 unsigned int last_arg = i + 1;
520 for (i = 1; i < last_arg; i++)
521 if (!r.require_matching_vector_type (i, type))
522 return error_mark_node;
523
524 if (!r.require_integer_immediate (0))
525 return error_mark_node;
526
527 return r.resolve_to (r.mode_suffix_id, type);
528 }
529 };
530 SHAPE (binary_acca_int64)
531
532 /* <T0>_t vfoo[_n_t0](<T0>_t, int32_t)
533
534 i.e. the shape for binary operations that operate on
535 a vector and an int32_t.
536
537 Example: vbrsrq.
538 int16x8_t [__arm_]vbrsrq[_n_s16](int16x8_t a, int32_t b)
539 int16x8_t [__arm_]vbrsrq_m[_n_s16](int16x8_t inactive, int16x8_t a, int32_t b, mve_pred16_t p)
540 int16x8_t [__arm_]vbrsrq_x[_n_s16](int16x8_t a, int32_t b, mve_pred16_t p) */
541 struct binary_imm32_def : public overloaded_base<0>
542 {
543 void
544 build (function_builder &b, const function_group_info &group,
545 bool preserve_user_namespace) const override
546 {
547 b.add_overloaded_functions (group, MODE_n, preserve_user_namespace);
548 build_all (b, "v0,v0,ss32", group, MODE_n, preserve_user_namespace);
549 }
550
551 tree
552 resolve (function_resolver &r) const override
553 {
554 return r.resolve_uniform (1, 1);
555 }
556 };
557 SHAPE (binary_imm32)
558
559 /* <T0>_t vfoo[_n_t0](<T0>_t, const int)
560
561 Shape for vector shift right operations that take a vector first
562 argument and an integer, and produce a vector.
563
564 Check that 'imm' is in the [1..#bits] range.
565
566 Example: vrshrq.
567 int8x16_t [__arm_]vrshrq[_n_s8](int8x16_t a, const int imm)
568 int8x16_t [__arm_]vrshrq_m[_n_s8](int8x16_t inactive, int8x16_t a, const int imm, mve_pred16_t p)
569 int8x16_t [__arm_]vrshrq_x[_n_s8](int8x16_t a, const int imm, mve_pred16_t p) */
570 struct binary_rshift_def : public overloaded_base<0>
571 {
572 void
573 build (function_builder &b, const function_group_info &group,
574 bool preserve_user_namespace) const override
575 {
576 b.add_overloaded_functions (group, MODE_n, preserve_user_namespace);
577 build_all (b, "v0,v0,ss32", group, MODE_n, preserve_user_namespace);
578 }
579
580 tree
581 resolve (function_resolver &r) const override
582 {
583 return r.resolve_uniform (1, 1);
584 }
585
586 bool
587 check (function_checker &c) const override
588 {
589 unsigned int bits = c.type_suffix (0).element_bits;
590 return c.require_immediate_range (1, 1, bits);
591 }
592 };
593 SHAPE (binary_rshift)
594
595
596 /* <uT0>_t vfoo[_n_t0](<T0>_t, int)
597
598 Shape for vector saturating shift left operations that take a
599 vector of signed elements as first argument and an integer, and
600 produce a vector of unsigned elements.
601
602 Check that 'imm' is in the [0..#bits-1] range.
603
604 Example: vqshluq.
605 uint16x8_t [__arm_]vqshluq[_n_s16](int16x8_t a, const int imm)
606 uint16x8_t [__arm_]vqshluq_m[_n_s16](uint16x8_t inactive, int16x8_t a, const int imm, mve_pred16_t p) */
607 struct binary_lshift_unsigned_def : public overloaded_base<0>
608 {
609 void
610 build (function_builder &b, const function_group_info &group,
611 bool preserve_user_namespace) const override
612 {
613 b.add_overloaded_functions (group, MODE_n, preserve_user_namespace);
614 build_all (b, "vu0,vs0,ss32", group, MODE_n, preserve_user_namespace);
615 }
616
617 tree
618 resolve (function_resolver &r) const override
619 {
620 unsigned int i, nargs;
621 type_suffix_index type;
622 if (!r.check_gp_argument (2, i, nargs)
623 || (type = r.infer_vector_type (i-1)) == NUM_TYPE_SUFFIXES)
624 return error_mark_node;
625
626 if (r.pred == PRED_m)
627 {
628 /* With PRED_m, check that the 'inactive' first argument has
629 the expeected unsigned type. */
630 type_suffix_index return_type
631 = find_type_suffix (TYPE_unsigned, type_suffixes[type].element_bits);
632
633 if (!r.require_matching_vector_type (0, return_type))
634 return error_mark_node;
635 }
636
637 for (; i < nargs; ++i)
638 if (!r.require_integer_immediate (i))
639 return error_mark_node;
640
641 return r.resolve_to (r.mode_suffix_id, type);
642 }
643
644 bool
645 check (function_checker &c) const override
646 {
647 unsigned int bits = c.type_suffix (0).element_bits;
648 return c.require_immediate_range (1, 0, bits - 1);
649 }
650
651 };
652 SHAPE (binary_lshift_unsigned)
653
654 /* <uT0>_t vfoo[_t0](<uT0>_t, <T0>_t)
655
656 i.e. binary operations that take a vector of unsigned elements as first argument and a
657 vector of signed elements as second argument, and produce a vector of unsigned elements.
658
659 Example: vminaq.
660 uint8x16_t [__arm_]vminaq[_s8](uint8x16_t a, int8x16_t b)
661 uint8x16_t [__arm_]vminaq_m[_s8](uint8x16_t a, int8x16_t b, mve_pred16_t p) */
662 struct binary_maxamina_def : public overloaded_base<0>
663 {
664 void
665 build (function_builder &b, const function_group_info &group,
666 bool preserve_user_namespace) const override
667 {
668 b.add_overloaded_functions (group, MODE_none, preserve_user_namespace);
669 build_all (b, "vu0,vu0,vs0", group, MODE_none, preserve_user_namespace);
670 }
671
672 tree
673 resolve (function_resolver &r) const override
674 {
675 unsigned int i, nargs;
676 type_suffix_index type;
677 if (!r.check_gp_argument (2, i, nargs)
678 || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES)
679 return error_mark_node;
680
681 /* Check that the first argument has the expeected unsigned
682 type. */
683 type_suffix_index return_type
684 = find_type_suffix (TYPE_unsigned, type_suffixes[type].element_bits);
685 if (!r.require_matching_vector_type (0, return_type))
686 return error_mark_node;
687
688 return r.resolve_to (r.mode_suffix_id, type);
689 }
690 };
691 SHAPE (binary_maxamina)
692
693 /* <uS0>_t vfoo[_<t0>](<uS0>_t, <T0>_t)
694
695 Example: vmaxavq.
696 uint8_t [__arm_]vmaxavq[_s8](uint8_t a, int8x16_t b)
697 uint8_t [__arm_]vmaxavq_p[_s8](uint8_t a, int8x16_t b, mve_pred16_t p) */
698 struct binary_maxavminav_def : public overloaded_base<0>
699 {
700 void
701 build (function_builder &b, const function_group_info &group,
702 bool preserve_user_namespace) const override
703 {
704 b.add_overloaded_functions (group, MODE_none, preserve_user_namespace);
705 build_all (b, "su0,su0,v0", group, MODE_none, preserve_user_namespace);
706 }
707
708 tree
709 resolve (function_resolver &r) const override
710 {
711 unsigned int i, nargs;
712 type_suffix_index type;
713 if (!r.check_gp_argument (2, i, nargs)
714 || !r.require_derived_scalar_type (0, TYPE_unsigned)
715 || (type = r.infer_vector_type (1)) == NUM_TYPE_SUFFIXES)
716 return error_mark_node;
717
718 return r.resolve_to (r.mode_suffix_id, type);
719 }
720 };
721 SHAPE (binary_maxavminav)
722
723 /* <S0>_t vfoo[_<t0>](<S0>_t, <T0>_t)
724
725 Example: vmaxvq.
726 int8_t [__arm_]vmaxvq[_s8](int8_t a, int8x16_t b)
727 int8_t [__arm_]vmaxvq_p[_s8](int8_t a, int8x16_t b, mve_pred16_t p) */
728 struct binary_maxvminv_def : public overloaded_base<0>
729 {
730 void
731 build (function_builder &b, const function_group_info &group,
732 bool preserve_user_namespace) const override
733 {
734 b.add_overloaded_functions (group, MODE_none, preserve_user_namespace);
735 build_all (b, "s0,s0,v0", group, MODE_none, preserve_user_namespace);
736 }
737
738 tree
739 resolve (function_resolver &r) const override
740 {
741 unsigned int i, nargs;
742 type_suffix_index type;
743 if (!r.check_gp_argument (2, i, nargs)
744 || !r.require_derived_scalar_type (0, r.SAME_TYPE_CLASS)
745 || (type = r.infer_vector_type (1)) == NUM_TYPE_SUFFIXES)
746 return error_mark_node;
747
748 return r.resolve_to (r.mode_suffix_id, type);
749 }
750 };
751 SHAPE (binary_maxvminv)
752
753 /* <T0:half>_t vfoo[_t0](<T0:half>_t, <T0>_t)
754
755 Example: vmovnbq.
756 int8x16_t [__arm_]vmovnbq[_s16](int8x16_t a, int16x8_t b)
757 int8x16_t [__arm_]vmovnbq_m[_s16](int8x16_t a, int16x8_t b, mve_pred16_t p) */
758 struct binary_move_narrow_def : public overloaded_base<0>
759 {
760 void
761 build (function_builder &b, const function_group_info &group,
762 bool preserve_user_namespace) const override
763 {
764 b.add_overloaded_functions (group, MODE_none, preserve_user_namespace);
765 build_all (b, "vh0,vh0,v0", group, MODE_none, preserve_user_namespace);
766 }
767
768 tree
769 resolve (function_resolver &r) const override
770 {
771 unsigned int i, nargs;
772 type_suffix_index type;
773 if (!r.check_gp_argument (2, i, nargs)
774 || (type = r.infer_vector_type (1)) == NUM_TYPE_SUFFIXES)
775 return error_mark_node;
776
777 type_suffix_index narrow_suffix
778 = find_type_suffix (type_suffixes[type].tclass,
779 type_suffixes[type].element_bits / 2);
780
781
782 if (!r.require_matching_vector_type (0, narrow_suffix))
783 return error_mark_node;
784
785 return r.resolve_to (r.mode_suffix_id, type);
786 }
787 };
788 SHAPE (binary_move_narrow)
789
790 /* <uT0:half>_t vfoo[_t0](<uT0:half>_t, <T0>_t)
791
792 Example: vqmovunbq.
793 uint8x16_t [__arm_]vqmovunbq[_s16](uint8x16_t a, int16x8_t b)
794 uint8x16_t [__arm_]vqmovunbq_m[_s16](uint8x16_t a, int16x8_t b, mve_pred16_t p) */
795 struct binary_move_narrow_unsigned_def : public overloaded_base<0>
796 {
797 void
798 build (function_builder &b, const function_group_info &group,
799 bool preserve_user_namespace) const override
800 {
801 b.add_overloaded_functions (group, MODE_none, preserve_user_namespace);
802 build_all (b, "vhu0,vhu0,v0", group, MODE_none, preserve_user_namespace);
803 }
804
805 tree
806 resolve (function_resolver &r) const override
807 {
808 unsigned int i, nargs;
809 type_suffix_index type;
810 if (!r.check_gp_argument (2, i, nargs)
811 || (type = r.infer_vector_type (1)) == NUM_TYPE_SUFFIXES)
812 return error_mark_node;
813
814 type_suffix_index narrow_suffix
815 = find_type_suffix (TYPE_unsigned,
816 type_suffixes[type].element_bits / 2);
817
818 if (!r.require_matching_vector_type (0, narrow_suffix))
819 return error_mark_node;
820
821 return r.resolve_to (r.mode_suffix_id, type);
822 }
823 };
824 SHAPE (binary_move_narrow_unsigned)
825
826 /* <T0>_t vfoo[_t0](<T0>_t, <T0>_t)
827 <T0>_t vfoo[_n_t0](<T0>_t, <S0>_t)
828
829 i.e. the standard shape for binary operations that operate on
830 uniform types.
831
832 Example: vaddq.
833 int8x16_t [__arm_]vaddq[_s8](int8x16_t a, int8x16_t b)
834 int8x16_t [__arm_]vaddq[_n_s8](int8x16_t a, int8_t b)
835 int8x16_t [__arm_]vaddq_m[_s8](int8x16_t inactive, int8x16_t a, int8x16_t b, mve_pred16_t p)
836 int8x16_t [__arm_]vaddq_m[_n_s8](int8x16_t inactive, int8x16_t a, int8_t b, mve_pred16_t p)
837 int8x16_t [__arm_]vaddq_x[_s8](int8x16_t a, int8x16_t b, mve_pred16_t p)
838 int8x16_t [__arm_]vaddq_x[_n_s8](int8x16_t a, int8_t b, mve_pred16_t p) */
839 struct binary_opt_n_def : public overloaded_base<0>
840 {
841 void
842 build (function_builder &b, const function_group_info &group,
843 bool preserve_user_namespace) const override
844 {
845 b.add_overloaded_functions (group, MODE_none, preserve_user_namespace);
846 build_all (b, "v0,v0,v0", group, MODE_none, preserve_user_namespace);
847 build_all (b, "v0,v0,s0", group, MODE_n, preserve_user_namespace);
848 }
849
850 tree
851 resolve (function_resolver &r) const override
852 {
853 return r.resolve_uniform_opt_n (2);
854 }
855 };
856 SHAPE (binary_opt_n)
857
858 /* <T0>_t vfoo[t0](<T0>_t, <T0>_t)
859 <T0>_t vfoo[_n_t0](<T0>_t, <S0>_t)
860
861 Where the _n form only supports s16/s32/u16/u32 types as for vorrq.
862
863 Example: vorrq.
864 int16x8_t [__arm_]vorrq[_s16](int16x8_t a, int16x8_t b)
865 int16x8_t [__arm_]vorrq_m[_s16](int16x8_t inactive, int16x8_t a, int16x8_t b, mve_pred16_t p)
866 int16x8_t [__arm_]vorrq_x[_s16](int16x8_t a, int16x8_t b, mve_pred16_t p)
867 int16x8_t [__arm_]vorrq[_n_s16](int16x8_t a, const int16_t imm)
868 int16x8_t [__arm_]vorrq_m_n[_s16](int16x8_t a, const int16_t imm, mve_pred16_t p) */
869 struct binary_orrq_def : public overloaded_base<0>
870 {
871 bool
872 explicit_mode_suffix_p (enum predication_index pred, enum mode_suffix_index mode) const override
873 {
874 return (mode == MODE_n
875 && pred == PRED_m);
876 }
877
878 bool
879 skip_overload_p (enum predication_index pred, enum mode_suffix_index mode) const override
880 {
881 switch (mode)
882 {
883 case MODE_none:
884 return false;
885
886 /* For MODE_n, share the overloaded instance with MODE_none, except for PRED_m. */
887 case MODE_n:
888 return pred != PRED_m;
889
890 default:
891 gcc_unreachable ();
892 }
893 }
894
895 void
896 build (function_builder &b, const function_group_info &group,
897 bool preserve_user_namespace) const override
898 {
899 b.add_overloaded_functions (group, MODE_none, preserve_user_namespace);
900 b.add_overloaded_functions (group, MODE_n, preserve_user_namespace);
901 build_all (b, "v0,v0,v0", group, MODE_none, preserve_user_namespace);
902 build_16_32 (b, "v0,v0,s0", group, MODE_n, preserve_user_namespace, false, preds_m_or_none);
903 }
904
905 tree
906 resolve (function_resolver &r) const override
907 {
908 unsigned int i, nargs;
909 type_suffix_index type;
910 if (!r.check_gp_argument (2, i, nargs)
911 || (type = r.infer_vector_type (0)) == NUM_TYPE_SUFFIXES)
912 return error_mark_node;
913
914 return r.finish_opt_n_resolution (i, 0, type);
915 }
916 };
917 SHAPE (binary_orrq)
918
919 /* <T0>_t vfoo[t0](<T0>_t, <T0>_t)
920 <T0>_t vfoo[_n_t0](<T0>_t, int32_t)
921
922 Shape for rounding shift left operations.
923
924 Example: vrshlq.
925 int8x16_t [__arm_]vrshlq[_n_s8](int8x16_t a, int32_t b)
926 int8x16_t [__arm_]vrshlq_m_n[_s8](int8x16_t a, int32_t b, mve_pred16_t p)
927 int8x16_t [__arm_]vrshlq[_s8](int8x16_t a, int8x16_t b)
928 int8x16_t [__arm_]vrshlq_m[_s8](int8x16_t inactive, int8x16_t a, int8x16_t b, mve_pred16_t p)
929 int8x16_t [__arm_]vrshlq_x[_s8](int8x16_t a, int8x16_t b, mve_pred16_t p) */
930 struct binary_round_lshift_def : public overloaded_base<0>
931 {
932 bool
933 explicit_mode_suffix_p (enum predication_index pred, enum mode_suffix_index mode) const override
934 {
935 return ((mode == MODE_n)
936 && (pred == PRED_m));
937 }
938
939 bool
940 skip_overload_p (enum predication_index pred, enum mode_suffix_index mode) const override
941 {
942 switch (mode)
943 {
944 case MODE_none:
945 return false;
946
947 /* For MODE_n, share the overloaded instance with MODE_none, except for PRED_m. */
948 case MODE_n:
949 return pred != PRED_m;
950
951 default:
952 gcc_unreachable ();
953 }
954 }
955
956 void
957 build (function_builder &b, const function_group_info &group,
958 bool preserve_user_namespace) const override
959 {
960 b.add_overloaded_functions (group, MODE_none, preserve_user_namespace);
961 b.add_overloaded_functions (group, MODE_n, preserve_user_namespace);
962 build_all (b, "v0,v0,vs0", group, MODE_none, preserve_user_namespace);
963 build_all (b, "v0,v0,ss32", group, MODE_n, preserve_user_namespace, false, preds_m_or_none);
964 }
965
966 tree
967 resolve (function_resolver &r) const override
968 {
969 unsigned int i, nargs;
970 type_suffix_index type;
971 if (!r.check_gp_argument (2, i, nargs)
972 || (type = r.infer_vector_type (0)) == NUM_TYPE_SUFFIXES)
973 return error_mark_node;
974
975 return r.finish_opt_n_resolution (i, 0, type, TYPE_signed);
976 }
977 };
978 SHAPE (binary_round_lshift)
979
980 /* <T0>_t vfoo[_t0](<T0>_t, <T0>_t)
981 <T0>_t vfoo_n[_t0](<T0>_t, const int)
982
983 i.e. the standard shape for left shift operations that operate on
984 vector types.
985
986 For the MODE_n versions, check that 'imm' is in the [0..#bits-1] range.
987
988 Example: vshlq.
989 int8x16_t [__arm_]vshlq[_s8](int8x16_t a, int8x16_t b)
990 int8x16_t [__arm_]vshlq_m[_s8](int8x16_t inactive, int8x16_t a, int8x16_t b, mve_pred16_t p)
991 int8x16_t [__arm_]vshlq_x[_s8](int8x16_t a, int8x16_t b, mve_pred16_t p)
992 int8x16_t [__arm_]vshlq_n[_s8](int8x16_t a, const int imm)
993 int8x16_t [__arm_]vshlq_m_n[_s8](int8x16_t inactive, int8x16_t a, const int imm, mve_pred16_t p)
994 int8x16_t [__arm_]vshlq_x_n[_s8](int8x16_t a, const int imm, mve_pred16_t p) */
995 struct binary_lshift_def : public overloaded_base<0>
996 {
997 bool
998 explicit_mode_suffix_p (enum predication_index, enum mode_suffix_index) const override
999 {
1000 return true;
1001 }
1002
1003 void
1004 build (function_builder &b, const function_group_info &group,
1005 bool preserve_user_namespace) const override
1006 {
1007 b.add_overloaded_functions (group, MODE_none, preserve_user_namespace);
1008 b.add_overloaded_functions (group, MODE_n, preserve_user_namespace);
1009 build_all (b, "v0,v0,vs0", group, MODE_none, preserve_user_namespace);
1010 build_all (b, "v0,v0,ss32", group, MODE_n, preserve_user_namespace);
1011 }
1012
1013 tree
1014 resolve (function_resolver &r) const override
1015 {
1016 unsigned int i, nargs;
1017 type_suffix_index type;
1018 if (!r.check_gp_argument (2, i, nargs)
1019 || (type = r.infer_vector_type (0)) == NUM_TYPE_SUFFIXES)
1020 return error_mark_node;
1021
1022 return r.finish_opt_n_resolution (i, 0, type, TYPE_signed);
1023 }
1024
1025 bool
1026 check (function_checker &c) const override
1027 {
1028 if (c.mode_suffix_id != MODE_n)
1029 return true;
1030
1031 unsigned int bits = c.type_suffix (0).element_bits;
1032 return c.require_immediate_range (1, 0, bits - 1);
1033 }
1034 };
1035 SHAPE (binary_lshift)
1036
1037 /* Used with the above form, but only for the MODE_r case which does
1038 not always support the same set of predicates as MODE_none and
1039 MODE_n. For vqshlq they are the same, but for vshlq they are not.
1040
1041 <T0>_t vfoo_r[_t0](<T0>_t, int32_t)
1042
1043 i.e. the standard shape for shift operations that operate on
1044 vector types.
1045 Example: vshlq.
1046 int8x16_t [__arm_]vshlq_r[_s8](int8x16_t a, int32_t b)
1047 int8x16_t [__arm_]vshlq_m_r[_s8](int8x16_t a, int32_t b, mve_pred16_t p) */
1048 struct binary_lshift_r_def : public overloaded_base<0>
1049 {
1050 bool
1051 explicit_mode_suffix_p (enum predication_index, enum mode_suffix_index) const override
1052 {
1053 return true;
1054 }
1055
1056 void
1057 build (function_builder &b, const function_group_info &group,
1058 bool preserve_user_namespace) const override
1059 {
1060 b.add_overloaded_functions (group, MODE_r, preserve_user_namespace);
1061 build_all (b, "v0,v0,ss32", group, MODE_r, preserve_user_namespace, false, preds_m_or_none);
1062 }
1063
1064 tree
1065 resolve (function_resolver &r) const override
1066 {
1067 unsigned int i, nargs;
1068 type_suffix_index type;
1069 if (!r.check_gp_argument (2, i, nargs)
1070 || (type = r.infer_vector_type (0)) == NUM_TYPE_SUFFIXES)
1071 return error_mark_node;
1072
1073 return r.finish_opt_n_resolution (i, 0, type, TYPE_signed);
1074 }
1075 };
1076 SHAPE (binary_lshift_r)
1077
1078 /* <T0:half>_t vfoo[_n_t0](<T0:half>_t, <T0>_t, const int)
1079
1080 Narrowing right shifts.
1081 Check that 'imm' is in the [1..#bits/2] range.
1082
1083 Example: vqrshrnbq.
1084 int8x16_t [__arm_]vqrshrnbq[_n_s16](int8x16_t a, int16x8_t b, const int imm)
1085 int8x16_t [__arm_]vqrshrnbq_m[_n_s16](int8x16_t a, int16x8_t b, const int imm, mve_pred16_t p) */
1086 struct binary_rshift_narrow_def : public overloaded_base<0>
1087 {
1088 void
1089 build (function_builder &b, const function_group_info &group,
1090 bool preserve_user_namespace) const override
1091 {
1092 b.add_overloaded_functions (group, MODE_n, preserve_user_namespace);
1093 build_all (b, "vh0,vh0,v0,ss32", group, MODE_n, preserve_user_namespace);
1094 }
1095
1096 tree
1097 resolve (function_resolver &r) const override
1098 {
1099 unsigned int i, nargs;
1100 type_suffix_index type;
1101 if (!r.check_gp_argument (3, i, nargs)
1102 || (type = r.infer_vector_type (1)) == NUM_TYPE_SUFFIXES
1103 || !r.require_integer_immediate (i))
1104 return error_mark_node;
1105
1106 type_suffix_index narrow_suffix
1107 = find_type_suffix (type_suffixes[type].tclass,
1108 type_suffixes[type].element_bits / 2);
1109
1110 if (!r.require_matching_vector_type (0, narrow_suffix))
1111 return error_mark_node;
1112
1113 return r.resolve_to (r.mode_suffix_id, type);
1114 }
1115
1116 bool
1117 check (function_checker &c) const override
1118 {
1119 unsigned int bits = c.type_suffix (0).element_bits;
1120 return c.require_immediate_range (2, 1, bits / 2);
1121 }
1122 };
1123 SHAPE (binary_rshift_narrow)
1124
1125 /* <uT0:half>_t vfoo[_n_t0](<uT0:half>_t, <T0>_t, const int)
1126
1127 Vector saturating rounding shift right and narrow.
1128 Check that 'imm' is in the [1..#bits/2] range.
1129
1130 Example: vqshrunbq.
1131 uint8x16_t [__arm_]vqshrunbq[_n_s16](uint8x16_t a, int16x8_t b, const int imm)
1132 uint8x16_t [__arm_]vqshrunbq_m[_n_s16](uint8x16_t a, int16x8_t b, const int imm, mve_pred16_t p) */
1133 struct binary_rshift_narrow_unsigned_def : public overloaded_base<0>
1134 {
1135 void
1136 build (function_builder &b, const function_group_info &group,
1137 bool preserve_user_namespace) const override
1138 {
1139 b.add_overloaded_functions (group, MODE_n, preserve_user_namespace);
1140 build_all (b, "vhu0,vhu0,v0,ss32", group, MODE_n, preserve_user_namespace);
1141 }
1142
1143 tree
1144 resolve (function_resolver &r) const override
1145 {
1146 unsigned int i, nargs;
1147 type_suffix_index type;
1148 if (!r.check_gp_argument (3, i, nargs)
1149 || (type = r.infer_vector_type (1)) == NUM_TYPE_SUFFIXES
1150 || !r.require_integer_immediate (i))
1151 return error_mark_node;
1152
1153 type_suffix_index narrow_suffix
1154 = find_type_suffix (TYPE_unsigned,
1155 type_suffixes[type].element_bits / 2);
1156
1157 if (!r.require_matching_vector_type (0, narrow_suffix))
1158 return error_mark_node;
1159
1160 return r.resolve_to (r.mode_suffix_id, type);
1161 }
1162
1163 bool
1164 check (function_checker &c) const override
1165 {
1166 unsigned int bits = c.type_suffix (0).element_bits;
1167 return c.require_immediate_range (2, 1, bits / 2);
1168 }
1169
1170 };
1171 SHAPE (binary_rshift_narrow_unsigned)
1172
1173 /* <T0:twice>_t vfoo[_t0](<T0>_t, <T0>_t)
1174
1175 Example: vmullbq.
1176 int32x4_t [__arm_]vmullbq_int[_s16](int16x8_t a, int16x8_t b)
1177 int32x4_t [__arm_]vmullbq_int_m[_s16](int32x4_t inactive, int16x8_t a, int16x8_t b, mve_pred16_t p)
1178 int32x4_t [__arm_]vmullbq_int_x[_s16](int16x8_t a, int16x8_t b, mve_pred16_t p) */
1179 struct binary_widen_def : public overloaded_base<0>
1180 {
1181 void
1182 build (function_builder &b, const function_group_info &group,
1183 bool preserve_user_namespace) const override
1184 {
1185 b.add_overloaded_functions (group, MODE_none, preserve_user_namespace);
1186 build_all (b, "vw0,v0,v0", group, MODE_none, preserve_user_namespace);
1187 }
1188
1189 tree
1190 resolve (function_resolver &r) const override
1191 {
1192 unsigned int i, nargs;
1193 type_suffix_index type;
1194 if (!r.check_gp_argument (2, i, nargs)
1195 || (type = r.infer_vector_type (i - 1)) == NUM_TYPE_SUFFIXES)
1196 return error_mark_node;
1197
1198 type_suffix_index wide_suffix
1199 = find_type_suffix (type_suffixes[type].tclass,
1200 type_suffixes[type].element_bits * 2);
1201
1202 if (!r.require_matching_vector_type (i, type))
1203 return error_mark_node;
1204
1205 /* Check the inactive argument has the wide type. */
1206 if ((r.pred == PRED_m)
1207 && (r.infer_vector_type (0) != wide_suffix))
1208 return r.report_no_such_form (type);
1209
1210 return r.resolve_to (r.mode_suffix_id, type);
1211 }
1212 };
1213 SHAPE (binary_widen)
1214
1215 /* <T0:twice>_t vfoo[_t0](<T0>_t, <T0>_t)
1216
1217 Example: vmullbq_poly.
1218 uint32x4_t [__arm_]vmullbq_poly[_p16](uint16x8_t a, uint16x8_t b)
1219 uint32x4_t [__arm_]vmullbq_poly_m[_p16](uint32x4_t inactive, uint16x8_t a, uint16x8_t b, mve_pred16_t p)
1220 uint32x4_t [__arm_]vmullbq_poly_x[_p16](uint16x8_t a, uint16x8_t b, mve_pred16_t p) */
1221 struct binary_widen_poly_def : public overloaded_base<0>
1222 {
1223 void
1224 build (function_builder &b, const function_group_info &group,
1225 bool preserve_user_namespace) const override
1226 {
1227 b.add_overloaded_functions (group, MODE_none, preserve_user_namespace);
1228 build_all (b, "vU0,vp0,vp0", group, MODE_none, preserve_user_namespace);
1229 }
1230
1231 tree
1232 resolve (function_resolver &r) const override
1233 {
1234 unsigned int i, nargs;
1235 type_suffix_index type;
1236 if (!r.check_gp_argument (2, i, nargs)
1237 || (type = r.infer_vector_type (i - 1)) == NUM_TYPE_SUFFIXES)
1238 return error_mark_node;
1239
1240 /* infer_vector_type found the 'unsigned' version of the 'poly'
1241 type we are looking for, so find the 'poly' type with the same
1242 width. */
1243 type = find_type_suffix (TYPE_poly, type_suffixes[type].element_bits);
1244
1245 type_suffix_index wide_suffix
1246 = find_type_suffix (TYPE_unsigned,
1247 type_suffixes[type].element_bits * 2);
1248
1249 /* Require the 'poly' type, require_matching_vector_type would try
1250 and fail with the 'unsigned' one. */
1251 if (!r.require_vector_type (i, type_suffixes[type].vector_type))
1252 return error_mark_node;
1253
1254 /* Check the inactive argument has the wide type. */
1255 if ((r.pred == PRED_m)
1256 && (r.infer_vector_type (0) != wide_suffix))
1257 return r.report_no_such_form (type);
1258
1259 return r.resolve_to (r.mode_suffix_id, type);
1260 }
1261 };
1262 SHAPE (binary_widen_poly)
1263
1264 /* <T0:twice>_t vfoo[_n_t0](<T0>_t, const int)
1265
1266 Check that 'imm' is in the [1..#bits] range.
1267
1268 Example: vshllbq.
1269 int16x8_t [__arm_]vshllbq[_n_s8](int8x16_t a, const int imm)
1270 int16x8_t [__arm_]vshllbq_m[_n_s8](int16x8_t inactive, int8x16_t a, const int imm, mve_pred16_t p)
1271 int16x8_t [__arm_]vshllbq_x[_n_s8](int8x16_t a, const int imm, mve_pred16_t p) */
1272 struct binary_widen_n_def : public overloaded_base<0>
1273 {
1274 void
1275 build (function_builder &b, const function_group_info &group,
1276 bool preserve_user_namespace) const override
1277 {
1278 b.add_overloaded_functions (group, MODE_n, preserve_user_namespace);
1279 build_all (b, "vw0,v0,s0", group, MODE_n, preserve_user_namespace);
1280 }
1281
1282 tree
1283 resolve (function_resolver &r) const override
1284 {
1285 unsigned int i, nargs;
1286 type_suffix_index type;
1287 tree res;
1288 if (!r.check_gp_argument (2, i, nargs)
1289 || (type = r.infer_vector_type (i - 1)) == NUM_TYPE_SUFFIXES
1290 || !r.require_integer_immediate (i))
1291 return error_mark_node;
1292
1293 type_suffix_index wide_suffix
1294 = find_type_suffix (type_suffixes[type].tclass,
1295 type_suffixes[type].element_bits * 2);
1296
1297 /* Check the inactive argument has the wide type. */
1298 if (((r.pred == PRED_m) && (r.infer_vector_type (0) == wide_suffix))
1299 || r.pred == PRED_none
1300 || r.pred == PRED_x)
1301 if ((res = r.lookup_form (r.mode_suffix_id, type)))
1302 return res;
1303
1304 return r.report_no_such_form (type);
1305 }
1306
1307 bool
1308 check (function_checker &c) const override
1309 {
1310 unsigned int bits = c.type_suffix (0).element_bits;
1311 return c.require_immediate_range (1, 1, bits);
1312 }
1313
1314 };
1315 SHAPE (binary_widen_n)
1316
1317 /* <T0:twice>_t vfoo[_t0](<T0>_t, <T0>_t)
1318 <T0:twice>_t vfoo[_n_t0](<T0>_t, <S0>_t)
1319
1320 Example: vqdmullbq.
1321 int32x4_t [__arm_]vqdmulltq[_n_s16](int16x8_t a, int16_t b)
1322 int32x4_t [__arm_]vqdmulltq_m[_n_s16](int32x4_t inactive, int16x8_t a, int16_t b, mve_pred16_t p)
1323 int32x4_t [__arm_]vqdmulltq[_s16](int16x8_t a, int16x8_t b)
1324 int32x4_t [__arm_]vqdmulltq_m[_s16](int32x4_t inactive, int16x8_t a, int16x8_t b, mve_pred16_t p) */
1325 struct binary_widen_opt_n_def : public overloaded_base<0>
1326 {
1327 void
1328 build (function_builder &b, const function_group_info &group,
1329 bool preserve_user_namespace) const override
1330 {
1331 b.add_overloaded_functions (group, MODE_none, preserve_user_namespace);
1332 build_all (b, "vw0,v0,v0", group, MODE_none, preserve_user_namespace);
1333 build_all (b, "vw0,v0,s0", group, MODE_n, preserve_user_namespace);
1334 }
1335
1336 tree
1337 resolve (function_resolver &r) const override
1338 {
1339 unsigned int i, nargs;
1340 type_suffix_index type;
1341 if (!r.check_gp_argument (2, i, nargs)
1342 || (type = r.infer_vector_type (i - 1)) == NUM_TYPE_SUFFIXES)
1343 return error_mark_node;
1344
1345 type_suffix_index wide_suffix
1346 = find_type_suffix (type_suffixes[type].tclass,
1347 type_suffixes[type].element_bits * 2);
1348
1349 /* Skip last argument, may be scalar, will be checked below by
1350 finish_opt_n_resolution. */
1351 unsigned int last_arg = i--;
1352 for (; i > 0; i--)
1353 if (!r.require_matching_vector_type (i, type))
1354 return error_mark_node;
1355
1356 /* Check the inactive argument has the wide type. */
1357 if ((r.pred == PRED_m)
1358 && (r.infer_vector_type (0) != wide_suffix))
1359 return r.report_no_such_form (type);
1360
1361 return r.finish_opt_n_resolution (last_arg, 0, type);
1362 }
1363 };
1364 SHAPE (binary_widen_opt_n)
1365
1366 /* Shape for comparison operations that operate on
1367 uniform types.
1368
1369 Examples: vcmpq.
1370 mve_pred16_t [__arm_]vcmpeqq[_s16](int16x8_t a, int16x8_t b)
1371 mve_pred16_t [__arm_]vcmpeqq[_n_s16](int16x8_t a, int16_t b)
1372 mve_pred16_t [__arm_]vcmpeqq_m[_s16](int16x8_t a, int16x8_t b, mve_pred16_t p)
1373 mve_pred16_t [__arm_]vcmpeqq_m[_n_s16](int16x8_t a, int16_t b, mve_pred16_t p) */
1374 struct cmp_def : public overloaded_base<0>
1375 {
1376 void
1377 build (function_builder &b, const function_group_info &group,
1378 bool preserve_user_namespace) const override
1379 {
1380 b.add_overloaded_functions (group, MODE_none, preserve_user_namespace);
1381 build_all (b, "p,v0,v0", group, MODE_none, preserve_user_namespace);
1382 build_all (b, "p,v0,s0", group, MODE_n, preserve_user_namespace);
1383 }
1384
1385 tree
1386 resolve (function_resolver &r) const override
1387 {
1388 return r.resolve_uniform_opt_n (2);
1389 }
1390 };
1391 SHAPE (cmp)
1392
1393 /* <T0>xN_t vfoo[_t0](uint64_t, uint64_t)
1394
1395 where there are N arguments in total.
1396 Example: vcreateq.
1397 int16x8_t [__arm_]vcreateq_s16(uint64_t a, uint64_t b) */
1398 struct create_def : public nonoverloaded_base
1399 {
1400 void
1401 build (function_builder &b, const function_group_info &group,
1402 bool preserve_user_namespace) const override
1403 {
1404 build_all (b, "v0,su64,su64", group, MODE_none, preserve_user_namespace);
1405 }
1406
1407 tree
1408 resolve (function_resolver &r) const override
1409 {
1410 return r.resolve_uniform (0, 2);
1411 }
1412 };
1413 SHAPE (create)
1414
1415 /* <T0>[xN]_t vfoo_t0().
1416
1417 Example: vuninitializedq.
1418 int8x16_t [__arm_]vuninitializedq_s8(void)
1419 int8x16_t [__arm_]vuninitializedq(int8x16_t t) */
1420 struct inherent_def : public nonoverloaded_base
1421 {
1422 void
1423 build (function_builder &b, const function_group_info &group,
1424 bool preserve_user_namespace) const override
1425 {
1426 build_all (b, "t0", group, MODE_none, preserve_user_namespace);
1427 }
1428 };
1429 SHAPE (inherent)
1430
1431 /* <T0>_t vfoo[_t0](<T0>_t)
1432 <T0>_t vfoo_n_t0(<sT0>_t)
1433
1434 For MODE_n, define only the 16 and 32 bits versions.
1435
1436 Example: vmvnq.
1437 int16x8_t [__arm_]vmvnq[_s16](int16x8_t a)
1438 int16x8_t [__arm_]vmvnq_m[_s16](int16x8_t inactive, int16x8_t a, mve_pred16_t p)
1439 int16x8_t [__arm_]vmvnq_x[_s16](int16x8_t a, mve_pred16_t p)
1440 int16x8_t [__arm_]vmvnq_n_s16(const int16_t imm)
1441 int16x8_t [__arm_]vmvnq_m[_n_s16](int16x8_t inactive, const int16_t imm, mve_pred16_t p)
1442 int16x8_t [__arm_]vmvnq_x_n_s16(const int16_t imm, mve_pred16_t p) */
1443 struct mvn_def : public overloaded_base<0>
1444 {
1445 void
1446 build (function_builder &b, const function_group_info &group,
1447 bool preserve_user_namespace) const override
1448 {
1449 b.add_overloaded_functions (group, MODE_none, preserve_user_namespace);
1450 /* Do not build a separate instance for MODE_n, since we want to
1451 share vmvnq_m[_n_s16] with vmvnq_m[_s16]. */
1452 build_all (b, "v0,v0", group, MODE_none, preserve_user_namespace);
1453 build_16_32 (b, "v0,s0", group, MODE_n, preserve_user_namespace);
1454 }
1455
1456 tree
1457 resolve (function_resolver &r) const override
1458 {
1459 unsigned int i, nargs;
1460 type_suffix_index type;
1461 if (!r.check_gp_argument (1, i, nargs)
1462 /* Same type for arg 0 and 1 if _m, so using 0 is OK */
1463 || (type = r.infer_vector_type (0)) == NUM_TYPE_SUFFIXES)
1464 return error_mark_node;
1465
1466 /* Skip last argument, may be scalar. */
1467 unsigned int last_arg = i;
1468 for (i = 0; i < last_arg; i++)
1469 if (!r.require_matching_vector_type (i, type))
1470 return error_mark_node;
1471
1472 if (last_arg == 0)
1473 return r.resolve_to (r.mode_suffix_id, type);
1474
1475 return r.finish_opt_n_resolution (last_arg, 0, type);
1476 }
1477 };
1478 SHAPE (mvn)
1479
1480 /* <T0>_t vfoo[_t0](<T0>_t, <T0>_t, <T0>_t)
1481
1482 i.e. the standard shape for ternary operations that operate on
1483 uniform types.
1484
1485 Example: vqrdmlsdhxq.
1486 int8x16_t [__arm_]vqrdmlsdhxq[_s8](int8x16_t inactive, int8x16_t a, int8x16_t b)
1487 int8x16_t [__arm_]vqrdmlsdhxq_m[_s8](int8x16_t inactive, int8x16_t a, int8x16_t b, mve_pred16_t p) */
1488 struct ternary_def : public overloaded_base<0>
1489 {
1490 void
1491 build (function_builder &b, const function_group_info &group,
1492 bool preserve_user_namespace) const override
1493 {
1494 b.add_overloaded_functions (group, MODE_none, preserve_user_namespace);
1495 build_all (b, "v0,v0,v0,v0", group, MODE_none, preserve_user_namespace);
1496 }
1497
1498 tree
1499 resolve (function_resolver &r) const override
1500 {
1501 return r.resolve_uniform_opt_n (3);
1502 }
1503 };
1504 SHAPE (ternary)
1505
1506 /* <T0>_t vfoo[_t0](<T0>_t, <T0>_t, const int)
1507
1508 i.e. ternary operations that operate on a pair of vectors of the
1509 same type as the destination, and take a third integer argument.
1510
1511 Check that 'imm' is in the [0..#bits-1] range.
1512
1513 Example: vsliq.
1514 int16x8_t [__arm_]vsliq[_n_s16](int16x8_t a, int16x8_t b, const int imm)
1515 int16x8_t [__arm_]vsliq_m[_n_s16](int16x8_t a, int16x8_t b, const int imm, mve_pred16_t p) */
1516 struct ternary_lshift_def : public overloaded_base<0>
1517 {
1518 void
1519 build (function_builder &b, const function_group_info &group,
1520 bool preserve_user_namespace) const override
1521 {
1522 b.add_overloaded_functions (group, MODE_n, preserve_user_namespace);
1523 build_all (b, "v0,v0,v0,ss32", group, MODE_n, preserve_user_namespace);
1524 }
1525
1526 tree
1527 resolve (function_resolver &r) const override
1528 {
1529 return r.resolve_uniform (2, 1);
1530 }
1531
1532 bool
1533 check (function_checker &c) const override
1534 {
1535 if (c.mode_suffix_id != MODE_n)
1536 return true;
1537
1538 unsigned int bits = c.type_suffix (0).element_bits;
1539 return c.require_immediate_range (2, 0, bits - 1);
1540 }
1541 };
1542 SHAPE (ternary_lshift)
1543
1544 /* <T0>_t vfoo[_n_t0](<T0>_t, <T0>_t, <S0>_t)
1545
1546 i.e. the standard shape for ternary operations that operate on a
1547 pair of vectors of the same type as the destination, and take a
1548 third scalar argument of the same type as the vector elements.
1549
1550 Example: vmlaq.
1551 int8x16_t [__arm_]vmlaq[_n_s8](int8x16_t add, int8x16_t m1, int8_t m2)
1552 int8x16_t [__arm_]vmlaq_m[_n_s8](int8x16_t add, int8x16_t m1, int8_t m2, mve_pred16_t p) */
1553 struct ternary_n_def : public overloaded_base<0>
1554 {
1555 void
1556 build (function_builder &b, const function_group_info &group,
1557 bool preserve_user_namespace) const override
1558 {
1559 b.add_overloaded_functions (group, MODE_n, preserve_user_namespace);
1560 build_all (b, "v0,v0,v0,s0", group, MODE_n, preserve_user_namespace);
1561 }
1562
1563 tree
1564 resolve (function_resolver &r) const override
1565 {
1566 return r.resolve_uniform (2, 1);
1567 }
1568 };
1569 SHAPE (ternary_n)
1570
1571 /* <T0>_t vfoo[_t0](<T0>_t, <T0>_t, <T0>_t)
1572 <T0>_t vfoo[_n_t0](<T0>_t, <T0>_t, <S0>_t)
1573
1574 i.e. the standard shape for ternary operations that operate on
1575 uniform types.
1576
1577 Example: vfmaq.
1578 float16x8_t [__arm_]vfmaq[_n_f16](float16x8_t add, float16x8_t m1, float16_t m2)
1579 float16x8_t [__arm_]vfmaq_m[_n_f16](float16x8_t add, float16x8_t m1, float16_t m2, mve_pred16_t p)
1580 float16x8_t [__arm_]vfmaq[_f16](float16x8_t add, float16x8_t m1, float16x8_t m2)
1581 float16x8_t [__arm_]vfmaq_m[_f16](float16x8_t add, float16x8_t m1, float16x8_t m2, mve_pred16_t p) */
1582 struct ternary_opt_n_def : public overloaded_base<0>
1583 {
1584 void
1585 build (function_builder &b, const function_group_info &group,
1586 bool preserve_user_namespace) const override
1587 {
1588 b.add_overloaded_functions (group, MODE_none, preserve_user_namespace);
1589 build_all (b, "v0,v0,v0,v0", group, MODE_none, preserve_user_namespace);
1590 build_all (b, "v0,v0,v0,s0", group, MODE_n, preserve_user_namespace);
1591 }
1592
1593 tree
1594 resolve (function_resolver &r) const override
1595 {
1596 return r.resolve_uniform_opt_n (3);
1597 }
1598 };
1599 SHAPE (ternary_opt_n)
1600
1601 /* <T0>_t vfoo[_t0](<T0>_t, <T0>_t, const int)
1602
1603 i.e. ternary operations that operate on a pair of vectors of the
1604 same type as the destination, and take a third integer argument.
1605
1606 Check that 'imm' is in the [1..#bits] range.
1607
1608 Example: vsriq.
1609 int8x16_t [__arm_]vsriq[_n_s8](int8x16_t a, int8x16_t b, const int imm)
1610 int8x16_t [__arm_]vsriq_m[_n_s8](int8x16_t a, int8x16_t b, const int imm, mve_pred16_t p) */
1611 struct ternary_rshift_def : public overloaded_base<0>
1612 {
1613 void
1614 build (function_builder &b, const function_group_info &group,
1615 bool preserve_user_namespace) const override
1616 {
1617 b.add_overloaded_functions (group, MODE_n, preserve_user_namespace);
1618 build_all (b, "v0,v0,v0,ss32", group, MODE_n, preserve_user_namespace);
1619 }
1620
1621 tree
1622 resolve (function_resolver &r) const override
1623 {
1624 return r.resolve_uniform (2, 1);
1625 }
1626
1627 bool
1628 check (function_checker &c) const override
1629 {
1630 if (c.mode_suffix_id != MODE_n)
1631 return true;
1632
1633 unsigned int bits = c.type_suffix (0).element_bits;
1634 return c.require_immediate_range (2, 1, bits);
1635 }
1636 };
1637 SHAPE (ternary_rshift)
1638
1639 /* <T0>_t vfoo[_t0](<T0>_t)
1640
1641 i.e. the standard shape for unary operations that operate on
1642 uniform types.
1643
1644 Example: vabsq.
1645 int8x16_t [__arm_]vabsq[_s8](int8x16_t a)
1646 int8x16_t [__arm_]vabsq_m[_s8](int8x16_t inactive, int8x16_t a, mve_pred16_t p)
1647 int8x16_t [__arm_]vabsq_x[_s8](int8x16_t a, mve_pred16_t p) */
1648 struct unary_def : public overloaded_base<0>
1649 {
1650 void
1651 build (function_builder &b, const function_group_info &group,
1652 bool preserve_user_namespace) const override
1653 {
1654 b.add_overloaded_functions (group, MODE_none, preserve_user_namespace);
1655 build_all (b, "v0,v0", group, MODE_none, preserve_user_namespace);
1656 }
1657
1658 tree
1659 resolve (function_resolver &r) const override
1660 {
1661 return r.resolve_unary ();
1662 }
1663 };
1664 SHAPE (unary)
1665
1666 /* <S0:twice>_t vfoo[_<t0>](<T0>_t)
1667
1668 i.e. a version of "unary" in which the source elements are half the
1669 size of the destination scalar, but have the same type class.
1670
1671 Example: vaddlvq.
1672 int64_t [__arm_]vaddlvq[_s32](int32x4_t a)
1673 int64_t [__arm_]vaddlvq_p[_s32](int32x4_t a, mve_pred16_t p) */
1674 struct unary_acc_def : public overloaded_base<0>
1675 {
1676 void
1677 build (function_builder &b, const function_group_info &group,
1678 bool preserve_user_namespace) const override
1679 {
1680 b.add_overloaded_functions (group, MODE_none, preserve_user_namespace);
1681 build_all (b, "sw0,v0", group, MODE_none, preserve_user_namespace);
1682 }
1683
1684 tree
1685 resolve (function_resolver &r) const override
1686 {
1687 /* FIXME: check that the return value is actually
1688 twice as wide as arg 0. */
1689 return r.resolve_unary ();
1690 }
1691 };
1692 SHAPE (unary_acc)
1693
1694 /* <T0>_t foo_t0[_t1](<T1>_t)
1695
1696 where the target type <t0> must be specified explicitly but the source
1697 type <t1> can be inferred.
1698
1699 Example: vreinterpretq.
1700 int16x8_t [__arm_]vreinterpretq_s16[_s8](int8x16_t a)
1701 int32x4_t [__arm_]vreinterpretq_s32[_s8](int8x16_t a)
1702 int8x16_t [__arm_]vreinterpretq_s8[_s16](int16x8_t a)
1703 int8x16_t [__arm_]vreinterpretq_s8[_s32](int32x4_t a) */
1704 struct unary_convert_def : public overloaded_base<1>
1705 {
1706 void
1707 build (function_builder &b, const function_group_info &group,
1708 bool preserve_user_namespace) const override
1709 {
1710 b.add_overloaded_functions (group, MODE_none, preserve_user_namespace);
1711 build_all (b, "v0,v1", group, MODE_none, preserve_user_namespace);
1712 }
1713
1714 tree
1715 resolve (function_resolver &r) const override
1716 {
1717 return r.resolve_unary ();
1718 }
1719 };
1720 SHAPE (unary_convert)
1721
1722 /* [u]int32_t vfoo[_<t0>](<T0>_t)
1723
1724 i.e. a version of "unary" which generates a scalar of type int32_t
1725 or uint32_t depending on the signedness of the elements of of input
1726 vector.
1727
1728 Example: vaddvq
1729 int32_t [__arm_]vaddvq[_s16](int16x8_t a)
1730 int32_t [__arm_]vaddvq_p[_s16](int16x8_t a, mve_pred16_t p) */
1731 struct unary_int32_def : public overloaded_base<0>
1732 {
1733 void
1734 build (function_builder &b, const function_group_info &group,
1735 bool preserve_user_namespace) const override
1736 {
1737 b.add_overloaded_functions (group, MODE_none, preserve_user_namespace);
1738 build_all (b, "sx32,v0", group, MODE_none, preserve_user_namespace);
1739 }
1740
1741 tree
1742 resolve (function_resolver &r) const override
1743 {
1744 return r.resolve_uniform (1);
1745 }
1746 };
1747 SHAPE (unary_int32)
1748
1749 /* [u]int32_t vfoo[_<t0>]([u]int32_t, <T0>_t)
1750
1751 i.e. a version of "unary" which accumulates into scalar of type
1752 int32_t or uint32_t depending on the signedness of the elements of
1753 of input vector.
1754
1755 Example: vaddvaq.
1756 int32_t [__arm_]vaddvaq[_s16](int32_t a, int16x8_t b)
1757 int32_t [__arm_]vaddvaq_p[_s16](int32_t a, int16x8_t b, mve_pred16_t p) */
1758 struct unary_int32_acc_def : public overloaded_base<0>
1759 {
1760 void
1761 build (function_builder &b, const function_group_info &group,
1762 bool preserve_user_namespace) const override
1763 {
1764 b.add_overloaded_functions (group, MODE_none, preserve_user_namespace);
1765 build_all (b, "sx32,sx32,v0", group, MODE_none, preserve_user_namespace);
1766 }
1767
1768 tree
1769 resolve (function_resolver &r) const override
1770 {
1771 unsigned int i, nargs;
1772 type_suffix_index type;
1773 if (!r.check_gp_argument (2, i, nargs)
1774 || !r.require_integer_immediate (0)
1775 || (type = r.infer_vector_type (1)) == NUM_TYPE_SUFFIXES)
1776 return error_mark_node;
1777
1778 return r.resolve_to (r.mode_suffix_id, type);
1779 }
1780 };
1781 SHAPE (unary_int32_acc)
1782
1783 /* <T0>_t vfoo[_n]_t0(<S0>_t)
1784
1785 Example: vdupq.
1786 int16x8_t [__arm_]vdupq_n_s16(int16_t a)
1787 int16x8_t [__arm_]vdupq_m[_n_s16](int16x8_t inactive, int16_t a, mve_pred16_t p)
1788 int16x8_t [__arm_]vdupq_x_n_s16(int16_t a, mve_pred16_t p) */
1789 struct unary_n_def : public overloaded_base<0>
1790 {
1791 bool
1792 explicit_type_suffix_p (unsigned int, enum predication_index pred,
1793 enum mode_suffix_index) const override
1794 {
1795 return pred != PRED_m;
1796 }
1797
1798 bool
1799 explicit_mode_suffix_p (enum predication_index pred,
1800 enum mode_suffix_index mode) const override
1801 {
1802 return ((mode == MODE_n)
1803 && (pred != PRED_m));
1804 }
1805
1806 bool
1807 skip_overload_p (enum predication_index pred, enum mode_suffix_index mode)
1808 const override
1809 {
1810 switch (mode)
1811 {
1812 case MODE_n:
1813 return pred != PRED_m;
1814
1815 default:
1816 gcc_unreachable ();
1817 }
1818 }
1819
1820 void
1821 build (function_builder &b, const function_group_info &group,
1822 bool preserve_user_namespace) const override
1823 {
1824 b.add_overloaded_functions (group, MODE_n, preserve_user_namespace);
1825 build_all (b, "v0,s0", group, MODE_n, preserve_user_namespace);
1826 }
1827
1828 tree
1829 resolve (function_resolver &r) const override
1830 {
1831 return r.resolve_unary_n ();
1832 }
1833 };
1834 SHAPE (unary_n)
1835
1836 /* <T0:twice>_t vfoo[_t0](<T0>_t)
1837
1838 i.e. a version of "unary" in which the source elements are half the
1839 size of the destination, but have the same type class.
1840
1841 Example: vmovlbq.
1842 int32x4_t [__arm_]vmovlbq[_s16](int16x8_t a)
1843 int32x4_t [__arm_]vmovlbq_m[_s16](int32x4_t inactive, int16x8_t a, mve_pred16_t p)
1844 int32x4_t [__arm_]vmovlbq_x[_s16](int16x8_t a, mve_pred16_t p) */
1845 struct unary_widen_def : public overloaded_base<0>
1846 {
1847 void
1848 build (function_builder &b, const function_group_info &group,
1849 bool preserve_user_namespace) const override
1850 {
1851 b.add_overloaded_functions (group, MODE_none, preserve_user_namespace);
1852 build_all (b, "vw0,v0", group, MODE_none, preserve_user_namespace);
1853 }
1854
1855 tree
1856 resolve (function_resolver &r) const override
1857 {
1858 unsigned int i, nargs;
1859 type_suffix_index type;
1860 tree res;
1861 if (!r.check_gp_argument (1, i, nargs)
1862 || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES)
1863 return error_mark_node;
1864
1865 type_suffix_index wide_suffix
1866 = find_type_suffix (type_suffixes[type].tclass,
1867 type_suffixes[type].element_bits * 2);
1868
1869 /* Check the inactive argument has the wide type. */
1870 if ((r.pred == PRED_m)
1871 && (r.infer_vector_type (0) != wide_suffix))
1872 return r.report_no_such_form (type);
1873
1874 if ((res = r.lookup_form (r.mode_suffix_id, type)))
1875 return res;
1876
1877 return r.report_no_such_form (type);
1878 }
1879 };
1880 SHAPE (unary_widen)
1881
1882 /* <S0:twice>_t vfoo[_<t0>](<S0:twice>_t, <T0>_t)
1883
1884 i.e. a version of "unary" in which the source elements are half the
1885 size of the destination scalar and accumulator, but have the same
1886 type class.
1887
1888 Example: vaddlvaq.
1889 int64_t [__arm_]vaddlvaq[_s32](int64_t a, int32x4_t b)
1890 int64_t [__arm_]vaddlvaq_p[_s32](int64_t a, int32x4_t b, mve_pred16_t p) */
1891 struct unary_widen_acc_def : public overloaded_base<0>
1892 {
1893 void
1894 build (function_builder &b, const function_group_info &group,
1895 bool preserve_user_namespace) const override
1896 {
1897 b.add_overloaded_functions (group, MODE_none, preserve_user_namespace);
1898 build_all (b, "sw0,sw0,v0", group, MODE_none, preserve_user_namespace);
1899 }
1900
1901 tree
1902 resolve (function_resolver &r) const override
1903 {
1904 unsigned int i, nargs;
1905 type_suffix_index type;
1906 if (!r.check_gp_argument (2, i, nargs)
1907 || !r.require_derived_scalar_type (0, r.SAME_TYPE_CLASS)
1908 || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES)
1909 return error_mark_node;
1910
1911 return r.resolve_to (r.mode_suffix_id, type);
1912 }
1913 };
1914 SHAPE (unary_widen_acc)
1915
1916 /* <T0>_t vfoo[_t0](<T0>_t, <T0>_t, mve_pred16_t)
1917
1918 i.e. a version of the standard ternary shape in which
1919 the final argument is always a set of predicates.
1920
1921 Example: vpselq.
1922 int16x8_t [__arm_]vpselq[_s16](int16x8_t a, int16x8_t b, mve_pred16_t p) */
1923 struct vpsel_def : public overloaded_base<0>
1924 {
1925 void
1926 build (function_builder &b, const function_group_info &group,
1927 bool preserve_user_namespace) const override
1928 {
1929 b.add_overloaded_functions (group, MODE_none, preserve_user_namespace);
1930 build_all (b, "v0,v0,v0,p", group, MODE_none, preserve_user_namespace);
1931 }
1932
1933 tree
1934 resolve (function_resolver &r) const override
1935 {
1936 unsigned int i, nargs;
1937 type_suffix_index type;
1938 if (!r.check_gp_argument (3, i, nargs)
1939 || (type = r.infer_vector_type (0)) == NUM_TYPE_SUFFIXES)
1940 return error_mark_node;
1941
1942 unsigned int last_arg = i;
1943 for (i = 0; i < last_arg; i++)
1944 if (!r.require_matching_vector_type (i, type))
1945 return error_mark_node;
1946
1947 if (!r.require_vector_type (2 , VECTOR_TYPE_mve_pred16_t))
1948 return error_mark_node;
1949
1950 return r.resolve_to (r.mode_suffix_id, type);
1951 }
1952 };
1953 SHAPE (vpsel)
1954
1955 } /* end namespace arm_mve */
1956
1957 #undef SHAPE
This page took 0.151496 seconds and 5 git commands to generate.