145
|
1 /* ACLE support for AArch64 SVE
|
|
2 Copyright (C) 2018-2020 Free Software Foundation, Inc.
|
|
3
|
|
4 This file is part of GCC.
|
|
5
|
|
6 GCC is free software; you can redistribute it and/or modify it
|
|
7 under the terms of the GNU General Public License as published by
|
|
8 the Free Software Foundation; either version 3, or (at your option)
|
|
9 any later version.
|
|
10
|
|
11 GCC is distributed in the hope that it will be useful, but
|
|
12 WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
14 General Public License for more details.
|
|
15
|
|
16 You should have received a copy of the GNU General Public License
|
|
17 along with GCC; see the file COPYING3. If not see
|
|
18 <http://www.gnu.org/licenses/>. */
|
|
19
|
|
20 #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). */
|
|
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, uint64_t, bool);
|
|
341
|
|
342 /* The function type to use for functions that are resolved by
|
|
343 function_resolver. */
|
|
344 tree m_overload_type;
|
|
345
|
|
346 /* True if we should create a separate decl for each instance of an
|
|
347 overloaded function, instead of using function_resolver. */
|
|
348 bool m_direct_overloads;
|
|
349
|
|
350 /* Used for building up function names. */
|
|
351 obstack m_string_obstack;
|
|
352
|
|
353 /* Maps all overloaded function names that we've registered so far
|
|
354 to their associated function_instances. */
|
|
355 hash_map<nofree_string_hash, registered_function *> m_overload_names;
|
|
356 };
|
|
357
|
|
358 /* A base class for handling calls to built-in functions. */
|
|
359 class function_call_info : public function_instance
|
|
360 {
|
|
361 public:
|
|
362 function_call_info (location_t, const function_instance &, tree);
|
|
363
|
|
364 bool function_returns_void_p ();
|
|
365
|
|
366 /* The location of the call. */
|
|
367 location_t location;
|
|
368
|
|
369 /* The FUNCTION_DECL that is being called. */
|
|
370 tree fndecl;
|
|
371 };
|
|
372
|
|
373 /* A class for resolving an overloaded function call. */
|
|
374 class function_resolver : public function_call_info
|
|
375 {
|
|
376 public:
|
|
377 enum { SAME_SIZE = 256, HALF_SIZE, QUARTER_SIZE };
|
|
378 static const type_class_index SAME_TYPE_CLASS = NUM_TYPE_CLASSES;
|
|
379
|
|
380 function_resolver (location_t, const function_instance &, tree,
|
|
381 vec<tree, va_gc> &);
|
|
382
|
|
383 tree get_vector_type (type_suffix_index);
|
|
384 const char *get_scalar_type_name (type_suffix_index);
|
|
385 tree get_argument_type (unsigned int);
|
|
386 bool scalar_argument_p (unsigned int);
|
|
387
|
|
388 tree report_no_such_form (type_suffix_index);
|
|
389 tree lookup_form (mode_suffix_index,
|
|
390 type_suffix_index = NUM_TYPE_SUFFIXES,
|
|
391 type_suffix_index = NUM_TYPE_SUFFIXES);
|
|
392 tree resolve_to (mode_suffix_index,
|
|
393 type_suffix_index = NUM_TYPE_SUFFIXES,
|
|
394 type_suffix_index = NUM_TYPE_SUFFIXES);
|
|
395
|
|
396 type_suffix_index infer_integer_scalar_type (unsigned int);
|
|
397 type_suffix_index infer_pointer_type (unsigned int, bool = false);
|
|
398 type_suffix_index infer_vector_or_tuple_type (unsigned int, unsigned int);
|
|
399 type_suffix_index infer_vector_type (unsigned int);
|
|
400 type_suffix_index infer_integer_vector_type (unsigned int);
|
|
401 type_suffix_index infer_unsigned_vector_type (unsigned int);
|
|
402 type_suffix_index infer_sd_vector_type (unsigned int);
|
|
403 type_suffix_index infer_tuple_type (unsigned int);
|
|
404
|
|
405 bool require_vector_or_scalar_type (unsigned int);
|
|
406
|
|
407 bool require_vector_type (unsigned int, vector_type_index);
|
|
408 bool require_matching_vector_type (unsigned int, type_suffix_index);
|
|
409 bool require_derived_vector_type (unsigned int, unsigned int,
|
|
410 type_suffix_index,
|
|
411 type_class_index = SAME_TYPE_CLASS,
|
|
412 unsigned int = SAME_SIZE);
|
|
413
|
|
414 bool require_scalar_type (unsigned int, const char *);
|
|
415 bool require_pointer_type (unsigned int);
|
|
416 bool require_matching_integer_scalar_type (unsigned int, unsigned int,
|
|
417 type_suffix_index);
|
|
418 bool require_derived_scalar_type (unsigned int, type_class_index,
|
|
419 unsigned int = SAME_SIZE);
|
|
420 bool require_matching_pointer_type (unsigned int, unsigned int,
|
|
421 type_suffix_index);
|
|
422 bool require_integer_immediate (unsigned int);
|
|
423
|
|
424 vector_type_index infer_vector_base_type (unsigned int);
|
|
425 vector_type_index infer_vector_displacement_type (unsigned int);
|
|
426
|
|
427 mode_suffix_index resolve_sv_displacement (unsigned int,
|
|
428 type_suffix_index, bool);
|
|
429 mode_suffix_index resolve_gather_address (unsigned int,
|
|
430 type_suffix_index, bool);
|
|
431 mode_suffix_index resolve_adr_address (unsigned int);
|
|
432
|
|
433 bool check_num_arguments (unsigned int);
|
|
434 bool check_gp_argument (unsigned int, unsigned int &, unsigned int &);
|
|
435 tree resolve_unary (type_class_index = SAME_TYPE_CLASS,
|
|
436 unsigned int = SAME_SIZE, bool = false);
|
|
437 tree resolve_uniform (unsigned int, unsigned int = 0);
|
|
438 tree resolve_uniform_opt_n (unsigned int);
|
|
439 tree finish_opt_n_resolution (unsigned int, unsigned int, type_suffix_index,
|
|
440 type_class_index = SAME_TYPE_CLASS,
|
|
441 unsigned int = SAME_SIZE,
|
|
442 type_suffix_index = NUM_TYPE_SUFFIXES);
|
|
443
|
|
444 tree resolve ();
|
|
445
|
|
446 private:
|
|
447 /* The arguments to the overloaded function. */
|
|
448 vec<tree, va_gc> &m_arglist;
|
|
449 };
|
|
450
|
|
451 /* A class for checking that the semantic constraints on a function call are
|
|
452 satisfied, such as arguments being integer constant expressions with
|
|
453 a particular range. The parent class's FNDECL is the decl that was
|
|
454 called in the original source, before overload resolution. */
|
|
455 class function_checker : public function_call_info
|
|
456 {
|
|
457 public:
|
|
458 function_checker (location_t, const function_instance &, tree,
|
|
459 tree, unsigned int, tree *);
|
|
460
|
|
461 bool require_immediate_either_or (unsigned int, HOST_WIDE_INT,
|
|
462 HOST_WIDE_INT);
|
|
463 bool require_immediate_enum (unsigned int, tree);
|
|
464 bool require_immediate_lane_index (unsigned int, unsigned int = 1);
|
|
465 bool require_immediate_one_of (unsigned int, HOST_WIDE_INT, HOST_WIDE_INT,
|
|
466 HOST_WIDE_INT, HOST_WIDE_INT);
|
|
467 bool require_immediate_range (unsigned int, HOST_WIDE_INT, HOST_WIDE_INT);
|
|
468
|
|
469 bool check ();
|
|
470
|
|
471 private:
|
|
472 bool argument_exists_p (unsigned int);
|
|
473
|
|
474 bool require_immediate (unsigned int, HOST_WIDE_INT &);
|
|
475
|
|
476 /* The type of the resolved function. */
|
|
477 tree m_fntype;
|
|
478
|
|
479 /* The arguments to the function. */
|
|
480 unsigned int m_nargs;
|
|
481 tree *m_args;
|
|
482
|
|
483 /* The first argument not associated with the function's predication
|
|
484 type. */
|
|
485 unsigned int m_base_arg;
|
|
486 };
|
|
487
|
|
488 /* A class for folding a gimple function call. */
|
|
489 class gimple_folder : public function_call_info
|
|
490 {
|
|
491 public:
|
|
492 gimple_folder (const function_instance &, tree,
|
|
493 gimple_stmt_iterator *, gcall *);
|
|
494
|
|
495 tree force_vector (gimple_seq &, tree, tree);
|
|
496 tree convert_pred (gimple_seq &, tree, unsigned int);
|
|
497 tree fold_contiguous_base (gimple_seq &, tree);
|
|
498 tree load_store_cookie (tree);
|
|
499
|
|
500 gimple *redirect_call (const function_instance &);
|
|
501 gimple *fold_to_pfalse ();
|
|
502 gimple *fold_to_ptrue ();
|
|
503 gimple *fold_to_vl_pred (unsigned int);
|
|
504
|
|
505 gimple *fold ();
|
|
506
|
|
507 /* Where to insert extra statements that feed the final replacement. */
|
|
508 gimple_stmt_iterator *gsi;
|
|
509
|
|
510 /* The call we're folding. */
|
|
511 gcall *call;
|
|
512
|
|
513 /* The result of the call, or null if none. */
|
|
514 tree lhs;
|
|
515 };
|
|
516
|
|
517 /* A class for expanding a function call into RTL. */
|
|
518 class function_expander : public function_call_info
|
|
519 {
|
|
520 public:
|
|
521 function_expander (const function_instance &, tree, tree, rtx);
|
|
522 rtx expand ();
|
|
523
|
|
524 insn_code direct_optab_handler (optab, unsigned int = 0);
|
|
525 insn_code direct_optab_handler_for_sign (optab, optab, unsigned int = 0,
|
|
526 machine_mode = E_VOIDmode);
|
|
527
|
|
528 bool overlaps_input_p (rtx);
|
|
529
|
|
530 rtx convert_to_pmode (rtx);
|
|
531 rtx get_contiguous_base (machine_mode);
|
|
532 rtx get_fallback_value (machine_mode, unsigned int,
|
|
533 unsigned int, unsigned int &);
|
|
534 rtx get_reg_target ();
|
|
535 rtx get_nonoverlapping_reg_target ();
|
|
536
|
|
537 void add_output_operand (insn_code);
|
|
538 void add_input_operand (insn_code, rtx);
|
|
539 void add_integer_operand (HOST_WIDE_INT);
|
|
540 void add_mem_operand (machine_mode, rtx);
|
|
541 void add_address_operand (rtx);
|
|
542 void add_fixed_operand (rtx);
|
|
543 rtx generate_insn (insn_code);
|
|
544
|
|
545 void prepare_gather_address_operands (unsigned int, bool = true);
|
|
546 void prepare_prefetch_operands ();
|
|
547 void add_ptrue_hint (unsigned int, machine_mode);
|
|
548 void rotate_inputs_left (unsigned int, unsigned int);
|
|
549 bool try_negating_argument (unsigned int, machine_mode);
|
|
550
|
|
551 rtx use_exact_insn (insn_code);
|
|
552 rtx use_unpred_insn (insn_code);
|
|
553 rtx use_pred_x_insn (insn_code);
|
|
554 rtx use_cond_insn (insn_code, unsigned int = DEFAULT_MERGE_ARGNO);
|
|
555 rtx use_vcond_mask_insn (insn_code, unsigned int = DEFAULT_MERGE_ARGNO);
|
|
556 rtx use_contiguous_load_insn (insn_code);
|
|
557 rtx use_contiguous_prefetch_insn (insn_code);
|
|
558 rtx use_contiguous_store_insn (insn_code);
|
|
559
|
|
560 rtx map_to_rtx_codes (rtx_code, rtx_code, int,
|
|
561 unsigned int = DEFAULT_MERGE_ARGNO);
|
|
562 rtx map_to_unspecs (int, int, int, unsigned int = DEFAULT_MERGE_ARGNO);
|
|
563
|
|
564 /* The function call expression. */
|
|
565 tree call_expr;
|
|
566
|
|
567 /* For functions that return a value, this is the preferred location
|
|
568 of that value. It could be null or could have a different mode
|
|
569 from the function return type. */
|
|
570 rtx possible_target;
|
|
571
|
|
572 /* The expanded arguments. */
|
|
573 auto_vec<rtx, 16> args;
|
|
574
|
|
575 private:
|
|
576 /* Used to build up the operands to an instruction. */
|
|
577 auto_vec<expand_operand, 8> m_ops;
|
|
578 };
|
|
579
|
|
580 /* Provides information about a particular function base name, and handles
|
|
581 tasks related to the base name. */
|
|
582 class function_base
|
|
583 {
|
|
584 public:
|
|
585 /* Return a set of CP_* flags that describe what the function might do,
|
|
586 in addition to reading its arguments and returning a result. */
|
|
587 virtual unsigned int call_properties (const function_instance &) const;
|
|
588
|
|
589 /* If the function operates on tuples of vectors, return the number
|
|
590 of vectors in the tuples, otherwise return 1. */
|
|
591 virtual unsigned int vectors_per_tuple () const { return 1; }
|
|
592
|
|
593 /* If the function addresses memory, return the type of a single
|
|
594 scalar memory element. */
|
|
595 virtual tree
|
|
596 memory_scalar_type (const function_instance &) const
|
|
597 {
|
|
598 gcc_unreachable ();
|
|
599 }
|
|
600
|
|
601 /* If the function addresses memory, return a vector mode whose
|
|
602 GET_MODE_NUNITS is the number of elements addressed and whose
|
|
603 GET_MODE_INNER is the mode of a single scalar memory element. */
|
|
604 virtual machine_mode
|
|
605 memory_vector_mode (const function_instance &) const
|
|
606 {
|
|
607 gcc_unreachable ();
|
|
608 }
|
|
609
|
|
610 /* Try to fold the given gimple call. Return the new gimple statement
|
|
611 on success, otherwise return null. */
|
|
612 virtual gimple *fold (gimple_folder &) const { return NULL; }
|
|
613
|
|
614 /* Expand the given call into rtl. Return the result of the function,
|
|
615 or an arbitrary value if the function doesn't return a result. */
|
|
616 virtual rtx expand (function_expander &) const = 0;
|
|
617 };
|
|
618
|
|
619 /* Classifies functions into "shapes". The idea is to take all the
|
|
620 type signatures for a set of functions, remove the governing predicate
|
|
621 (if any), and classify what's left based on:
|
|
622
|
|
623 - the number of arguments
|
|
624
|
|
625 - the process of determining the types in the signature from the mode
|
|
626 and type suffixes in the function name (including types that are not
|
|
627 affected by the suffixes)
|
|
628
|
|
629 - which arguments must be integer constant expressions, and what range
|
|
630 those arguments have
|
|
631
|
|
632 - the process for mapping overloaded names to "full" names. */
|
|
633 class function_shape
|
|
634 {
|
|
635 public:
|
|
636 virtual bool explicit_type_suffix_p (unsigned int) const = 0;
|
|
637
|
|
638 /* Define all functions associated with the given group. */
|
|
639 virtual void build (function_builder &,
|
|
640 const function_group_info &) const = 0;
|
|
641
|
|
642 /* Try to resolve the overloaded call. Return the non-overloaded
|
|
643 function decl on success and error_mark_node on failure. */
|
|
644 virtual tree resolve (function_resolver &) const = 0;
|
|
645
|
|
646 /* Check whether the given call is semantically valid. Return true
|
|
647 if it is, otherwise report an error and return false. */
|
|
648 virtual bool check (function_checker &) const { return true; }
|
|
649 };
|
|
650
|
|
651 /* RAII class for enabling enough SVE features to define the built-in
|
|
652 types and implement the arm_sve.h pragma. */
|
|
653 class sve_switcher
|
|
654 {
|
|
655 public:
|
|
656 sve_switcher ();
|
|
657 ~sve_switcher ();
|
|
658
|
|
659 private:
|
|
660 unsigned long m_old_isa_flags;
|
|
661 bool m_old_have_regs_of_mode[MAX_MACHINE_MODE];
|
|
662 };
|
|
663
|
|
664 extern const type_suffix_info type_suffixes[NUM_TYPE_SUFFIXES + 1];
|
|
665 extern const mode_suffix_info mode_suffixes[MODE_none + 1];
|
|
666
|
|
667 extern tree scalar_types[NUM_VECTOR_TYPES];
|
|
668 extern tree acle_vector_types[MAX_TUPLE_SIZE][NUM_VECTOR_TYPES + 1];
|
|
669 extern tree acle_svpattern;
|
|
670 extern tree acle_svprfop;
|
|
671
|
|
672 /* Return the ACLE type svbool_t. */
|
|
673 inline tree
|
|
674 get_svbool_t (void)
|
|
675 {
|
|
676 return acle_vector_types[0][VECTOR_TYPE_svbool_t];
|
|
677 }
|
|
678
|
|
679 /* Try to find a mode with the given mode_suffix_info fields. Return the
|
|
680 mode on success or MODE_none on failure. */
|
|
681 inline mode_suffix_index
|
|
682 find_mode_suffix (vector_type_index base_vector_type,
|
|
683 vector_type_index displacement_vector_type,
|
|
684 units_index displacement_units)
|
|
685 {
|
|
686 for (unsigned int mode_i = 0; mode_i < ARRAY_SIZE (mode_suffixes); ++mode_i)
|
|
687 {
|
|
688 const mode_suffix_info &mode = mode_suffixes[mode_i];
|
|
689 if (mode.base_vector_type == base_vector_type
|
|
690 && mode.displacement_vector_type == displacement_vector_type
|
|
691 && mode.displacement_units == displacement_units)
|
|
692 return mode_suffix_index (mode_i);
|
|
693 }
|
|
694 return MODE_none;
|
|
695 }
|
|
696
|
|
697 /* Return the type suffix associated with ELEMENT_BITS-bit elements of type
|
|
698 class TCLASS. */
|
|
699 inline type_suffix_index
|
|
700 find_type_suffix (type_class_index tclass, unsigned int element_bits)
|
|
701 {
|
|
702 for (unsigned int i = 0; i < NUM_TYPE_SUFFIXES; ++i)
|
|
703 if (type_suffixes[i].tclass == tclass
|
|
704 && type_suffixes[i].element_bits == element_bits)
|
|
705 return type_suffix_index (i);
|
|
706 gcc_unreachable ();
|
|
707 }
|
|
708
|
|
709 /* Return the single field in tuple type TYPE. */
|
|
710 inline tree
|
|
711 tuple_type_field (tree type)
|
|
712 {
|
|
713 for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
|
|
714 if (TREE_CODE (field) == FIELD_DECL)
|
|
715 return field;
|
|
716 gcc_unreachable ();
|
|
717 }
|
|
718
|
|
719 inline function_instance::
|
|
720 function_instance (const char *base_name_in,
|
|
721 const function_base *base_in,
|
|
722 const function_shape *shape_in,
|
|
723 mode_suffix_index mode_suffix_id_in,
|
|
724 const type_suffix_pair &type_suffix_ids_in,
|
|
725 predication_index pred_in)
|
|
726 : base_name (base_name_in), base (base_in), shape (shape_in),
|
|
727 mode_suffix_id (mode_suffix_id_in), pred (pred_in)
|
|
728 {
|
|
729 memcpy (type_suffix_ids, type_suffix_ids_in, sizeof (type_suffix_ids));
|
|
730 }
|
|
731
|
|
732 inline bool
|
|
733 function_instance::operator== (const function_instance &other) const
|
|
734 {
|
|
735 return (base == other.base
|
|
736 && shape == other.shape
|
|
737 && mode_suffix_id == other.mode_suffix_id
|
|
738 && pred == other.pred
|
|
739 && type_suffix_ids[0] == other.type_suffix_ids[0]
|
|
740 && type_suffix_ids[1] == other.type_suffix_ids[1]);
|
|
741 }
|
|
742
|
|
743 inline bool
|
|
744 function_instance::operator!= (const function_instance &other) const
|
|
745 {
|
|
746 return !operator== (other);
|
|
747 }
|
|
748
|
|
749 /* If the function operates on tuples of vectors, return the number
|
|
750 of vectors in the tuples, otherwise return 1. */
|
|
751 inline unsigned int
|
|
752 function_instance::vectors_per_tuple () const
|
|
753 {
|
|
754 return base->vectors_per_tuple ();
|
|
755 }
|
|
756
|
|
757 /* If the function addresses memory, return the type of a single
|
|
758 scalar memory element. */
|
|
759 inline tree
|
|
760 function_instance::memory_scalar_type () const
|
|
761 {
|
|
762 return base->memory_scalar_type (*this);
|
|
763 }
|
|
764
|
|
765 /* If the function addresses memory, return a vector mode whose
|
|
766 GET_MODE_NUNITS is the number of elements addressed and whose
|
|
767 GET_MODE_INNER is the mode of a single scalar memory element. */
|
|
768 inline machine_mode
|
|
769 function_instance::memory_vector_mode () const
|
|
770 {
|
|
771 return base->memory_vector_mode (*this);
|
|
772 }
|
|
773
|
|
774 /* Return information about the function's mode suffix. */
|
|
775 inline const mode_suffix_info &
|
|
776 function_instance::mode_suffix () const
|
|
777 {
|
|
778 return mode_suffixes[mode_suffix_id];
|
|
779 }
|
|
780
|
|
781 /* Return the type of the function's vector base address argument,
|
|
782 or null it doesn't have a vector base address. */
|
|
783 inline tree
|
|
784 function_instance::base_vector_type () const
|
|
785 {
|
|
786 return acle_vector_types[0][mode_suffix ().base_vector_type];
|
|
787 }
|
|
788
|
|
789 /* Return the type of the function's vector index or offset argument,
|
|
790 or null if doesn't have a vector index or offset argument. */
|
|
791 inline tree
|
|
792 function_instance::displacement_vector_type () const
|
|
793 {
|
|
794 return acle_vector_types[0][mode_suffix ().displacement_vector_type];
|
|
795 }
|
|
796
|
|
797 /* If the function takes a vector or scalar displacement, return the units
|
|
798 in which the displacement is measured, otherwise return UNITS_none. */
|
|
799 inline units_index
|
|
800 function_instance::displacement_units () const
|
|
801 {
|
|
802 return mode_suffix ().displacement_units;
|
|
803 }
|
|
804
|
|
805 /* Return information about type suffix I. */
|
|
806 inline const type_suffix_info &
|
|
807 function_instance::type_suffix (unsigned int i) const
|
|
808 {
|
|
809 return type_suffixes[type_suffix_ids[i]];
|
|
810 }
|
|
811
|
|
812 /* Return the scalar type associated with type suffix I. */
|
|
813 inline tree
|
|
814 function_instance::scalar_type (unsigned int i) const
|
|
815 {
|
|
816 return scalar_types[type_suffix (i).vector_type];
|
|
817 }
|
|
818
|
|
819 /* Return the vector type associated with type suffix I. */
|
|
820 inline tree
|
|
821 function_instance::vector_type (unsigned int i) const
|
|
822 {
|
|
823 return acle_vector_types[0][type_suffix (i).vector_type];
|
|
824 }
|
|
825
|
|
826 /* If the function operates on tuples of vectors, return the tuple type
|
|
827 associated with type suffix I, otherwise return the vector type associated
|
|
828 with type suffix I. */
|
|
829 inline tree
|
|
830 function_instance::tuple_type (unsigned int i) const
|
|
831 {
|
|
832 unsigned int num_vectors = vectors_per_tuple ();
|
|
833 return acle_vector_types[num_vectors - 1][type_suffix (i).vector_type];
|
|
834 }
|
|
835
|
|
836 /* Return the number of elements of type suffix I that fit within a
|
|
837 128-bit block. */
|
|
838 inline unsigned int
|
|
839 function_instance::elements_per_vq (unsigned int i) const
|
|
840 {
|
|
841 return 128 / type_suffix (i).element_bits;
|
|
842 }
|
|
843
|
|
844 /* Return the vector or predicate mode associated with type suffix I. */
|
|
845 inline machine_mode
|
|
846 function_instance::vector_mode (unsigned int i) const
|
|
847 {
|
|
848 return type_suffix (i).vector_mode;
|
|
849 }
|
|
850
|
|
851 /* Return the mode of the governing predicate to use when operating on
|
|
852 type suffix I. */
|
|
853 inline machine_mode
|
|
854 function_instance::gp_mode (unsigned int i) const
|
|
855 {
|
|
856 return aarch64_sve_pred_mode (type_suffix (i).element_bytes).require ();
|
|
857 }
|
|
858
|
|
859 /* Return true if the function has no return value. */
|
|
860 inline bool
|
|
861 function_call_info::function_returns_void_p ()
|
|
862 {
|
|
863 return TREE_TYPE (TREE_TYPE (fndecl)) == void_type_node;
|
|
864 }
|
|
865
|
|
866 /* Default implementation of function::call_properties, with conservatively
|
|
867 correct behavior for floating-point instructions. */
|
|
868 inline unsigned int
|
|
869 function_base::call_properties (const function_instance &instance) const
|
|
870 {
|
|
871 unsigned int flags = 0;
|
|
872 if (instance.type_suffix (0).float_p || instance.type_suffix (1).float_p)
|
|
873 flags |= CP_READ_FPCR | CP_RAISE_FP_EXCEPTIONS;
|
|
874 return flags;
|
|
875 }
|
|
876
|
|
877 }
|
|
878
|
|
879 #endif
|