1 /* ACLE support for AArch64 SVE
2 Copyright (C) 2018-2021 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 #ifndef GCC_AARCH64_SVE_BUILTINS_H
21 #define GCC_AARCH64_SVE_BUILTINS_H
22
23 /* The full name of an SVE ACLE function is the concatenation of:
24
25 - the base name ("svadd", etc.)
26 - the "mode" suffix ("_n", "_index", etc.)
27 - the type suffixes ("_s32", "_b8", etc.)
28 - the predication suffix ("_x", "_z", etc.)
29
30 Each piece of information is individually useful, so we retain this
31 classification throughout:
32
33 - function_base represents the base name
34
35 - mode_suffix_index represents the mode suffix
36
37 - type_suffix_index represents individual type suffixes, while
38 type_suffix_pair represents a pair of them
39
40 - prediction_index extends the predication suffix with an additional
41 alternative: PRED_implicit for implicitly-predicated operations
42
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.
48
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
53 the language level.
54
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
60 described above.
61
62 The classes involved in compiling a function call are:
63
64 - function_resolver, which resolves an overloaded function call to a
65 specific function_instance and its associated function decl
66
67 - function_checker, which checks whether the values of the arguments
68 conform to the ACLE specification
69
70 - gimple_folder, which tries to fold a function call at the gimple level
71
72 - function_expander, which expands a function call into rtl instructions
73
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.
78
79 Note that we've specifically chosen not to fold calls in the frontend,
80 since SVE intrinsics will hardly ever fold a useful language-level
81 constant. */
82 namespace aarch64_sve
83 {
84 /* The maximum number of vectors in an ACLE tuple type. */
85 const unsigned int MAX_TUPLE_SIZE = 4;
86
87 /* Used to represent the default merge argument index for _m functions.
88 The actual index depends on how many arguments the function takes. */
89 const unsigned int DEFAULT_MERGE_ARGNO = ~0U;
90
91 /* Flags that describe what a function might do, in addition to reading
92 its arguments and returning a result. */
93 const unsigned int CP_READ_FPCR = 1U << 0;
94 const unsigned int CP_RAISE_FP_EXCEPTIONS = 1U << 1;
95 const unsigned int CP_READ_MEMORY = 1U << 2;
96 const unsigned int CP_PREFETCH_MEMORY = 1U << 3;
97 const unsigned int CP_WRITE_MEMORY = 1U << 4;
98 const unsigned int CP_READ_FFR = 1U << 5;
99 const unsigned int CP_WRITE_FFR = 1U << 6;
100
101 /* Enumerates the SVE predicate and (data) vector types, together called
102 "vector types" for brevity. */
103 enum vector_type_index
104 {
105 #define DEF_SVE_TYPE(ACLE_NAME, NCHARS, ABI_NAME, SCALAR_TYPE) \
106 VECTOR_TYPE_ ## ACLE_NAME,
107 #include "aarch64-sve-builtins.def"
108 NUM_VECTOR_TYPES
109 };
110
111 /* Classifies the available measurement units for an address displacement. */
112 enum units_index
113 {
114 UNITS_none,
115 UNITS_bytes,
116 UNITS_elements,
117 UNITS_vectors
118 };
119
120 /* Describes the various uses of a governing predicate. */
121 enum predication_index
122 {
123 /* No governing predicate is present. */
124 PRED_none,
125
126 /* A governing predicate is present but there is no predication suffix
127 associated with it. This is used when the result is neither a vector
128 nor a predicate, since the distinction between "zeroing" and "merging"
129 doesn't apply in that case. It is also used when a suffix would be
130 redundant (such as for loads and comparisons, which are inherently
131 zeroing operations). */
132 PRED_implicit,
133
134 /* Merging predication: copy inactive lanes from the first data argument
135 to the vector result. */
136 PRED_m,
137
138 /* "Don't care" predication: set inactive lanes of the vector result
139 to arbitrary values. */
140 PRED_x,
141
142 /* Zero predication: set inactive lanes of the vector result to zero. */
143 PRED_z,
144
145 NUM_PREDS
146 };
147
148 /* Classifies element types, based on type suffixes with the bit count
149 removed. */
150 enum type_class_index
151 {
152 TYPE_bool,
153 TYPE_bfloat,
154 TYPE_float,
155 TYPE_signed,
156 TYPE_unsigned,
157 NUM_TYPE_CLASSES
158 };
159
160 /* Classifies an operation into "modes"; for example, to distinguish
161 vector-scalar operations from vector-vector operations, or to
162 distinguish between different addressing modes. This classification
163 accounts for the function suffixes that occur between the base name
164 and the first type suffix. */
165 enum mode_suffix_index
166 {
167 #define DEF_SVE_MODE(NAME, BASE, DISPLACEMENT, UNITS) MODE_##NAME,
168 #include "aarch64-sve-builtins.def"
169 MODE_none
170 };
171
172 /* Enumerates the possible type suffixes. Each suffix is associated with
173 a vector type, but for predicates provides extra information about the
174 element size. */
175 enum type_suffix_index
176 {
177 #define DEF_SVE_TYPE_SUFFIX(NAME, ACLE_TYPE, CLASS, BITS, MODE) \
178 TYPE_SUFFIX_ ## NAME,
179 #include "aarch64-sve-builtins.def"
180 NUM_TYPE_SUFFIXES
181 };
182
183 /* Combines two type suffixes. */
184 typedef enum type_suffix_index type_suffix_pair[2];
185
186 class function_base;
187 class function_shape;
188
189 /* Static information about a mode suffix. */
190 struct mode_suffix_info
191 {
192 /* The suffix string itself. */
193 const char *string;
194
195 /* The type of the vector base address, or NUM_VECTOR_TYPES if the
196 mode does not include a vector base address. */
197 vector_type_index base_vector_type;
198
199 /* The type of the vector displacement, or NUM_VECTOR_TYPES if the
200 mode does not include a vector displacement. (Note that scalar
201 displacements are always int64_t.) */
202 vector_type_index displacement_vector_type;
203
204 /* The units in which the vector or scalar displacement is measured,
205 or UNITS_none if the mode doesn't take a displacement. */
206 units_index displacement_units;
207 };
208
209 /* Static information about a type suffix. */
210 struct type_suffix_info
211 {
212 /* The suffix string itself. */
213 const char *string;
214
215 /* The associated ACLE vector or predicate type. */
216 vector_type_index vector_type : 8;
217
218 /* What kind of type the suffix represents. */
219 type_class_index tclass : 8;
220
221 /* The number of bits and bytes in an element. For predicates this
222 measures the associated data elements. */
223 unsigned int element_bits : 8;
224 unsigned int element_bytes : 8;
225
226 /* True if the suffix is for an integer type. */
227 unsigned int integer_p : 1;
228 /* True if the suffix is for an unsigned type. */
229 unsigned int unsigned_p : 1;
230 /* True if the suffix is for a floating-point type. */
231 unsigned int float_p : 1;
232 /* True if the suffix is for a boolean type. */
233 unsigned int bool_p : 1;
234 unsigned int spare : 12;
235
236 /* The associated vector or predicate mode. */
237 machine_mode vector_mode : 16;
238 };
239
240 /* Static information about a set of functions. */
241 struct function_group_info
242 {
243 /* The base name, as a string. */
244 const char *base_name;
245
246 /* Describes the behavior associated with the function base name. */
247 const function_base *const *base;
248
249 /* The shape of the functions, as described above the class definition.
250 It's possible to have entries with the same base name but different
251 shapes. */
252 const function_shape *const *shape;
253
254 /* A list of the available type suffixes, and of the available predication
255 types. The function supports every combination of the two.
256
257 The list of type suffixes is terminated by two NUM_TYPE_SUFFIXES
258 while the list of predication types is terminated by NUM_PREDS.
259 The list of type suffixes is lexicographically ordered based
260 on the index value. */
261 const type_suffix_pair *types;
262 const predication_index *preds;
263
264 /* The architecture extensions that the functions require, as a set of
265 AARCH64_FL_* flags. */
266 uint64_t required_extensions;
267 };
268
269 /* Describes a single fully-resolved function (i.e. one that has a
270 unique full name). */
class(user)271 class GTY((user)) function_instance
272 {
273 public:
274 function_instance (const char *, const function_base *,
275 const function_shape *, mode_suffix_index,
276 const type_suffix_pair &, predication_index);
277
278 bool operator== (const function_instance &) const;
279 bool operator!= (const function_instance &) const;
280 hashval_t hash () const;
281
282 unsigned int call_properties () const;
283 bool reads_global_state_p () const;
284 bool modifies_global_state_p () const;
285 bool could_trap_p () const;
286
287 unsigned int vectors_per_tuple () const;
288 tree memory_scalar_type () const;
289 machine_mode memory_vector_mode () const;
290
291 const mode_suffix_info &mode_suffix () const;
292 tree base_vector_type () const;
293 tree displacement_vector_type () const;
294 units_index displacement_units () const;
295
296 const type_suffix_info &type_suffix (unsigned int) const;
297 tree scalar_type (unsigned int) const;
298 tree vector_type (unsigned int) const;
299 tree tuple_type (unsigned int) const;
300 unsigned int elements_per_vq (unsigned int i) const;
301 machine_mode vector_mode (unsigned int) const;
302 machine_mode gp_mode (unsigned int) const;
303
304 /* The properties of the function. (The explicit "enum"s are required
305 for gengtype.) */
306 const char *base_name;
307 const function_base *base;
308 const function_shape *shape;
309 enum mode_suffix_index mode_suffix_id;
310 type_suffix_pair type_suffix_ids;
311 enum predication_index pred;
312 };
313
314 class registered_function;
315
316 /* A class for building and registering function decls. */
317 class function_builder
318 {
319 public:
320 function_builder ();
321 ~function_builder ();
322
323 void add_unique_function (const function_instance &, tree,
324 vec<tree> &, uint64_t, bool);
325 void add_overloaded_function (const function_instance &, uint64_t);
326 void add_overloaded_functions (const function_group_info &,
327 mode_suffix_index);
328
329 void register_function_group (const function_group_info &);
330
331 private:
332 void append_name (const char *);
333 char *finish_name ();
334
335 char *get_name (const function_instance &, bool);
336
337 tree get_attributes (const function_instance &);
338
339 registered_function &add_function (const function_instance &,
340 const char *, tree, tree,
341 uint64_t, bool, bool);
342
343 /* The function type to use for functions that are resolved by
344 function_resolver. */
345 tree m_overload_type;
346
347 /* True if we should create a separate decl for each instance of an
348 overloaded function, instead of using function_resolver. */
349 bool m_direct_overloads;
350
351 /* Used for building up function names. */
352 obstack m_string_obstack;
353
354 /* Maps all overloaded function names that we've registered so far
355 to their associated function_instances. */
356 hash_map<nofree_string_hash, registered_function *> m_overload_names;
357 };
358
359 /* A base class for handling calls to built-in functions. */
360 class function_call_info : public function_instance
361 {
362 public:
363 function_call_info (location_t, const function_instance &, tree);
364
365 bool function_returns_void_p ();
366
367 /* The location of the call. */
368 location_t location;
369
370 /* The FUNCTION_DECL that is being called. */
371 tree fndecl;
372 };
373
374 /* A class for resolving an overloaded function call. */
375 class function_resolver : public function_call_info
376 {
377 public:
378 enum { SAME_SIZE = 256, HALF_SIZE, QUARTER_SIZE };
379 static const type_class_index SAME_TYPE_CLASS = NUM_TYPE_CLASSES;
380
381 function_resolver (location_t, const function_instance &, tree,
382 vec<tree, va_gc> &);
383
384 tree get_vector_type (type_suffix_index);
385 const char *get_scalar_type_name (type_suffix_index);
386 tree get_argument_type (unsigned int);
387 bool scalar_argument_p (unsigned int);
388
389 tree report_no_such_form (type_suffix_index);
390 tree lookup_form (mode_suffix_index,
391 type_suffix_index = NUM_TYPE_SUFFIXES,
392 type_suffix_index = NUM_TYPE_SUFFIXES);
393 tree resolve_to (mode_suffix_index,
394 type_suffix_index = NUM_TYPE_SUFFIXES,
395 type_suffix_index = NUM_TYPE_SUFFIXES);
396
397 type_suffix_index infer_integer_scalar_type (unsigned int);
398 type_suffix_index infer_pointer_type (unsigned int, bool = false);
399 type_suffix_index infer_vector_or_tuple_type (unsigned int, unsigned int);
400 type_suffix_index infer_vector_type (unsigned int);
401 type_suffix_index infer_integer_vector_type (unsigned int);
402 type_suffix_index infer_unsigned_vector_type (unsigned int);
403 type_suffix_index infer_sd_vector_type (unsigned int);
404 type_suffix_index infer_tuple_type (unsigned int);
405
406 bool require_vector_or_scalar_type (unsigned int);
407
408 bool require_vector_type (unsigned int, vector_type_index);
409 bool require_matching_vector_type (unsigned int, type_suffix_index);
410 bool require_derived_vector_type (unsigned int, unsigned int,
411 type_suffix_index,
412 type_class_index = SAME_TYPE_CLASS,
413 unsigned int = SAME_SIZE);
414
415 bool require_scalar_type (unsigned int, const char *);
416 bool require_pointer_type (unsigned int);
417 bool require_matching_integer_scalar_type (unsigned int, unsigned int,
418 type_suffix_index);
419 bool require_derived_scalar_type (unsigned int, type_class_index,
420 unsigned int = SAME_SIZE);
421 bool require_matching_pointer_type (unsigned int, unsigned int,
422 type_suffix_index);
423 bool require_integer_immediate (unsigned int);
424
425 vector_type_index infer_vector_base_type (unsigned int);
426 vector_type_index infer_vector_displacement_type (unsigned int);
427
428 mode_suffix_index resolve_sv_displacement (unsigned int,
429 type_suffix_index, bool);
430 mode_suffix_index resolve_gather_address (unsigned int,
431 type_suffix_index, bool);
432 mode_suffix_index resolve_adr_address (unsigned int);
433
434 bool check_num_arguments (unsigned int);
435 bool check_gp_argument (unsigned int, unsigned int &, unsigned int &);
436 tree resolve_unary (type_class_index = SAME_TYPE_CLASS,
437 unsigned int = SAME_SIZE, bool = false);
438 tree resolve_uniform (unsigned int, unsigned int = 0);
439 tree resolve_uniform_opt_n (unsigned int);
440 tree finish_opt_n_resolution (unsigned int, unsigned int, type_suffix_index,
441 type_class_index = SAME_TYPE_CLASS,
442 unsigned int = SAME_SIZE,
443 type_suffix_index = NUM_TYPE_SUFFIXES);
444
445 tree resolve ();
446
447 private:
448 /* The arguments to the overloaded function. */
449 vec<tree, va_gc> &m_arglist;
450 };
451
452 /* A class for checking that the semantic constraints on a function call are
453 satisfied, such as arguments being integer constant expressions with
454 a particular range. The parent class's FNDECL is the decl that was
455 called in the original source, before overload resolution. */
456 class function_checker : public function_call_info
457 {
458 public:
459 function_checker (location_t, const function_instance &, tree,
460 tree, unsigned int, tree *);
461
462 bool require_immediate_either_or (unsigned int, HOST_WIDE_INT,
463 HOST_WIDE_INT);
464 bool require_immediate_enum (unsigned int, tree);
465 bool require_immediate_lane_index (unsigned int, unsigned int = 1);
466 bool require_immediate_one_of (unsigned int, HOST_WIDE_INT, HOST_WIDE_INT,
467 HOST_WIDE_INT, HOST_WIDE_INT);
468 bool require_immediate_range (unsigned int, HOST_WIDE_INT, HOST_WIDE_INT);
469
470 bool check ();
471
472 private:
473 bool argument_exists_p (unsigned int);
474
475 bool require_immediate (unsigned int, HOST_WIDE_INT &);
476
477 /* The type of the resolved function. */
478 tree m_fntype;
479
480 /* The arguments to the function. */
481 unsigned int m_nargs;
482 tree *m_args;
483
484 /* The first argument not associated with the function's predication
485 type. */
486 unsigned int m_base_arg;
487 };
488
489 /* A class for folding a gimple function call. */
490 class gimple_folder : public function_call_info
491 {
492 public:
493 gimple_folder (const function_instance &, tree,
494 gimple_stmt_iterator *, gcall *);
495
496 tree force_vector (gimple_seq &, tree, tree);
497 tree convert_pred (gimple_seq &, tree, unsigned int);
498 tree fold_contiguous_base (gimple_seq &, tree);
499 tree load_store_cookie (tree);
500
501 gimple *redirect_call (const function_instance &);
502 gimple *fold_to_pfalse ();
503 gimple *fold_to_ptrue ();
504 gimple *fold_to_vl_pred (unsigned int);
505
506 gimple *fold ();
507
508 /* Where to insert extra statements that feed the final replacement. */
509 gimple_stmt_iterator *gsi;
510
511 /* The call we're folding. */
512 gcall *call;
513
514 /* The result of the call, or null if none. */
515 tree lhs;
516 };
517
518 /* A class for expanding a function call into RTL. */
519 class function_expander : public function_call_info
520 {
521 public:
522 function_expander (const function_instance &, tree, tree, rtx);
523 rtx expand ();
524
525 insn_code direct_optab_handler (optab, unsigned int = 0);
526 insn_code direct_optab_handler_for_sign (optab, optab, unsigned int = 0,
527 machine_mode = E_VOIDmode);
528
529 bool overlaps_input_p (rtx);
530
531 rtx convert_to_pmode (rtx);
532 rtx get_contiguous_base (machine_mode);
533 rtx get_fallback_value (machine_mode, unsigned int,
534 unsigned int, unsigned int &);
535 rtx get_reg_target ();
536 rtx get_nonoverlapping_reg_target ();
537
538 void add_output_operand (insn_code);
539 void add_input_operand (insn_code, rtx);
540 void add_integer_operand (HOST_WIDE_INT);
541 void add_mem_operand (machine_mode, rtx);
542 void add_address_operand (rtx);
543 void add_fixed_operand (rtx);
544 rtx generate_insn (insn_code);
545
546 void prepare_gather_address_operands (unsigned int, bool = true);
547 void prepare_prefetch_operands ();
548 void add_ptrue_hint (unsigned int, machine_mode);
549 void rotate_inputs_left (unsigned int, unsigned int);
550 bool try_negating_argument (unsigned int, machine_mode);
551
552 rtx use_exact_insn (insn_code);
553 rtx use_unpred_insn (insn_code);
554 rtx use_pred_x_insn (insn_code);
555 rtx use_cond_insn (insn_code, unsigned int = DEFAULT_MERGE_ARGNO);
556 rtx use_vcond_mask_insn (insn_code, unsigned int = DEFAULT_MERGE_ARGNO);
557 rtx use_contiguous_load_insn (insn_code);
558 rtx use_contiguous_prefetch_insn (insn_code);
559 rtx use_contiguous_store_insn (insn_code);
560
561 rtx map_to_rtx_codes (rtx_code, rtx_code, int,
562 unsigned int = DEFAULT_MERGE_ARGNO);
563 rtx map_to_unspecs (int, int, int, unsigned int = DEFAULT_MERGE_ARGNO);
564
565 /* The function call expression. */
566 tree call_expr;
567
568 /* For functions that return a value, this is the preferred location
569 of that value. It could be null or could have a different mode
570 from the function return type. */
571 rtx possible_target;
572
573 /* The expanded arguments. */
574 auto_vec<rtx, 16> args;
575
576 private:
577 /* Used to build up the operands to an instruction. */
578 auto_vec<expand_operand, 8> m_ops;
579 };
580
581 /* Provides information about a particular function base name, and handles
582 tasks related to the base name. */
583 class function_base
584 {
585 public:
586 /* Return a set of CP_* flags that describe what the function might do,
587 in addition to reading its arguments and returning a result. */
588 virtual unsigned int call_properties (const function_instance &) const;
589
590 /* If the function operates on tuples of vectors, return the number
591 of vectors in the tuples, otherwise return 1. */
vectors_per_tuple()592 virtual unsigned int vectors_per_tuple () const { return 1; }
593
594 /* If the function addresses memory, return the type of a single
595 scalar memory element. */
596 virtual tree
memory_scalar_type(const function_instance &)597 memory_scalar_type (const function_instance &) const
598 {
599 gcc_unreachable ();
600 }
601
602 /* If the function addresses memory, return a vector mode whose
603 GET_MODE_NUNITS is the number of elements addressed and whose
604 GET_MODE_INNER is the mode of a single scalar memory element. */
605 virtual machine_mode
memory_vector_mode(const function_instance &)606 memory_vector_mode (const function_instance &) const
607 {
608 gcc_unreachable ();
609 }
610
611 /* Try to fold the given gimple call. Return the new gimple statement
612 on success, otherwise return null. */
fold(gimple_folder &)613 virtual gimple *fold (gimple_folder &) const { return NULL; }
614
615 /* Expand the given call into rtl. Return the result of the function,
616 or an arbitrary value if the function doesn't return a result. */
617 virtual rtx expand (function_expander &) const = 0;
618 };
619
620 /* Classifies functions into "shapes". The idea is to take all the
621 type signatures for a set of functions, remove the governing predicate
622 (if any), and classify what's left based on:
623
624 - the number of arguments
625
626 - the process of determining the types in the signature from the mode
627 and type suffixes in the function name (including types that are not
628 affected by the suffixes)
629
630 - which arguments must be integer constant expressions, and what range
631 those arguments have
632
633 - the process for mapping overloaded names to "full" names. */
634 class function_shape
635 {
636 public:
637 virtual bool explicit_type_suffix_p (unsigned int) const = 0;
638
639 /* Define all functions associated with the given group. */
640 virtual void build (function_builder &,
641 const function_group_info &) const = 0;
642
643 /* Try to resolve the overloaded call. Return the non-overloaded
644 function decl on success and error_mark_node on failure. */
645 virtual tree resolve (function_resolver &) const = 0;
646
647 /* Check whether the given call is semantically valid. Return true
648 if it is, otherwise report an error and return false. */
check(function_checker &)649 virtual bool check (function_checker &) const { return true; }
650 };
651
652 /* RAII class for enabling enough SVE features to define the built-in
653 types and implement the arm_sve.h pragma. */
654 class sve_switcher
655 {
656 public:
657 sve_switcher ();
658 ~sve_switcher ();
659
660 private:
661 unsigned long m_old_isa_flags;
662 unsigned int m_old_maximum_field_alignment;
663 bool m_old_general_regs_only;
664 bool m_old_have_regs_of_mode[MAX_MACHINE_MODE];
665 };
666
667 extern const type_suffix_info type_suffixes[NUM_TYPE_SUFFIXES + 1];
668 extern const mode_suffix_info mode_suffixes[MODE_none + 1];
669
670 extern tree scalar_types[NUM_VECTOR_TYPES];
671 extern tree acle_vector_types[MAX_TUPLE_SIZE][NUM_VECTOR_TYPES + 1];
672 extern tree acle_svpattern;
673 extern tree acle_svprfop;
674
675 /* Return the ACLE type svbool_t. */
676 inline tree
get_svbool_t(void)677 get_svbool_t (void)
678 {
679 return acle_vector_types[0][VECTOR_TYPE_svbool_t];
680 }
681
682 /* Try to find a mode with the given mode_suffix_info fields. Return the
683 mode on success or MODE_none on failure. */
684 inline mode_suffix_index
find_mode_suffix(vector_type_index base_vector_type,vector_type_index displacement_vector_type,units_index displacement_units)685 find_mode_suffix (vector_type_index base_vector_type,
686 vector_type_index displacement_vector_type,
687 units_index displacement_units)
688 {
689 for (unsigned int mode_i = 0; mode_i < ARRAY_SIZE (mode_suffixes); ++mode_i)
690 {
691 const mode_suffix_info &mode = mode_suffixes[mode_i];
692 if (mode.base_vector_type == base_vector_type
693 && mode.displacement_vector_type == displacement_vector_type
694 && mode.displacement_units == displacement_units)
695 return mode_suffix_index (mode_i);
696 }
697 return MODE_none;
698 }
699
700 /* Return the type suffix associated with ELEMENT_BITS-bit elements of type
701 class TCLASS. */
702 inline type_suffix_index
find_type_suffix(type_class_index tclass,unsigned int element_bits)703 find_type_suffix (type_class_index tclass, unsigned int element_bits)
704 {
705 for (unsigned int i = 0; i < NUM_TYPE_SUFFIXES; ++i)
706 if (type_suffixes[i].tclass == tclass
707 && type_suffixes[i].element_bits == element_bits)
708 return type_suffix_index (i);
709 gcc_unreachable ();
710 }
711
712 /* Return the single field in tuple type TYPE. */
713 inline tree
tuple_type_field(tree type)714 tuple_type_field (tree type)
715 {
716 for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
717 if (TREE_CODE (field) == FIELD_DECL)
718 return field;
719 gcc_unreachable ();
720 }
721
722 inline function_instance::
function_instance(const char * base_name_in,const function_base * base_in,const function_shape * shape_in,mode_suffix_index mode_suffix_id_in,const type_suffix_pair & type_suffix_ids_in,predication_index pred_in)723 function_instance (const char *base_name_in,
724 const function_base *base_in,
725 const function_shape *shape_in,
726 mode_suffix_index mode_suffix_id_in,
727 const type_suffix_pair &type_suffix_ids_in,
728 predication_index pred_in)
729 : base_name (base_name_in), base (base_in), shape (shape_in),
730 mode_suffix_id (mode_suffix_id_in), pred (pred_in)
731 {
732 memcpy (type_suffix_ids, type_suffix_ids_in, sizeof (type_suffix_ids));
733 }
734
735 inline bool
736 function_instance::operator== (const function_instance &other) const
737 {
738 return (base == other.base
739 && shape == other.shape
740 && mode_suffix_id == other.mode_suffix_id
741 && pred == other.pred
742 && type_suffix_ids[0] == other.type_suffix_ids[0]
743 && type_suffix_ids[1] == other.type_suffix_ids[1]);
744 }
745
746 inline bool
747 function_instance::operator!= (const function_instance &other) const
748 {
749 return !operator== (other);
750 }
751
752 /* If the function operates on tuples of vectors, return the number
753 of vectors in the tuples, otherwise return 1. */
754 inline unsigned int
vectors_per_tuple()755 function_instance::vectors_per_tuple () const
756 {
757 return base->vectors_per_tuple ();
758 }
759
760 /* If the function addresses memory, return the type of a single
761 scalar memory element. */
762 inline tree
memory_scalar_type()763 function_instance::memory_scalar_type () const
764 {
765 return base->memory_scalar_type (*this);
766 }
767
768 /* If the function addresses memory, return a vector mode whose
769 GET_MODE_NUNITS is the number of elements addressed and whose
770 GET_MODE_INNER is the mode of a single scalar memory element. */
771 inline machine_mode
memory_vector_mode()772 function_instance::memory_vector_mode () const
773 {
774 return base->memory_vector_mode (*this);
775 }
776
777 /* Return information about the function's mode suffix. */
778 inline const mode_suffix_info &
mode_suffix()779 function_instance::mode_suffix () const
780 {
781 return mode_suffixes[mode_suffix_id];
782 }
783
784 /* Return the type of the function's vector base address argument,
785 or null it doesn't have a vector base address. */
786 inline tree
base_vector_type()787 function_instance::base_vector_type () const
788 {
789 return acle_vector_types[0][mode_suffix ().base_vector_type];
790 }
791
792 /* Return the type of the function's vector index or offset argument,
793 or null if doesn't have a vector index or offset argument. */
794 inline tree
displacement_vector_type()795 function_instance::displacement_vector_type () const
796 {
797 return acle_vector_types[0][mode_suffix ().displacement_vector_type];
798 }
799
800 /* If the function takes a vector or scalar displacement, return the units
801 in which the displacement is measured, otherwise return UNITS_none. */
802 inline units_index
displacement_units()803 function_instance::displacement_units () const
804 {
805 return mode_suffix ().displacement_units;
806 }
807
808 /* Return information about type suffix I. */
809 inline const type_suffix_info &
type_suffix(unsigned int i)810 function_instance::type_suffix (unsigned int i) const
811 {
812 return type_suffixes[type_suffix_ids[i]];
813 }
814
815 /* Return the scalar type associated with type suffix I. */
816 inline tree
scalar_type(unsigned int i)817 function_instance::scalar_type (unsigned int i) const
818 {
819 return scalar_types[type_suffix (i).vector_type];
820 }
821
822 /* Return the vector type associated with type suffix I. */
823 inline tree
vector_type(unsigned int i)824 function_instance::vector_type (unsigned int i) const
825 {
826 return acle_vector_types[0][type_suffix (i).vector_type];
827 }
828
829 /* If the function operates on tuples of vectors, return the tuple type
830 associated with type suffix I, otherwise return the vector type associated
831 with type suffix I. */
832 inline tree
tuple_type(unsigned int i)833 function_instance::tuple_type (unsigned int i) const
834 {
835 unsigned int num_vectors = vectors_per_tuple ();
836 return acle_vector_types[num_vectors - 1][type_suffix (i).vector_type];
837 }
838
839 /* Return the number of elements of type suffix I that fit within a
840 128-bit block. */
841 inline unsigned int
elements_per_vq(unsigned int i)842 function_instance::elements_per_vq (unsigned int i) const
843 {
844 return 128 / type_suffix (i).element_bits;
845 }
846
847 /* Return the vector or predicate mode associated with type suffix I. */
848 inline machine_mode
vector_mode(unsigned int i)849 function_instance::vector_mode (unsigned int i) const
850 {
851 return type_suffix (i).vector_mode;
852 }
853
854 /* Return the mode of the governing predicate to use when operating on
855 type suffix I. */
856 inline machine_mode
gp_mode(unsigned int i)857 function_instance::gp_mode (unsigned int i) const
858 {
859 return aarch64_sve_pred_mode (type_suffix (i).element_bytes).require ();
860 }
861
862 /* Return true if the function has no return value. */
863 inline bool
function_returns_void_p()864 function_call_info::function_returns_void_p ()
865 {
866 return TREE_TYPE (TREE_TYPE (fndecl)) == void_type_node;
867 }
868
869 /* Default implementation of function::call_properties, with conservatively
870 correct behavior for floating-point instructions. */
871 inline unsigned int
call_properties(const function_instance & instance)872 function_base::call_properties (const function_instance &instance) const
873 {
874 unsigned int flags = 0;
875 if (instance.type_suffix (0).float_p || instance.type_suffix (1).float_p)
876 flags |= CP_READ_FPCR | CP_RAISE_FP_EXCEPTIONS;
877 return flags;
878 }
879
880 }
881
882 #endif
883