1 /* ACLE support for Arm MVE
2 Copyright (C) 2021-2025 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
11 GCC is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
20 #ifndef GCC_ARM_MVE_BUILTINS_H
21 #define GCC_ARM_MVE_BUILTINS_H
23 /* The full name of an MVE ACLE function is the concatenation of:
25 - the base name ("vadd", etc.)
26 - the "mode" suffix ("_n", "_index", etc.)
27 - the type suffixes ("_s32", "_b8", etc.)
28 - the predication suffix ("_x", "_z", etc.)
30 Each piece of information is individually useful, so we retain this
31 classification throughout:
33 - function_base represents the base name
35 - mode_suffix_index represents the mode suffix
37 - type_suffix_index represents individual type suffixes, while
38 type_suffix_pair represents a pair of them
40 - prediction_index extends the predication suffix with an additional
41 alternative: PRED_implicit for implicitly-predicated operations
43 In addition to its unique full name, a function may have a shorter
44 overloaded alias. This alias removes pieces of the suffixes that
45 can be inferred from the arguments, such as by shortening the mode
46 suffix or dropping some of the type suffixes. The base name and the
47 predication suffix stay the same.
49 The function_shape class describes what arguments a given function
50 takes and what its overloaded alias is called. In broad terms,
51 function_base describes how the underlying instruction behaves while
52 function_shape describes how that instruction has been presented at
55 The static list of functions uses function_group to describe a group
56 of related functions. The function_builder class is responsible for
57 expanding this static description into a list of individual functions
58 and registering the associated built-in functions. function_instance
59 describes one of these individual functions in terms of the properties
62 The classes involved in compiling a function call are:
64 - function_resolver, which resolves an overloaded function call to a
65 specific function_instance and its associated function decl
67 - function_checker, which checks whether the values of the arguments
68 conform to the ACLE specification
70 - gimple_folder, which tries to fold a function call at the gimple level
72 - function_expander, which expands a function call into rtl instructions
74 function_resolver and function_checker operate at the language level
75 and so are associated with the function_shape. gimple_folder and
76 function_expander are concerned with the behavior of the function
77 and so are associated with the function_base.
79 Note that we've specifically chosen not to fold calls in the frontend,
80 since MVE intrinsics will hardly ever fold a useful language-level
83 /* The maximum number of vectors in an ACLE tuple type. */
84 const unsigned int MAX_TUPLE_SIZE
= 3;
86 /* Used to represent the default merge argument index for _m functions.
87 The actual index depends on how many arguments the function takes. */
88 const unsigned int DEFAULT_MERGE_ARGNO
= 0;
90 /* Flags that describe what a function might do, in addition to reading
91 its arguments and returning a result. */
92 const unsigned int CP_READ_FPCR
= 1U << 0;
93 const unsigned int CP_RAISE_FP_EXCEPTIONS
= 1U << 1;
94 const unsigned int CP_READ_MEMORY
= 1U << 2;
95 const unsigned int CP_WRITE_MEMORY
= 1U << 3;
97 /* Enumerates the MVE predicate and (data) vector types, together called
98 "vector types" for brevity. */
99 enum vector_type_index
101 #define DEF_MVE_TYPE(ACLE_NAME, SCALAR_TYPE) \
102 VECTOR_TYPE_ ## ACLE_NAME,
103 #include "arm-mve-builtins.def"
107 /* Classifies the available measurement units for an address displacement. */
114 /* Describes the various uses of a governing predicate. */
115 enum predication_index
117 /* No governing predicate is present. */
120 /* Merging predication: copy inactive lanes from the first data argument
121 to the vector result. */
124 /* Plain predication: inactive lanes are not used to compute the
128 /* "Don't care" predication: set inactive lanes of the vector result
129 to arbitrary values. */
132 /* Zero predication: set inactive lanes of the vector result to zero. */
138 /* Some shapes need access to some predicate sets. */
139 extern const predication_index preds_m_or_none
[];
141 /* Classifies element types, based on type suffixes with the bit count
143 enum type_class_index
153 /* Classifies an operation into "modes"; for example, to distinguish
154 vector-scalar operations from vector-vector operations, or to
155 distinguish between different addressing modes. This classification
156 accounts for the function suffixes that occur between the base name
157 and the first type suffix. */
158 enum mode_suffix_index
160 #define DEF_MVE_MODE(NAME, BASE, DISPLACEMENT, UNITS) MODE_##NAME,
161 #include "arm-mve-builtins.def"
165 /* Enumerates the possible type suffixes. Each suffix is associated with
166 a vector type, but for predicates provides extra information about the
168 enum type_suffix_index
170 #define DEF_MVE_TYPE_SUFFIX(NAME, ACLE_TYPE, CLASS, BITS, MODE) \
171 TYPE_SUFFIX_ ## NAME,
172 #include "arm-mve-builtins.def"
176 /* Combines two type suffixes. */
177 typedef enum type_suffix_index type_suffix_pair
[2];
180 class function_shape
;
182 /* Static information about a mode suffix. */
183 struct mode_suffix_info
185 /* The suffix string itself. */
188 /* The type of the vector base address, or NUM_VECTOR_TYPES if the
189 mode does not include a vector base address. */
190 vector_type_index base_vector_type
;
192 /* The type of the vector displacement, or NUM_VECTOR_TYPES if the
193 mode does not include a vector displacement. (Note that scalar
194 displacements are always int64_t.) */
195 vector_type_index displacement_vector_type
;
197 /* The units in which the vector or scalar displacement is measured,
198 or UNITS_none if the mode doesn't take a displacement. */
199 units_index displacement_units
;
202 /* Static information about a type suffix. */
203 struct type_suffix_info
205 /* The suffix string itself. */
208 /* The associated ACLE vector or predicate type. */
209 vector_type_index vector_type
: 8;
211 /* What kind of type the suffix represents. */
212 type_class_index tclass
: 8;
214 /* The number of bits and bytes in an element. For predicates this
215 measures the associated data elements. */
216 unsigned int element_bits
: 8;
217 unsigned int element_bytes
: 8;
219 /* True if the suffix is for an integer type. */
220 unsigned int integer_p
: 1;
221 /* True if the suffix is for an unsigned type. */
222 unsigned int unsigned_p
: 1;
223 /* True if the suffix is for a floating-point type. */
224 unsigned int float_p
: 1;
225 /* True if the suffix is for a polynomial type. */
226 unsigned int poly_p
: 1;
227 unsigned int spare
: 12;
229 /* The associated vector or predicate mode. */
230 machine_mode vector_mode
: 16;
233 /* Static information about a set of functions. */
234 struct function_group_info
236 /* The base name, as a string. */
237 const char *base_name
;
239 /* Describes the behavior associated with the function base name. */
240 const function_base
*const *base
;
242 /* The shape of the functions, as described above the class definition.
243 It's possible to have entries with the same base name but different
245 const function_shape
*const *shape
;
247 /* A list of the available type suffixes, and of the available predication
248 types. The function supports every combination of the two.
250 The list of type suffixes is terminated by two NUM_TYPE_SUFFIXES
251 while the list of predication types is terminated by NUM_PREDS.
252 The list of type suffixes is lexicographically ordered based
253 on the index value. */
254 const type_suffix_pair
*types
;
255 const predication_index
*preds
;
257 /* Whether the function group requires a floating point abi. */
261 /* Describes a single fully-resolved function (i.e. one that has a
262 unique full name). */
263 class GTY((user
)) function_instance
266 function_instance (const char *, const function_base
*,
267 const function_shape
*, mode_suffix_index
,
268 const type_suffix_pair
&, predication_index
);
270 bool operator== (const function_instance
&) const;
271 bool operator!= (const function_instance
&) const;
272 hashval_t
hash () const;
274 unsigned int call_properties () const;
275 bool reads_global_state_p () const;
276 bool modifies_global_state_p () const;
277 bool could_trap_p () const;
279 unsigned int vectors_per_tuple () const;
280 tree
memory_scalar_type () const;
281 machine_mode
memory_vector_mode () const;
283 const mode_suffix_info
&mode_suffix () const;
285 const type_suffix_info
&type_suffix (unsigned int) const;
286 tree
scalar_type (unsigned int) const;
287 tree
vector_type (unsigned int) const;
288 tree
tuple_type (unsigned int) const;
289 machine_mode
vector_mode (unsigned int) const;
290 machine_mode
gp_mode (unsigned int) const;
292 bool has_inactive_argument () const;
294 /* The properties of the function. (The explicit "enum"s are required
296 const char *base_name
;
297 const function_base
*base
;
298 const function_shape
*shape
;
299 enum mode_suffix_index mode_suffix_id
;
300 type_suffix_pair type_suffix_ids
;
301 enum predication_index pred
;
304 class registered_function
;
306 /* A class for building and registering function decls. */
307 class function_builder
311 ~function_builder ();
313 void add_unique_function (const function_instance
&, tree
,
314 vec
<tree
> &, bool, bool, bool);
315 void add_overloaded_function (const function_instance
&, bool, bool);
316 void add_overloaded_functions (const function_group_info
&,
317 mode_suffix_index
, bool);
319 void register_function_group (const function_group_info
&, bool);
322 void append_name (const char *);
323 char *finish_name ();
325 char *get_name (const function_instance
&, bool, bool);
327 tree
get_attributes (const function_instance
&);
329 registered_function
&add_function (const function_instance
&,
330 const char *, tree
, tree
,
333 /* The function type to use for functions that are resolved by
334 function_resolver. */
335 tree m_overload_type
;
337 /* True if we should create a separate decl for each instance of an
338 overloaded function, instead of using function_resolver. */
339 bool m_direct_overloads
;
341 /* Used for building up function names. */
342 obstack m_string_obstack
;
344 /* Maps all overloaded function names that we've registered so far
345 to their associated function_instances. */
346 hash_map
<nofree_string_hash
, registered_function
*> m_overload_names
;
349 /* A base class for handling calls to built-in functions. */
350 class function_call_info
: public function_instance
353 function_call_info (location_t
, const function_instance
&, tree
);
355 bool function_returns_void_p ();
357 /* The location of the call. */
360 /* The FUNCTION_DECL that is being called. */
364 /* A class for resolving an overloaded function call. */
365 class function_resolver
: public function_call_info
368 enum { SAME_SIZE
= 256, HALF_SIZE
, QUARTER_SIZE
};
369 static const type_class_index SAME_TYPE_CLASS
= NUM_TYPE_CLASSES
;
371 function_resolver (location_t
, const function_instance
&, tree
,
374 tree
get_vector_type (type_suffix_index
);
375 const char *get_scalar_type_name (type_suffix_index
);
376 tree
get_argument_type (unsigned int);
377 bool scalar_argument_p (unsigned int);
379 tree
report_no_such_form (type_suffix_index
);
380 tree
lookup_form (mode_suffix_index
,
381 type_suffix_index
= NUM_TYPE_SUFFIXES
,
382 type_suffix_index
= NUM_TYPE_SUFFIXES
);
383 tree
resolve_to (mode_suffix_index
,
384 type_suffix_index
= NUM_TYPE_SUFFIXES
,
385 type_suffix_index
= NUM_TYPE_SUFFIXES
);
387 type_suffix_index
infer_pointer_type (unsigned int);
388 type_suffix_index
infer_vector_or_tuple_type (unsigned int, unsigned int);
389 type_suffix_index
infer_vector_type (unsigned int);
390 type_suffix_index
infer_tuple_type (unsigned int);
392 bool require_vector_or_scalar_type (unsigned int);
394 bool require_vector_type (unsigned int, vector_type_index
);
395 bool require_matching_vector_type (unsigned int, type_suffix_index
);
396 bool require_derived_vector_type (unsigned int, unsigned int,
398 type_class_index
= SAME_TYPE_CLASS
,
399 unsigned int = SAME_SIZE
);
400 bool require_scalar_type (unsigned int, const char *);
401 bool require_pointer_type (unsigned int);
402 bool require_pointer_to_type (unsigned int, tree
);
403 bool require_integer_immediate (unsigned int);
404 bool require_derived_scalar_type (unsigned int, type_class_index
,
405 unsigned int = SAME_SIZE
);
407 bool check_num_arguments (unsigned int);
408 bool check_gp_argument (unsigned int, unsigned int &, unsigned int &);
409 tree
resolve_unary (type_class_index
= SAME_TYPE_CLASS
,
410 unsigned int = SAME_SIZE
, bool = false);
411 tree
resolve_unary_n ();
412 tree
resolve_uniform (unsigned int, unsigned int = 0);
413 tree
resolve_uniform_opt_n (unsigned int);
414 tree
finish_opt_n_resolution (unsigned int, unsigned int, type_suffix_index
,
415 type_class_index
= SAME_TYPE_CLASS
,
416 unsigned int = SAME_SIZE
,
417 type_suffix_index
= NUM_TYPE_SUFFIXES
);
422 /* The arguments to the overloaded function. */
423 vec
<tree
, va_gc
> &m_arglist
;
426 /* A class for checking that the semantic constraints on a function call are
427 satisfied, such as arguments being integer constant expressions with
428 a particular range. The parent class's FNDECL is the decl that was
429 called in the original source, before overload resolution. */
430 class function_checker
: public function_call_info
433 function_checker (location_t
, const function_instance
&, tree
,
434 tree
, unsigned int, tree
*);
436 bool require_immediate_enum (unsigned int, tree
);
437 bool require_immediate_lane_index (unsigned int, unsigned int = 1);
438 bool require_immediate_one_of (unsigned int, HOST_WIDE_INT
, HOST_WIDE_INT
,
439 HOST_WIDE_INT
, HOST_WIDE_INT
);
440 bool require_immediate_range (unsigned int, HOST_WIDE_INT
, HOST_WIDE_INT
);
441 bool require_immediate_range_multiple (unsigned int, HOST_WIDE_INT
,
442 HOST_WIDE_INT
, HOST_WIDE_INT
);
447 bool argument_exists_p (unsigned int);
449 bool require_immediate (unsigned int, HOST_WIDE_INT
&);
450 bool require_signed_immediate (unsigned int, HOST_WIDE_INT
&);
452 /* The type of the resolved function. */
455 /* The arguments to the function. */
456 unsigned int m_nargs
;
459 /* The first argument not associated with the function's predication
461 unsigned int m_base_arg
;
464 /* A class for folding a gimple function call. */
465 class gimple_folder
: public function_call_info
468 gimple_folder (const function_instance
&, tree
,
473 /* The call we're folding. */
476 /* The result of the call, or null if none. */
480 /* A class for expanding a function call into RTL. */
481 class function_expander
: public function_call_info
484 function_expander (const function_instance
&, tree
, tree
, rtx
);
487 insn_code
direct_optab_handler (optab
, unsigned int = 0);
489 rtx
get_contiguous_base ();
490 rtx
get_fallback_value (machine_mode
, unsigned int, unsigned int &);
491 rtx
get_reg_target ();
493 void add_output_operand (insn_code
);
494 void add_input_operand (insn_code
, rtx
);
495 void add_integer_operand (HOST_WIDE_INT
);
496 void add_mem_operand (machine_mode
, rtx
);
497 void add_fixed_operand (rtx
);
498 rtx
generate_insn (insn_code
);
500 rtx
use_exact_insn (insn_code
);
501 rtx
use_unpred_insn (insn_code
);
502 rtx
use_pred_x_insn (insn_code
);
503 rtx
use_cond_insn (insn_code
, unsigned int = DEFAULT_MERGE_ARGNO
);
504 rtx
use_contiguous_load_insn (insn_code
);
505 rtx
use_contiguous_store_insn (insn_code
);
507 rtx
map_to_rtx_codes (rtx_code
, rtx_code
, rtx_code
);
509 /* The function call expression. */
512 /* For functions that return a value, this is the preferred location
513 of that value. It could be null or could have a different mode
514 from the function return type. */
517 /* The expanded arguments. */
518 auto_vec
<rtx
, 16> args
;
521 /* Used to build up the operands to an instruction. */
522 auto_vec
<expand_operand
, 8> m_ops
;
525 /* Provides information about a particular function base name, and handles
526 tasks related to the base name. */
530 /* Return a set of CP_* flags that describe what the function might do,
531 in addition to reading its arguments and returning a result. */
532 virtual unsigned int call_properties (const function_instance
&) const;
534 /* If the function operates on tuples of vectors, return the number
535 of vectors in the tuples, otherwise return 1. */
536 virtual unsigned int vectors_per_tuple () const { return 1; }
538 /* If the function addresses memory, return the type of a single
539 scalar memory element. */
541 memory_scalar_type (const function_instance
&) const
546 /* If the function addresses memory, return a vector mode whose
547 GET_MODE_NUNITS is the number of elements addressed and whose
548 GET_MODE_INNER is the mode of a single scalar memory element. */
550 memory_vector_mode (const function_instance
&) const
555 /* Try to fold the given gimple call. Return the new gimple statement
556 on success, otherwise return null. */
557 virtual gimple
*fold (gimple_folder
&) const { return NULL
; }
559 /* Expand the given call into rtl. Return the result of the function,
560 or an arbitrary value if the function doesn't return a result. */
561 virtual rtx
expand (function_expander
&) const = 0;
564 /* Classifies functions into "shapes". The idea is to take all the
565 type signatures for a set of functions, and classify what's left
568 - the number of arguments
570 - the process of determining the types in the signature from the mode
571 and type suffixes in the function name (including types that are not
572 affected by the suffixes)
574 - which arguments must be integer constant expressions, and what range
577 - the process for mapping overloaded names to "full" names. */
581 virtual bool explicit_type_suffix_p (unsigned int, enum predication_index
,
582 enum mode_suffix_index
,
583 type_suffix_info
) const = 0;
584 virtual bool explicit_mode_suffix_p (enum predication_index
,
585 enum mode_suffix_index
) const = 0;
586 virtual bool skip_overload_p (enum predication_index
,
587 enum mode_suffix_index
) const = 0;
588 virtual bool mode_after_pred () const = 0;
590 /* Define all functions associated with the given group. */
591 virtual void build (function_builder
&,
592 const function_group_info
&,
595 /* Try to resolve the overloaded call. Return the non-overloaded
596 function decl on success and error_mark_node on failure. */
597 virtual tree
resolve (function_resolver
&) const = 0;
599 /* Check whether the given call is semantically valid. Return true
600 if it is, otherwise report an error and return false. */
601 virtual bool check (function_checker
&) const { return true; }
604 extern const type_suffix_info type_suffixes
[NUM_TYPE_SUFFIXES
+ 1];
605 extern const mode_suffix_info mode_suffixes
[MODE_none
+ 1];
607 extern tree scalar_types
[NUM_VECTOR_TYPES
];
608 extern tree acle_vector_types
[MAX_TUPLE_SIZE
][NUM_VECTOR_TYPES
+ 1];
610 /* Return the ACLE type mve_pred16_t. */
612 get_mve_pred16_t (void)
614 return acle_vector_types
[0][VECTOR_TYPE_mve_pred16_t
];
617 /* Try to find a mode with the given mode_suffix_info fields. Return the
618 mode on success or MODE_none on failure. */
619 inline mode_suffix_index
620 find_mode_suffix (vector_type_index base_vector_type
,
621 vector_type_index displacement_vector_type
,
622 units_index displacement_units
)
624 for (unsigned int mode_i
= 0; mode_i
< ARRAY_SIZE (mode_suffixes
); ++mode_i
)
626 const mode_suffix_info
&mode
= mode_suffixes
[mode_i
];
627 if (mode
.base_vector_type
== base_vector_type
628 && mode
.displacement_vector_type
== displacement_vector_type
629 && mode
.displacement_units
== displacement_units
)
630 return mode_suffix_index (mode_i
);
635 /* Return the type suffix associated with ELEMENT_BITS-bit elements of type
637 inline type_suffix_index
638 find_type_suffix (type_class_index tclass
, unsigned int element_bits
)
640 for (unsigned int i
= 0; i
< NUM_TYPE_SUFFIXES
; ++i
)
641 if (type_suffixes
[i
].tclass
== tclass
642 && type_suffixes
[i
].element_bits
== element_bits
)
643 return type_suffix_index (i
);
647 inline function_instance::
648 function_instance (const char *base_name_in
,
649 const function_base
*base_in
,
650 const function_shape
*shape_in
,
651 mode_suffix_index mode_suffix_id_in
,
652 const type_suffix_pair
&type_suffix_ids_in
,
653 predication_index pred_in
)
654 : base_name (base_name_in
), base (base_in
), shape (shape_in
),
655 mode_suffix_id (mode_suffix_id_in
), pred (pred_in
)
657 memcpy (type_suffix_ids
, type_suffix_ids_in
, sizeof (type_suffix_ids
));
661 function_instance::operator== (const function_instance
&other
) const
663 return (base
== other
.base
664 && shape
== other
.shape
665 && mode_suffix_id
== other
.mode_suffix_id
666 && pred
== other
.pred
667 && type_suffix_ids
[0] == other
.type_suffix_ids
[0]
668 && type_suffix_ids
[1] == other
.type_suffix_ids
[1]);
672 function_instance::operator!= (const function_instance
&other
) const
674 return !operator== (other
);
677 /* If the function operates on tuples of vectors, return the number
678 of vectors in the tuples, otherwise return 1. */
680 function_instance::vectors_per_tuple () const
682 return base
->vectors_per_tuple ();
685 /* If the function addresses memory, return the type of a single
686 scalar memory element. */
688 function_instance::memory_scalar_type () const
690 return base
->memory_scalar_type (*this);
693 /* If the function addresses memory, return a vector mode whose
694 GET_MODE_NUNITS is the number of elements addressed and whose
695 GET_MODE_INNER is the mode of a single scalar memory element. */
697 function_instance::memory_vector_mode () const
699 return base
->memory_vector_mode (*this);
702 /* Return information about the function's mode suffix. */
703 inline const mode_suffix_info
&
704 function_instance::mode_suffix () const
706 return mode_suffixes
[mode_suffix_id
];
709 /* Return information about type suffix I. */
710 inline const type_suffix_info
&
711 function_instance::type_suffix (unsigned int i
) const
713 return type_suffixes
[type_suffix_ids
[i
]];
716 /* Return the scalar type associated with type suffix I. */
718 function_instance::scalar_type (unsigned int i
) const
720 return scalar_types
[type_suffix (i
).vector_type
];
723 /* Return the vector type associated with type suffix I. */
725 function_instance::vector_type (unsigned int i
) const
727 return acle_vector_types
[0][type_suffix (i
).vector_type
];
730 /* If the function operates on tuples of vectors, return the tuple type
731 associated with type suffix I, otherwise return the vector type associated
732 with type suffix I. */
734 function_instance::tuple_type (unsigned int i
) const
736 unsigned int num_vectors
= vectors_per_tuple ();
737 return acle_vector_types
[num_vectors
>> 1][type_suffix (i
).vector_type
];
740 /* Return the vector or predicate mode associated with type suffix I. */
742 function_instance::vector_mode (unsigned int i
) const
744 return type_suffix (i
).vector_mode
;
747 /* Return true if the function has no return value. */
749 function_call_info::function_returns_void_p ()
751 return TREE_TYPE (TREE_TYPE (fndecl
)) == void_type_node
;
754 /* Default implementation of function::call_properties, with conservatively
755 correct behavior for floating-point instructions. */
757 function_base::call_properties (const function_instance
&instance
) const
759 unsigned int flags
= 0;
760 if (instance
.type_suffix (0).float_p
|| instance
.type_suffix (1).float_p
)
761 flags
|= CP_READ_FPCR
| CP_RAISE_FP_EXCEPTIONS
;
765 } /* end namespace arm_mve */
767 #endif /* GCC_ARM_MVE_BUILTINS_H */