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