]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/riscv/riscv-vector-builtins.h
Update copyright years.
[thirdparty/gcc.git] / gcc / config / riscv / riscv-vector-builtins.h
1 /* Builtins definitions for RISC-V 'V' Extension for GNU compiler.
2 Copyright (C) 2022-2023 Free Software Foundation, Inc.
3 Contributed by Ju-Zhe Zhong (juzhe.zhong@rivai.ai), RiVAI Technologies Ltd.
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
11
12 GCC is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
20
21 #ifndef GCC_RISCV_VECTOR_BUILTINS_H
22 #define GCC_RISCV_VECTOR_BUILTINS_H
23
24 /* The full name of an RVV intrinsic function is the concatenation of:
25
26 - the base name ("vadd", etc.)
27 - the operand suffix ("_vv", "_vx", etc.)
28 - the type suffix ("_i32m1", "_i32mf2", etc.)
29 - the predication suffix ("_tamu", "_tumu", etc.)
30
31 Each piece of information is individually useful, so we retain this
32 classification throughout:
33
34 - function_base represents the base name.
35
36 - operand_type_index can be used as an index to get operand suffix.
37
38 - rvv_op_info can be used as an index to get argument suffix.
39
40 - predication_type_index can be used as an index to get predication suffix.
41
42 In addition to its unique full name, a function may have a shorter
43 overloaded alias. This alias removes pieces of the suffixes that
44 can be inferred from the arguments, such as by shortening the mode
45 suffix or dropping some of the type suffixes. The base name and the
46 predication suffix stay the same.
47
48 - The function_instance class describes contains all properties of each
49 individual function. Such these information will be used by
50 function_builder, function_base, function_shape, gimple_folder,
51 function_expander, etc.
52
53 - The function_builder class provides several helper function to add an
54 intrinsic function.
55
56 - The function_shape class describes how that instruction has been presented
57 at the language level:
58
59 1. Determine the function name for C and C++ overload function which can
60 be recognized by compiler at language level for each instruction
61 according to members of function_instance (base name, operand suffix,
62 type suffix, predication suffix, etc.).
63
64 2. Specify the arguments type and return type of each function to
65 describe how that instruction has presented at language level.
66
67 - The function_base describes how the underlying instruction behaves.
68
69 The static list of functions uses function_group to describe a group
70 of related functions. The function_builder class is responsible for
71 expanding this static description into a list of individual functions
72 and registering the associated built-in functions. function_instance
73 describes one of these individual functions in terms of the properties
74 described above.
75
76 The classes involved in compiling a function call are:
77
78 - function_resolver, which resolves an overloaded function call to a
79 specific function_instance and its associated function decl.
80
81 - function_checker, which checks whether the values of the arguments
82 conform to the RVV ISA specification.
83
84 - gimple_folder, which tries to fold a function call at the gimple level
85
86 - function_expander, which expands a function call into rtl instructions
87
88 function_resolver and function_checker operate at the language level
89 and so are associated with the function_shape. gimple_folder and
90 function_expander are concerned with the behavior of the function
91 and so are associated with the function_base. */
92
93 namespace riscv_vector {
94
95 /* Flags that describe what a function might do, in addition to reading
96 its arguments and returning a result. */
97 static const unsigned int CP_READ_FPCR = 1U << 0;
98 static const unsigned int CP_RAISE_FP_EXCEPTIONS = 1U << 1;
99 static const unsigned int CP_READ_MEMORY = 1U << 2;
100 static const unsigned int CP_WRITE_MEMORY = 1U << 3;
101 static const unsigned int CP_READ_CSR = 1U << 4;
102 static const unsigned int CP_WRITE_CSR = 1U << 5;
103
104 /* Bit values used to identify required extensions for RVV intrinsics. */
105 #define RVV_REQUIRE_RV64BIT (1 << 0) /* Require RV64. */
106 #define RVV_REQUIRE_ZVE64 (1 << 1) /* Require TARGET_MIN_VLEN > 32. */
107 #define RVV_REQUIRE_ELEN_FP_32 (1 << 2) /* Require FP ELEN >= 32. */
108 #define RVV_REQUIRE_ELEN_FP_64 (1 << 3) /* Require FP ELEN >= 64. */
109
110 /* Enumerates the RVV operand types. */
111 enum operand_type_index
112 {
113 OP_TYPE_none,
114 #define DEF_RVV_OP_TYPE(NAME) OP_TYPE_##NAME,
115 #include "riscv-vector-builtins.def"
116 NUM_OP_TYPES
117 };
118
119 /* Enumerates the RVV types, together called
120 "vector types" for brevity. */
121 enum vector_type_index
122 {
123 #define DEF_RVV_TYPE(NAME, ABI_NAME, NCHARS, ARGS...) VECTOR_TYPE_##NAME,
124 #include "riscv-vector-builtins.def"
125 NUM_VECTOR_TYPES
126 };
127
128 /* Enumerates the RVV governing predication types. */
129 enum predication_type_index
130 {
131 PRED_TYPE_none,
132 #define DEF_RVV_PRED_TYPE(NAME) PRED_TYPE_##NAME,
133 #include "riscv-vector-builtins.def"
134 NUM_PRED_TYPES
135 };
136
137 /* Enumerates the RVV base types. */
138 enum rvv_base_type
139 {
140 RVV_BASE_vector,
141 RVV_BASE_scalar,
142 RVV_BASE_vector_ptr,
143 RVV_BASE_scalar_ptr,
144 RVV_BASE_scalar_const_ptr,
145 RVV_BASE_void,
146 RVV_BASE_size,
147 RVV_BASE_ptrdiff,
148 RVV_BASE_unsigned_long,
149 RVV_BASE_long,
150 NUM_BASE_TYPES
151 };
152
153 /* Builtin types that are used to register RVV intrinsics. */
154 struct GTY (()) rvv_builtin_types_t
155 {
156 tree vector;
157 tree scalar;
158 tree vector_ptr;
159 tree scalar_ptr;
160 tree scalar_const_ptr;
161 };
162
163 /* Builtin suffix that are used to register RVV intrinsics. */
164 struct rvv_builtin_suffixes
165 {
166 const char *vector;
167 const char *scalar;
168 const char *vsetvl;
169 };
170
171 /* RVV Builtin argument information. */
172 struct rvv_arg_type_info
173 {
174 CONSTEXPR rvv_arg_type_info (rvv_base_type base_type_in)
175 : base_type (base_type_in)
176 {}
177 enum rvv_base_type base_type;
178
179 tree get_tree_type (vector_type_index) const;
180 };
181
182 /* Static information for each operand. */
183 struct rvv_type_info
184 {
185 enum vector_type_index index;
186 uint64_t required_extensions;
187 };
188
189 /* RVV Builtin operands information. */
190 struct rvv_op_info
191 {
192 const rvv_type_info *types;
193 const operand_type_index op;
194 rvv_arg_type_info ret;
195 const rvv_arg_type_info *args;
196 };
197
198 class registered_function;
199 class function_base;
200 class function_shape;
201
202 /* Static information about a set of functions. */
203 struct function_group_info
204 {
205 /* The base name, as a string. */
206 const char *base_name;
207
208 /* Describes the behavior associated with the function base name. */
209 const function_base *const *base;
210
211 /* The shape of the functions, as described above the class definition.
212 It's possible to have entries with the same base name but different
213 shapes. */
214 const function_shape *const *shape;
215
216 /* A list of the available operand types, predication types,
217 and of the available operand datatype.
218 The function supports every combination of the two.
219 The list of predication is terminated by two NUM_PRED_TYPES,
220 while the list of operand info is terminated by NUM_BASE_TYPES.
221 The list of these type suffix is lexicographically ordered based
222 on the index value. */
223 const predication_type_index *preds;
224 const rvv_op_info ops_infos;
225 };
226
227 class GTY ((user)) function_instance
228 {
229 public:
230 function_instance (const char *, const function_base *,
231 const function_shape *, rvv_type_info,
232 predication_type_index, const rvv_op_info *);
233
234 bool operator== (const function_instance &) const;
235 bool operator!= (const function_instance &) const;
236 hashval_t hash () const;
237
238 unsigned int call_properties () const;
239 bool reads_global_state_p () const;
240 bool modifies_global_state_p () const;
241 bool could_trap_p () const;
242
243 /* Return true if return type or arguments are floating point type. */
244 bool any_type_float_p () const;
245
246 tree get_return_type () const;
247 tree get_arg_type (unsigned opno) const;
248
249 /* The properties of the function. (The explicit "enum"s are required
250 for gengtype.) */
251 const char *base_name;
252 const function_base *base;
253 const function_shape *shape;
254 rvv_type_info type;
255 enum predication_type_index pred;
256 const rvv_op_info *op_info;
257 };
258
259 /* A class for building and registering function decls. */
260 class function_builder
261 {
262 public:
263 function_builder ();
264 ~function_builder ();
265
266 void allocate_argument_types (const function_instance &, vec<tree> &) const;
267 void apply_predication (const function_instance &, tree, vec<tree> &) const;
268 void add_unique_function (const function_instance &, const function_shape *,
269 tree, vec<tree> &);
270 void register_function_group (const function_group_info &);
271 void append_name (const char *);
272 void append_base_name (const char *);
273 void append_sew (int);
274 char *finish_name ();
275
276 private:
277 tree get_attributes (const function_instance &);
278
279 registered_function &add_function (const function_instance &, const char *,
280 tree, tree, bool);
281
282 /* True if we should create a separate decl for each instance of an
283 overloaded function, instead of using function_builder. */
284 bool m_direct_overloads;
285
286 /* Used for building up function names. */
287 obstack m_string_obstack;
288 };
289
290 /* A base class for handling calls to built-in functions. */
291 class function_call_info : public function_instance
292 {
293 public:
294 function_call_info (location_t, const function_instance &, tree);
295
296 bool function_returns_void_p ();
297
298 /* The location of the call. */
299 location_t location;
300
301 /* The FUNCTION_DECL that is being called. */
302 tree fndecl;
303 };
304
305 /* Return true if the function has no return value. */
306 inline bool
307 function_call_info::function_returns_void_p ()
308 {
309 return TREE_TYPE (TREE_TYPE (fndecl)) == void_type_node;
310 }
311
312 /* A class for expanding a function call into RTL. */
313 class function_expander : public function_call_info
314 {
315 public:
316 function_expander (const function_instance &, tree, tree, rtx);
317 rtx expand ();
318
319 void add_input_operand (machine_mode, rtx);
320 void add_input_operand (unsigned argno);
321 void add_output_operand (machine_mode, rtx);
322 void add_all_one_mask_operand (machine_mode mode);
323 void add_vundef_operand (machine_mode mode);
324 void add_fixed_operand (rtx);
325 rtx add_mem_operand (machine_mode, rtx);
326
327 machine_mode vector_mode (void) const;
328
329 rtx use_contiguous_load_insn (insn_code);
330 rtx use_contiguous_store_insn (insn_code);
331 rtx generate_insn (insn_code);
332
333 /* The function call expression. */
334 tree exp;
335
336 /* For functions that return a value, this is the preferred location
337 of that value. It could be null or could have a different mode
338 from the function return type. */
339 rtx target;
340
341 /* The number of the operands. */
342 int opno;
343
344 private:
345 /* Used to build up the operands to an instruction. */
346 struct expand_operand m_ops[MAX_RECOG_OPERANDS];
347 };
348
349 /* Provides information about a particular function base name, and handles
350 tasks related to the base name. */
351 class function_base
352 {
353 public:
354 /* Return a set of CP_* flags that describe what the function might do,
355 in addition to reading its arguments and returning a result. */
356 virtual unsigned int call_properties (const function_instance &) const;
357
358 /* Return true if intrinsics should apply vl operand. */
359 virtual bool apply_vl_p () const;
360
361 /* Return true if intrinsic can be overloaded. */
362 virtual bool can_be_overloaded_p (enum predication_type_index) const;
363
364 /* Expand the given call into rtl. Return the result of the function,
365 or an arbitrary value if the function doesn't return a result. */
366 virtual rtx expand (function_expander &) const = 0;
367 };
368
369 /* Classifies functions into "shapes" base on:
370
371 - Base name of the intrinsic function.
372
373 - Operand types list.
374
375 - Argument type list.
376
377 - Predication type list. */
378 class function_shape
379 {
380 public:
381 /* Shape the function name according to function_instance. */
382 virtual char *get_name (function_builder &, const function_instance &,
383 bool) const
384 = 0;
385
386 /* Define all functions associated with the given group. */
387 virtual void build (function_builder &, const function_group_info &) const
388 = 0;
389 };
390
391 extern const char *const operand_suffixes[NUM_OP_TYPES];
392 extern const rvv_builtin_suffixes type_suffixes[NUM_VECTOR_TYPES + 1];
393 extern const char *const predication_suffixes[NUM_PRED_TYPES];
394 extern rvv_builtin_types_t builtin_types[NUM_VECTOR_TYPES + 1];
395
396 inline bool
397 function_instance::operator!= (const function_instance &other) const
398 {
399 return !operator== (other);
400 }
401
402 /* Expand the call and return its lhs. */
403 inline rtx
404 function_expander::expand ()
405 {
406 return base->expand (*this);
407 }
408
409 /* Create op and add it into M_OPS and increase OPNO. */
410 inline void
411 function_expander::add_input_operand (machine_mode mode, rtx op)
412 {
413 create_input_operand (&m_ops[opno++], op, mode);
414 }
415
416 /* Create output and add it into M_OPS and increase OPNO. */
417 inline void
418 function_expander::add_output_operand (machine_mode mode, rtx target)
419 {
420 create_output_operand (&m_ops[opno++], target, mode);
421 }
422
423 /* Since we may normalize vop/vop_tu/vop_m/vop_tumu.. into a single patter.
424 We add a fake all true mask for the intrinsics that don't need a real mask.
425 */
426 inline void
427 function_expander::add_all_one_mask_operand (machine_mode mode)
428 {
429 add_input_operand (mode, CONSTM1_RTX (mode));
430 }
431
432 /* Add an operand that must be X. The only way of legitimizing an
433 invalid X is to reload the address of a MEM. */
434 inline void
435 function_expander::add_fixed_operand (rtx x)
436 {
437 create_fixed_operand (&m_ops[opno++], x);
438 }
439
440 /* Return the machine_mode of the corresponding vector type. */
441 inline machine_mode
442 function_expander::vector_mode (void) const
443 {
444 return TYPE_MODE (builtin_types[type.index].vector);
445 }
446
447 /* Default implementation of function_base::call_properties, with conservatively
448 correct behavior for floating-point instructions. */
449 inline unsigned int
450 function_base::call_properties (const function_instance &instance) const
451 {
452 unsigned int flags = 0;
453 if (instance.any_type_float_p ())
454 return flags | CP_READ_FPCR | CP_RAISE_FP_EXCEPTIONS;
455 return flags;
456 }
457
458 /* We choose to apply vl operand by default since most of the intrinsics
459 has vl operand. */
460 inline bool
461 function_base::apply_vl_p () const
462 {
463 return true;
464 }
465
466 /* Since most of intrinsics can be overloaded, we set it true by default. */
467 inline bool
468 function_base::can_be_overloaded_p (enum predication_type_index) const
469 {
470 return true;
471 }
472
473 } // end namespace riscv_vector
474
475 #endif