[committed] Fix RISC-V missing stack tie
[official-gcc.git] / gcc / config / riscv / riscv-vector-builtins-shapes.cc
blobc5ffcc1f2c4c0d90a2b4ff1d1704874a9f868451
1 /* function_shape implementation for RISC-V 'V' Extension for GNU compiler.
2 Copyright (C) 2022-2024 Free Software Foundation, Inc.
3 Contributed by Ju-Zhe Zhong (juzhe.zhong@rivai.ai), RiVAI Technologies Ltd.
5 This file is part of GCC.
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.
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.
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/>. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "tree.h"
26 #include "rtl.h"
27 #include "tm_p.h"
28 #include "memmodel.h"
29 #include "insn-codes.h"
30 #include "optabs.h"
31 #include "riscv-vector-builtins.h"
32 #include "riscv-vector-builtins-shapes.h"
34 namespace riscv_vector {
36 /* Check whether the RETURN_TYPE and ARGUMENT_TYPES are
37 valid for the function. */
39 static bool
40 check_type (tree return_type, vec<tree> &argument_types)
42 tree arg;
43 unsigned i;
45 if (!return_type)
46 return false;
48 FOR_EACH_VEC_ELT (argument_types, i, arg)
49 if (!arg)
50 return false;
52 return true;
55 /* Add one function instance for GROUP, using operand suffix at index OI,
56 mode suffix at index PAIR && bi and predication suffix at index pred_idx. */
57 static void
58 build_one (function_builder &b, const function_group_info &group,
59 unsigned int pred_idx, unsigned int vec_type_idx)
61 /* Byte forms of non-tuple vlxusegei take 21 arguments. */
62 auto_vec<tree, 21> argument_types;
63 function_instance function_instance (group.base_name, *group.base,
64 *group.shape,
65 group.ops_infos.types[vec_type_idx],
66 group.preds[pred_idx], &group.ops_infos);
67 tree return_type = group.ops_infos.ret.get_tree_type (
68 group.ops_infos.types[vec_type_idx].index);
69 b.allocate_argument_types (function_instance, argument_types);
70 b.apply_predication (function_instance, return_type, argument_types);
72 if (TARGET_XTHEADVECTOR && !check_type (return_type, argument_types))
73 return;
75 b.add_overloaded_function (function_instance, *group.shape);
76 b.add_unique_function (function_instance, (*group.shape), return_type,
77 argument_types);
80 /* Add a function instance for every operand && predicate && args
81 combination in GROUP. Take the function base name from GROUP && operand
82 suffix from operand_suffixes && mode suffix from type_suffixes && predication
83 suffix from predication_suffixes. Use apply_predication to add in
84 the predicate. */
85 static void
86 build_all (function_builder &b, const function_group_info &group)
88 for (unsigned int pred_idx = 0; group.preds[pred_idx] != NUM_PRED_TYPES;
89 ++pred_idx)
90 for (unsigned int vec_type_idx = 0;
91 group.ops_infos.types[vec_type_idx].index != NUM_VECTOR_TYPES;
92 ++vec_type_idx)
93 build_one (b, group, pred_idx, vec_type_idx);
96 /* Declare the function shape NAME, pointing it to an instance
97 of class <NAME>_def. */
98 #define SHAPE(DEF, VAR) \
99 static CONSTEXPR const DEF##_def VAR##_obj; \
100 namespace shapes { const function_shape *const VAR = &VAR##_obj; }
102 #define BASE_NAME_MAX_LEN 16
104 /* Base class for for build. */
105 struct build_base : public function_shape
107 void build (function_builder &b,
108 const function_group_info &group) const override
110 build_all (b, group);
114 /* vsetvl_def class. */
115 struct vsetvl_def : public build_base
117 char *get_name (function_builder &b, const function_instance &instance,
118 bool overloaded_p) const override
120 /* vsetvl* instruction doesn't have C++ overloaded functions. */
121 if (overloaded_p)
122 return nullptr;
123 b.append_base_name (instance.base_name);
124 b.append_name (type_suffixes[instance.type.index].vsetvl);
125 return b.finish_name ();
129 /* loadstore_def class. */
130 struct loadstore_def : public build_base
132 char *get_name (function_builder &b, const function_instance &instance,
133 bool overloaded_p) const override
135 /* Return nullptr if it can not be overloaded. */
136 if (overloaded_p && !instance.base->can_be_overloaded_p (instance.pred))
137 return nullptr;
139 b.append_base_name (instance.base_name);
141 tree type = builtin_types[instance.type.index].vector;
142 machine_mode mode = TYPE_MODE (type);
143 int sew = GET_MODE_BITSIZE (GET_MODE_INNER (mode));
144 /* vop --> vop<sew>. */
145 if (GET_MODE_CLASS (mode) != MODE_VECTOR_BOOL)
146 b.append_sew (sew);
148 /* vop<sew>_v --> vop<sew>_v_<type>. */
149 if (!overloaded_p)
151 /* vop<sew> --> vop<sew>_v. */
152 b.append_name (operand_suffixes[instance.op_info->op]);
153 /* vop<sew>_v --> vop<sew>_v_<type>. */
154 b.append_name (type_suffixes[instance.type.index].vector);
157 /* According to rvv-intrinsic-doc, it does not add "_m" suffix
158 for vop_m C++ overloaded API. */
159 if (overloaded_p && instance.pred == PRED_TYPE_m)
160 return b.finish_name ();
161 b.append_name (predication_suffixes[instance.pred]);
162 return b.finish_name ();
166 /* indexed_loadstore_def class. */
167 struct indexed_loadstore_def : public function_shape
169 void build (function_builder &b,
170 const function_group_info &group) const override
172 for (unsigned int pred_idx = 0; group.preds[pred_idx] != NUM_PRED_TYPES;
173 ++pred_idx)
175 for (unsigned int vec_type_idx = 0;
176 group.ops_infos.types[vec_type_idx].index != NUM_VECTOR_TYPES;
177 ++vec_type_idx)
179 tree index_type = group.ops_infos.args[1].get_tree_type (
180 group.ops_infos.types[vec_type_idx].index);
181 if (!index_type)
182 continue;
183 build_one (b, group, pred_idx, vec_type_idx);
188 char *get_name (function_builder &b, const function_instance &instance,
189 bool overloaded_p) const override
191 /* Return nullptr if it can not be overloaded. */
192 if (overloaded_p && !instance.base->can_be_overloaded_p (instance.pred))
193 return nullptr;
195 b.append_base_name (instance.base_name);
196 /* vop<sew>_v --> vop<sew>_v_<type>. */
197 if (!overloaded_p)
199 /* vop<sew> --> vop<sew>_v. */
200 b.append_name (operand_suffixes[instance.op_info->op]);
201 /* vop<sew>_v --> vop<sew>_v_<type>. */
202 b.append_name (type_suffixes[instance.type.index].vector);
205 /* According to rvv-intrinsic-doc, it does not add "_m" suffix
206 for vop_m C++ overloaded API. */
207 if (overloaded_p && instance.pred == PRED_TYPE_m)
208 return b.finish_name ();
209 b.append_name (predication_suffixes[instance.pred]);
210 return b.finish_name ();
214 /* Add one function instance for GROUP, using operand suffix at index OI,
215 mode suffix at index PAIR && bi and predication suffix at index pred_idx. */
216 static void
217 build_th_loadstore (function_builder &b, const function_group_info &group,
218 unsigned int pred_idx, unsigned int vec_type_idx)
220 auto_vec<tree, 5> argument_types;
221 function_instance function_instance (group.base_name, *group.base,
222 *group.shape,
223 group.ops_infos.types[vec_type_idx],
224 group.preds[pred_idx], &group.ops_infos);
225 tree return_type = group.ops_infos.ret.get_tree_type (
226 group.ops_infos.types[vec_type_idx].index);
227 b.allocate_argument_types (function_instance, argument_types);
228 b.apply_predication (function_instance, return_type, argument_types);
230 if (TARGET_XTHEADVECTOR && !check_type (return_type, argument_types))
231 return;
233 tree type = builtin_types[group.ops_infos.types[vec_type_idx].index].vector;
234 if (strstr (group.base_name, "l")
235 && strstr (group.base_name, "u")
236 && !TYPE_UNSIGNED (TREE_TYPE (type)))
237 return;
239 if (strstr (group.base_name, "l")
240 && !strstr (group.base_name, "u")
241 && TYPE_UNSIGNED (TREE_TYPE (type)))
242 return;
244 machine_mode mode = TYPE_MODE (type);
245 int sew = GET_MODE_BITSIZE (GET_MODE_INNER (mode));
246 if (strstr (group.base_name, "h") && sew == 8)
247 return;
249 if (strstr (group.base_name, "w") && (sew == 8 || sew ==16))
250 return;
252 b.add_overloaded_function (function_instance, *group.shape);
253 b.add_unique_function (function_instance, (*group.shape), return_type,
254 argument_types);
257 /* th_loadstore_width_def class. */
258 struct th_loadstore_width_def : public build_base
260 void build (function_builder &b,
261 const function_group_info &group) const override
263 for (unsigned int pred_idx = 0; group.preds[pred_idx] != NUM_PRED_TYPES;
264 ++pred_idx)
266 for (unsigned int vec_type_idx = 0;
267 group.ops_infos.types[vec_type_idx].index != NUM_VECTOR_TYPES;
268 ++vec_type_idx)
270 build_th_loadstore (b, group, pred_idx, vec_type_idx);
275 char *get_name (function_builder &b, const function_instance &instance,
276 bool overloaded_p) const override
278 /* Return nullptr if it can not be overloaded. */
279 if (overloaded_p && !instance.base->can_be_overloaded_p (instance.pred))
280 return nullptr;
282 b.append_name ("__riscv_th_");
283 b.append_name (instance.base_name);
285 /* vop_v --> vop_v_<type>. */
286 if (!overloaded_p)
288 /* vop --> vop_v. */
289 b.append_name (operand_suffixes[instance.op_info->op]);
290 /* vop_v --> vop_v_<type>. */
291 b.append_name (type_suffixes[instance.type.index].vector);
294 /* According to rvv-intrinsic-doc, it does not add "_m" suffix
295 for vop_m C++ overloaded API. */
296 if (overloaded_p && instance.pred == PRED_TYPE_m)
297 return b.finish_name ();
298 b.append_name (predication_suffixes[instance.pred]);
299 return b.finish_name ();
304 /* th_indexed_loadstore_width_def class. */
305 struct th_indexed_loadstore_width_def : public function_shape
307 void build (function_builder &b,
308 const function_group_info &group) const override
310 for (unsigned int pred_idx = 0; group.preds[pred_idx] != NUM_PRED_TYPES;
311 ++pred_idx)
313 for (unsigned int vec_type_idx = 0;
314 group.ops_infos.types[vec_type_idx].index != NUM_VECTOR_TYPES;
315 ++vec_type_idx)
317 tree index_type = group.ops_infos.args[1].get_tree_type (
318 group.ops_infos.types[vec_type_idx].index);
319 if (!index_type)
320 continue;
321 build_th_loadstore (b, group, pred_idx, vec_type_idx);
326 char *get_name (function_builder &b, const function_instance &instance,
327 bool overloaded_p) const override
330 /* Return nullptr if it can not be overloaded. */
331 if (overloaded_p && !instance.base->can_be_overloaded_p (instance.pred))
332 return nullptr;
334 b.append_name ("__riscv_th_");
335 b.append_name (instance.base_name);
336 /* vop_v --> vop_v_<type>. */
337 if (!overloaded_p)
339 /* vop --> vop_v. */
340 b.append_name (operand_suffixes[instance.op_info->op]);
341 /* vop_v --> vop_v_<type>. */
342 b.append_name (type_suffixes[instance.type.index].vector);
345 /* According to rvv-intrinsic-doc, it does not add "_m" suffix
346 for vop_m C++ overloaded API. */
347 if (overloaded_p && instance.pred == PRED_TYPE_m)
348 return b.finish_name ();
349 b.append_name (predication_suffixes[instance.pred]);
350 return b.finish_name ();
354 /* alu_def class. */
355 struct alu_def : public build_base
357 char *get_name (function_builder &b, const function_instance &instance,
358 bool overloaded_p) const override
360 /* Return nullptr if it can not be overloaded. */
361 if (overloaded_p && !instance.base->can_be_overloaded_p (instance.pred))
362 return nullptr;
364 b.append_base_name (instance.base_name);
366 /* vop<sew>_<op> --> vop<sew>_<op>_<type>. */
367 if (!overloaded_p)
369 b.append_name (operand_suffixes[instance.op_info->op]);
370 b.append_name (type_suffixes[instance.type.index].vector);
373 /* According to rvv-intrinsic-doc, it does not add "_m" suffix
374 for vop_m C++ overloaded API. */
375 if (overloaded_p && instance.pred == PRED_TYPE_m)
376 return b.finish_name ();
377 b.append_name (predication_suffixes[instance.pred]);
378 return b.finish_name ();
381 bool check (function_checker &c) const override
383 /* Check whether rounding mode argument is a valid immediate. */
384 if (c.base->has_rounding_mode_operand_p ())
386 /* Some invalid overload intrinsic like below will have zero for
387 c.arg_num (). Thus, make sure arg_num is big enough here.
388 __riscv_vaadd () will make c.arg_num () == 0. */
389 if (!c.any_type_float_p () && c.arg_num () >= 2)
390 return c.require_immediate (c.arg_num () - 2, VXRM_RNU, VXRM_ROD);
391 /* TODO: We will support floating-point intrinsic modeling
392 rounding mode in the future. */
394 return true;
398 /* The base class for frm build. */
399 struct build_frm_base : public build_base
401 /* Normalize vf<op>_frm to vf<op>. */
402 static void normalize_base_name (char *to, const char *from, int limit)
404 strncpy (to, from, limit - 1);
405 char *suffix = strstr (to, "_frm");
407 if (suffix)
408 *suffix = '\0';
410 to[limit - 1] = '\0';
413 bool check (function_checker &c) const override
415 gcc_assert (c.any_type_float_p ());
417 /* Check whether rounding mode argument is a valid immediate.
418 Some invalid overload intrinsic like below will have zero for
419 c.arg_num (). Thus, make sure arg_num is big enough here.
420 __riscv_vaadd () will make c.arg_num () == 0. */
421 if (c.base->has_rounding_mode_operand_p () && c.arg_num () >= 2)
423 unsigned int frm_num = c.arg_num () - 2;
425 return c.require_immediate (frm_num, FRM_STATIC_MIN, FRM_STATIC_MAX);
428 return true;
432 /* alu_frm_def class. */
433 struct alu_frm_def : public build_frm_base
435 char *get_name (function_builder &b, const function_instance &instance,
436 bool overloaded_p) const override
438 char base_name[BASE_NAME_MAX_LEN] = {};
440 /* Return nullptr if it can not be overloaded. */
441 if (overloaded_p && !instance.base->can_be_overloaded_p (instance.pred))
442 return nullptr;
444 normalize_base_name (base_name, instance.base_name, sizeof (base_name));
446 b.append_base_name (base_name);
448 /* vop<sew>_<op> --> vop<sew>_<op>_<type>. */
449 if (!overloaded_p)
451 b.append_name (operand_suffixes[instance.op_info->op]);
452 b.append_name (type_suffixes[instance.type.index].vector);
455 /* According to rvv-intrinsic-doc, it does not add "_rm" suffix
456 for vop_rm C++ overloaded API. */
457 if (!overloaded_p)
458 b.append_name ("_rm");
460 /* According to rvv-intrinsic-doc, it does not add "_m" suffix
461 for vop_m C++ overloaded API. */
462 if (overloaded_p && instance.pred == PRED_TYPE_m)
463 return b.finish_name ();
465 b.append_name (predication_suffixes[instance.pred]);
467 return b.finish_name ();
471 /* widen_alu_frm_def class. */
472 struct widen_alu_frm_def : public build_frm_base
474 char *get_name (function_builder &b, const function_instance &instance,
475 bool overloaded_p) const override
477 char base_name[BASE_NAME_MAX_LEN] = {};
479 normalize_base_name (base_name, instance.base_name, sizeof (base_name));
481 b.append_base_name (base_name);
483 /* vop<sew> --> vop<sew>_<op>. */
484 b.append_name (operand_suffixes[instance.op_info->op]);
486 /* vop<sew>_<op> --> vop<sew>_<op>_<type>. */
487 if (!overloaded_p)
488 b.append_name (type_suffixes[instance.type.index].vector);
490 /* According to rvv-intrinsic-doc, it does not add "_rm" suffix
491 for vop_rm C++ overloaded API. */
492 if (!overloaded_p)
493 b.append_name ("_rm");
495 /* According to rvv-intrinsic-doc, it does not add "_m" suffix
496 for vop_m C++ overloaded API. */
497 if (overloaded_p && instance.pred == PRED_TYPE_m)
498 return b.finish_name ();
500 b.append_name (predication_suffixes[instance.pred]);
502 return b.finish_name ();
506 /* narrow_alu_frm_def class. */
507 struct narrow_alu_frm_def : public build_frm_base
509 char *get_name (function_builder &b, const function_instance &instance,
510 bool overloaded_p) const override
512 char base_name[BASE_NAME_MAX_LEN] = {};
514 normalize_base_name (base_name, instance.base_name, sizeof (base_name));
516 b.append_base_name (base_name);
518 if (!overloaded_p)
520 /* vop --> vop_<op>. */
521 b.append_name (operand_suffixes[instance.op_info->op]);
522 /* vop_<op> --> vop_<op>_<type>. */
523 vector_type_index ret_type_idx
524 = instance.op_info->ret.get_function_type_index (instance.type.index);
525 b.append_name (type_suffixes[ret_type_idx].vector);
528 /* According to rvv-intrinsic-doc, it does not add "_rm" suffix
529 for vop_rm C++ overloaded API. */
530 if (!overloaded_p)
531 b.append_name ("_rm");
533 /* According to rvv-intrinsic-doc, it does not add "_m" suffix
534 for vop_m C++ overloaded API. */
535 if (overloaded_p && instance.pred == PRED_TYPE_m)
536 return b.finish_name ();
538 b.append_name (predication_suffixes[instance.pred]);
540 return b.finish_name ();
544 /* reduc_alu_frm_def class. */
545 struct reduc_alu_frm_def : public build_frm_base
547 char *get_name (function_builder &b, const function_instance &instance,
548 bool overloaded_p) const override
550 char base_name[BASE_NAME_MAX_LEN] = {};
552 normalize_base_name (base_name, instance.base_name, sizeof (base_name));
554 b.append_base_name (base_name);
556 /* vop_<op> --> vop<sew>_<op>_<type>. */
557 if (!overloaded_p)
559 b.append_name (operand_suffixes[instance.op_info->op]);
560 b.append_name (type_suffixes[instance.type.index].vector);
561 vector_type_index ret_type_idx
562 = instance.op_info->ret.get_function_type_index (instance.type.index);
563 b.append_name (type_suffixes[ret_type_idx].vector);
566 /* According to rvv-intrinsic-doc, it does not add "_rm" suffix
567 for vop_rm C++ overloaded API. */
568 if (!overloaded_p)
569 b.append_name ("_rm");
571 /* According to rvv-intrinsic-doc, it does not add "_m" suffix
572 for vop_m C++ overloaded API. */
573 if (overloaded_p && instance.pred == PRED_TYPE_m)
574 return b.finish_name ();
576 b.append_name (predication_suffixes[instance.pred]);
578 return b.finish_name ();
582 /* widen_alu_def class. Handle vwadd/vwsub. Unlike
583 vadd.vx/vadd.vv/vwmul.vv/vwmul.vx, vwadd.vv/vwadd.vx/vwadd.wv/vwadd.wx has
584 'OP' suffix in overloaded API. */
585 struct widen_alu_def : public build_base
587 char *get_name (function_builder &b, const function_instance &instance,
588 bool overloaded_p) const override
590 b.append_base_name (instance.base_name);
592 /* vop<sew> --> vop<sew>_<op>. */
593 b.append_name (operand_suffixes[instance.op_info->op]);
595 /* vop<sew>_<op> --> vop<sew>_<op>_<type>. */
596 if (!overloaded_p)
597 b.append_name (type_suffixes[instance.type.index].vector);
599 /* According to rvv-intrinsic-doc, it does not add "_m" suffix
600 for vop_m C++ overloaded API. */
601 if (overloaded_p && instance.pred == PRED_TYPE_m)
602 return b.finish_name ();
603 b.append_name (predication_suffixes[instance.pred]);
604 return b.finish_name ();
608 /* no_mask_policy_def class. Such instructions belong to this class
609 doesn't need mask policy. */
610 struct no_mask_policy_def : public build_base
612 char *get_name (function_builder &b, const function_instance &instance,
613 bool overloaded_p) const override
615 b.append_base_name (instance.base_name);
617 if (!overloaded_p)
618 b.append_name (operand_suffixes[instance.op_info->op]);
620 /* vop<sew>_<op> --> vop<sew>_<op>_<type>. */
621 if (!overloaded_p)
622 b.append_name (type_suffixes[instance.type.index].vector);
624 b.append_name (predication_suffixes[instance.pred]);
625 return b.finish_name ();
629 /* return_mask_def class. Such instructions belong to this class
630 is returning mask value. */
631 struct return_mask_def : public build_base
633 char *get_name (function_builder &b, const function_instance &instance,
634 bool overloaded_p) const override
636 b.append_base_name (instance.base_name);
638 if (!overloaded_p)
639 b.append_name (operand_suffixes[instance.op_info->op]);
641 /* vop<sew>_<op> --> vop<sew>_<op>_<type1>_<type2>. */
642 if (!overloaded_p)
644 b.append_name (type_suffixes[instance.type.index].vector);
645 vector_type_index ret_type_idx
646 = instance.op_info->ret.get_function_type_index (instance.type.index);
647 b.append_name (type_suffixes[ret_type_idx].vector);
650 if (overloaded_p && instance.pred == PRED_TYPE_m)
651 return b.finish_name ();
652 b.append_name (predication_suffixes[instance.pred]);
653 return b.finish_name ();
657 /* narrow_alu_def class. Handle narrowing instructions like vnsrl.wv. */
658 struct narrow_alu_def : public build_base
660 char *get_name (function_builder &b, const function_instance &instance,
661 bool overloaded_p) const override
663 b.append_base_name (instance.base_name);
665 if (!overloaded_p)
667 /* vop --> vop_<op>. */
668 b.append_name (operand_suffixes[instance.op_info->op]);
669 /* vop_<op> --> vop_<op>_<type>. */
670 vector_type_index ret_type_idx
671 = instance.op_info->ret.get_function_type_index (instance.type.index);
672 b.append_name (type_suffixes[ret_type_idx].vector);
675 /* According to rvv-intrinsic-doc, it does not add "_m" suffix
676 for vop_m C++ overloaded API. */
677 if (overloaded_p && instance.pred == PRED_TYPE_m)
678 return b.finish_name ();
679 b.append_name (predication_suffixes[instance.pred]);
680 return b.finish_name ();
683 bool check (function_checker &c) const override
685 /* Check whether rounding mode argument is a valid immediate. */
686 if (c.base->has_rounding_mode_operand_p ())
688 /* Some invalid overload intrinsic like below will have zero for
689 c.arg_num (). Thus, make sure arg_num is big enough here.
690 __riscv_vaadd () will make c.arg_num () == 0. */
691 if (!c.any_type_float_p () && c.arg_num () >= 2)
692 return c.require_immediate (c.arg_num () - 2, VXRM_RNU, VXRM_ROD);
693 /* TODO: We will support floating-point intrinsic modeling
694 rounding mode in the future. */
696 return true;
700 /* move_def class. Handle vmv.v.v/vmv.v.x. */
701 struct move_def : public build_base
703 char *get_name (function_builder &b, const function_instance &instance,
704 bool overloaded_p) const override
706 /* vmv.v.x/vfmv.v.f (PRED_none) can not be overloaded. */
707 if ((instance.op_info->op == OP_TYPE_x || instance.op_info->op == OP_TYPE_f)
708 && overloaded_p && instance.pred == PRED_TYPE_none)
709 return nullptr;
711 b.append_base_name (instance.base_name);
713 if (!overloaded_p)
715 b.append_name (operand_suffixes[instance.op_info->op]);
716 b.append_name (type_suffixes[instance.type.index].vector);
719 /* According to rvv-intrinsic-doc, it does not add "_m" suffix
720 for vop_m C++ overloaded API. */
721 if (overloaded_p && instance.pred == PRED_TYPE_m)
722 return b.finish_name ();
723 b.append_name (predication_suffixes[instance.pred]);
724 return b.finish_name ();
728 /* mask_alu_def class. */
729 struct mask_alu_def : public build_base
731 char *get_name (function_builder &b, const function_instance &instance,
732 bool overloaded_p) const override
734 /* Return nullptr if it can not be overloaded. */
735 if (overloaded_p && !instance.base->can_be_overloaded_p (instance.pred))
736 return nullptr;
738 b.append_base_name (instance.base_name);
740 if (instance.op_info->op == OP_TYPE_mm || instance.op_info->op == OP_TYPE_m)
741 if (!overloaded_p)
742 b.append_name (operand_suffixes[instance.op_info->op]);
744 /* vop<sew>_<op> --> vop<sew>_<op>_<type>. */
745 if (!overloaded_p)
746 b.append_name (type_suffixes[instance.type.index].vector);
748 /* According to rvv-intrinsic-doc, it does not add "_m" suffix
749 for vop_m C++ overloaded API. */
750 if (overloaded_p && instance.pred == PRED_TYPE_m)
751 return b.finish_name ();
752 b.append_name (predication_suffixes[instance.pred]);
753 return b.finish_name ();
757 /* reduc_alu_def class. */
758 struct reduc_alu_def : public build_base
760 char *get_name (function_builder &b, const function_instance &instance,
761 bool overloaded_p) const override
763 b.append_base_name (instance.base_name);
765 /* vop_<op> --> vop<sew>_<op>_<type>. */
766 if (!overloaded_p)
768 b.append_name (operand_suffixes[instance.op_info->op]);
769 b.append_name (type_suffixes[instance.type.index].vector);
770 vector_type_index ret_type_idx
771 = instance.op_info->ret.get_function_type_index (instance.type.index);
772 b.append_name (type_suffixes[ret_type_idx].vector);
775 /* According to rvv-intrinsic-doc, it does not add "_m" suffix
776 for vop_m C++ overloaded API. */
777 if (overloaded_p && instance.pred == PRED_TYPE_m)
778 return b.finish_name ();
779 b.append_name (predication_suffixes[instance.pred]);
780 return b.finish_name ();
784 /* th_extract_def class. */
785 struct th_extract_def : public build_base
787 char *get_name (function_builder &b, const function_instance &instance,
788 bool overloaded_p) const override
790 b.append_name ("__riscv_th_");
791 b.append_name (instance.base_name);
793 if (overloaded_p)
794 return b.finish_name ();
795 b.append_name (type_suffixes[instance.type.index].vector);
796 b.append_name (type_suffixes[instance.type.index].scalar);
797 return b.finish_name ();
801 /* scalar_move_def class. */
802 struct scalar_move_def : public build_base
804 char *get_name (function_builder &b, const function_instance &instance,
805 bool overloaded_p) const override
807 b.append_base_name (instance.base_name);
808 if (overloaded_p)
809 return b.finish_name ();
810 b.append_name (operand_suffixes[instance.op_info->op]);
811 b.append_name (type_suffixes[instance.type.index].vector);
812 b.append_name (type_suffixes[instance.type.index].scalar);
813 return b.finish_name ();
817 /* vundefined_def class. */
818 struct vundefined_def : public build_base
820 char *get_name (function_builder &b, const function_instance &instance,
821 bool overloaded_p) const override
823 if (overloaded_p)
824 return nullptr;
825 b.append_base_name (instance.base_name);
826 b.append_name (type_suffixes[instance.type.index].vector);
827 return b.finish_name ();
831 /* misc_def class. */
832 struct misc_def : public build_base
834 char *get_name (function_builder &b, const function_instance &instance,
835 bool overloaded_p) const override
837 b.append_base_name (instance.base_name);
839 if (!overloaded_p)
841 b.append_name (operand_suffixes[instance.op_info->op]);
842 vector_type_index arg0_type_idx
843 = instance.op_info->args[0].get_function_type_index (
844 instance.type.index);
845 b.append_name (type_suffixes[arg0_type_idx].vector);
848 vector_type_index ret_type_idx
849 = instance.op_info->ret.get_function_type_index (instance.type.index);
850 b.append_name (type_suffixes[ret_type_idx].vector);
851 return b.finish_name ();
855 /* vset_def class. */
856 struct vset_def : public build_base
858 char *get_name (function_builder &b, const function_instance &instance,
859 bool overloaded_p) const override
861 b.append_base_name (instance.base_name);
863 if (!overloaded_p)
865 b.append_name (operand_suffixes[instance.op_info->op]);
866 vector_type_index arg_type_idx
867 = instance.op_info->args[2].get_function_type_index (
868 instance.type.index);
869 b.append_name (type_suffixes[arg_type_idx].vector);
871 vector_type_index ret_type_idx
872 = instance.op_info->ret.get_function_type_index (instance.type.index);
873 b.append_name (type_suffixes[ret_type_idx].vector);
875 return b.finish_name ();
878 bool check (function_checker &c) const override
880 poly_int64 outer_size = GET_MODE_SIZE (c.arg_mode (0));
881 poly_int64 inner_size = GET_MODE_SIZE (c.arg_mode (2));
882 unsigned int nvecs = exact_div (outer_size, inner_size).to_constant ();
883 return c.require_immediate (1, 0, nvecs - 1);
887 /* vget_def class. */
888 struct vget_def : public misc_def
890 bool check (function_checker &c) const override
892 poly_int64 outer_size = GET_MODE_SIZE (c.arg_mode (0));
893 poly_int64 inner_size = GET_MODE_SIZE (c.ret_mode ());
894 unsigned int nvecs = exact_div (outer_size, inner_size).to_constant ();
895 return c.require_immediate (1, 0, nvecs - 1);
899 /* vcreate_def class. */
900 struct vcreate_def : public build_base
902 void build (function_builder &b,
903 const function_group_info &group) const override
905 for (unsigned int vec_type_idx = 0;
906 group.ops_infos.types[vec_type_idx].index != NUM_VECTOR_TYPES;
907 ++vec_type_idx)
909 auto_vec<tree, 8> argument_types;
910 function_instance function_instance (group.base_name, *group.base,
911 *group.shape,
912 group.ops_infos.types[vec_type_idx],
913 group.preds[0], &group.ops_infos);
915 tree return_type = group.ops_infos.ret.get_tree_type (
916 group.ops_infos.types[vec_type_idx].index);
918 if (!return_type)
919 continue;
921 tree arg_type = function_instance.op_info->args[0].get_tree_type (
922 function_instance.type.index);
924 machine_mode outer_mode = TYPE_MODE (return_type);
925 machine_mode inner_mode = TYPE_MODE (arg_type);
926 unsigned int nargs
927 = exact_div (GET_MODE_SIZE (outer_mode), GET_MODE_SIZE (inner_mode))
928 .to_constant ();
930 for (unsigned int i = 0; i < nargs; i++)
931 argument_types.quick_push (arg_type);
933 b.add_unique_function (function_instance, (*group.shape), return_type,
934 argument_types);
938 char *get_name (function_builder &b, const function_instance &instance,
939 bool overloaded_p) const override
941 if (overloaded_p)
942 return nullptr;
943 b.append_base_name (instance.base_name);
944 b.append_name (operand_suffixes[instance.op_info->op]);
946 if (instance.op_info->ret.base_type != RVV_BASE_vector)
948 vector_type_index arg_type_idx
949 = instance.op_info->args[0].get_function_type_index (
950 instance.type.index);
951 b.append_name (type_suffixes[arg_type_idx].vector);
954 vector_type_index ret_type_idx
955 = instance.op_info->ret.get_function_type_index (instance.type.index);
956 b.append_name (type_suffixes[ret_type_idx].vector);
957 return b.finish_name ();
961 /* read_vl_def class. */
962 struct read_vl_def : public function_shape
964 void build (function_builder &b,
965 const function_group_info &group) const override
967 auto_vec<tree> argument_types;
968 b.add_unique_function (get_read_vl_instance (), (*group.shape),
969 size_type_node, argument_types);
972 char *get_name (function_builder &b, const function_instance &instance,
973 bool overloaded_p) const override
975 if (overloaded_p)
976 return nullptr;
977 b.append_base_name (instance.base_name);
978 return b.finish_name ();
982 /* fault_load_def class. */
983 struct fault_load_def : public build_base
985 char *get_name (function_builder &b, const function_instance &instance,
986 bool overloaded_p) const override
988 if (overloaded_p && !instance.base->can_be_overloaded_p (instance.pred))
989 return nullptr;
990 tree type = builtin_types[instance.type.index].vector;
991 machine_mode mode = TYPE_MODE (type);
992 int sew = GET_MODE_BITSIZE (GET_MODE_INNER (mode));
993 b.append_name ("__riscv_");
994 b.append_name ("vle");
995 b.append_sew (sew);
996 b.append_name ("ff");
998 /* vop<sew>_v --> vop<sew>_v_<type>. */
999 if (!overloaded_p)
1001 /* vop<sew> --> vop<sew>_v. */
1002 b.append_name (operand_suffixes[instance.op_info->op]);
1003 /* vop<sew>_v --> vop<sew>_v_<type>. */
1004 b.append_name (type_suffixes[instance.type.index].vector);
1007 /* According to rvv-intrinsic-doc, it does not add "_m" suffix
1008 for vop_m C++ overloaded API. */
1009 if (overloaded_p && instance.pred == PRED_TYPE_m)
1010 return b.finish_name ();
1011 b.append_name (predication_suffixes[instance.pred]);
1012 return b.finish_name ();
1016 /* vlenb_def class. */
1017 struct vlenb_def : public function_shape
1019 void build (function_builder &b,
1020 const function_group_info &group) const override
1022 auto_vec<tree> argument_types;
1023 function_instance function_instance (group.base_name, *group.base,
1024 *group.shape, group.ops_infos.types[0],
1025 group.preds[0], &group.ops_infos);
1026 b.add_unique_function (function_instance, (*group.shape),
1027 long_unsigned_type_node, argument_types);
1030 char *get_name (function_builder &b, const function_instance &instance,
1031 bool overloaded_p) const override
1033 if (overloaded_p)
1034 return nullptr;
1035 b.append_base_name (instance.base_name);
1036 return b.finish_name ();
1040 /* seg_loadstore_def class. */
1041 struct seg_loadstore_def : public build_base
1043 char *get_name (function_builder &b, const function_instance &instance,
1044 bool overloaded_p) const override
1046 /* Return nullptr if it can not be overloaded. */
1047 if (overloaded_p && !instance.base->can_be_overloaded_p (instance.pred))
1048 return nullptr;
1050 b.append_base_name (instance.base_name);
1052 tree type = builtin_types[instance.type.index].vector;
1053 machine_mode mode = TYPE_MODE (type);
1055 int nf = get_nf (mode);
1056 /* vop --> vop<nf>. */
1057 b.append_nf (nf);
1059 /* vop<nf> --> vop<nf>e. */
1060 b.append_name ("e");
1062 int sew = GET_MODE_BITSIZE (GET_MODE_INNER (mode));
1063 /* vop<nf>e --> vop<nf>e<sew>. */
1064 b.append_sew (sew);
1066 if (!overloaded_p)
1068 /* vop<nf>e<sew> --> vop<nf>e<sew>_v. */
1069 b.append_name (operand_suffixes[instance.op_info->op]);
1070 /* vop<nf>e<sew>_v --> vop<nf>e<sew>_v_<type>. */
1071 b.append_name (type_suffixes[instance.type.index].vector);
1074 /* According to rvv-intrinsic-doc, it does not add "_m" suffix
1075 for vop_m C++ overloaded API. */
1076 if (overloaded_p && instance.pred == PRED_TYPE_m)
1077 return b.finish_name ();
1078 b.append_name (predication_suffixes[instance.pred]);
1079 return b.finish_name ();
1083 /* seg_indexed_loadstore_def class. */
1084 struct seg_indexed_loadstore_def : public indexed_loadstore_def
1086 char *get_name (function_builder &b, const function_instance &instance,
1087 bool overloaded_p) const override
1089 /* Return nullptr if it can not be overloaded. */
1090 if (overloaded_p && !instance.base->can_be_overloaded_p (instance.pred))
1091 return nullptr;
1093 b.append_base_name (instance.base_name);
1095 tree type = builtin_types[instance.type.index].vector;
1096 machine_mode mode = TYPE_MODE (type);
1098 int nf = get_nf (mode);
1099 /* vop --> vop<nf>. */
1100 b.append_nf (nf);
1102 /* vop<nf> --> vop<nf>ei. */
1103 b.append_name ("ei");
1105 /* vop<nf>ei --> vop<nf>ei<eew>. */
1106 vector_type_index arg1_type_idx
1107 = instance.op_info->args[1].get_function_type_index (instance.type.index);
1108 tree index_type = builtin_types[arg1_type_idx].vector;
1109 machine_mode index_mode = TYPE_MODE (index_type);
1110 int eew = GET_MODE_BITSIZE (GET_MODE_INNER (index_mode));
1111 b.append_sew (eew);
1113 if (!overloaded_p)
1115 /* vop<sew> --> vop<sew>_v. */
1116 b.append_name (operand_suffixes[instance.op_info->op]);
1117 /* vop<sew>_v --> vop<sew>_v_<type>. */
1118 b.append_name (type_suffixes[instance.type.index].vector);
1121 /* According to rvv-intrinsic-doc, it does not add "_m" suffix
1122 for vop_m C++ overloaded API. */
1123 if (overloaded_p && instance.pred == PRED_TYPE_m)
1124 return b.finish_name ();
1125 b.append_name (predication_suffixes[instance.pred]);
1126 return b.finish_name ();
1130 /* seg_fault_load_def class. */
1131 struct seg_fault_load_def : public build_base
1133 char *get_name (function_builder &b, const function_instance &instance,
1134 bool overloaded_p) const override
1136 /* Return nullptr if it can not be overloaded. */
1137 if (overloaded_p && !instance.base->can_be_overloaded_p (instance.pred))
1138 return nullptr;
1140 b.append_name ("__riscv_vlseg");
1142 tree type = builtin_types[instance.type.index].vector;
1143 machine_mode mode = TYPE_MODE (type);
1145 int nf = get_nf (mode);
1146 /* vop --> vop<nf>. */
1147 b.append_nf (nf);
1149 /* vop<nf> --> vop<nf>e. */
1150 b.append_name ("e");
1152 int sew = GET_MODE_BITSIZE (GET_MODE_INNER (mode));
1153 /* vop<nf>e --> vop<nf>e<sew>. */
1154 b.append_sew (sew);
1156 /* vop<nf>e<sew> --> vop<nf>e<sew>ff. */
1157 b.append_name ("ff");
1159 if (!overloaded_p)
1161 /* vop<nf>e<sew>ff --> vop<nf>e<sew>ff_v. */
1162 b.append_name (operand_suffixes[instance.op_info->op]);
1163 /* vop<nf>e<sew>ff_v --> vop<nf>e<sew>ff_v_<type>. */
1164 b.append_name (type_suffixes[instance.type.index].vector);
1167 /* According to rvv-intrinsic-doc, it does not add "_m" suffix
1168 for vop_m C++ overloaded API. */
1169 if (overloaded_p && instance.pred == PRED_TYPE_m)
1170 return b.finish_name ();
1171 b.append_name (predication_suffixes[instance.pred]);
1172 return b.finish_name ();
1176 /* vsm4r/vaes* class. */
1177 struct crypto_vv_def : public build_base
1179 char *get_name (function_builder &b, const function_instance &instance,
1180 bool overloaded_p) const override
1182 /* Return nullptr if it can not be overloaded. */
1183 if (overloaded_p && !instance.base->can_be_overloaded_p (instance.pred))
1184 return nullptr;
1185 b.append_base_name (instance.base_name);
1186 b.append_name (operand_suffixes[instance.op_info->op]);
1188 if (!overloaded_p)
1190 if (instance.op_info->op == OP_TYPE_vv)
1191 b.append_name (type_suffixes[instance.type.index].vector);
1192 else
1194 vector_type_index arg0_type_idx
1195 = instance.op_info->args[1].get_function_type_index
1196 (instance.type.index);
1197 b.append_name (type_suffixes[arg0_type_idx].vector);
1198 vector_type_index ret_type_idx
1199 = instance.op_info->ret.get_function_type_index
1200 (instance.type.index);
1201 b.append_name (type_suffixes[ret_type_idx].vector);
1205 b.append_name (predication_suffixes[instance.pred]);
1206 return b.finish_name ();
1210 /* vaeskf1/vaeskf2/vsm4k/vsm3c class. */
1211 struct crypto_vi_def : public build_base
1213 char *get_name (function_builder &b, const function_instance &instance,
1214 bool overloaded_p) const override
1216 /* Return nullptr if it can not be overloaded. */
1217 if (overloaded_p && !instance.base->can_be_overloaded_p (instance.pred))
1218 return nullptr;
1219 b.append_base_name (instance.base_name);
1220 if (!overloaded_p)
1222 b.append_name (operand_suffixes[instance.op_info->op]);
1223 b.append_name (type_suffixes[instance.type.index].vector);
1225 b.append_name (predication_suffixes[instance.pred]);
1226 return b.finish_name ();
1230 /* vaesz class. */
1231 struct crypto_vv_no_op_type_def : public build_base
1233 char *get_name (function_builder &b, const function_instance &instance,
1234 bool overloaded_p) const override
1236 /* Return nullptr if it can not be overloaded. */
1237 if (overloaded_p && !instance.base->can_be_overloaded_p (instance.pred))
1238 return nullptr;
1239 b.append_base_name (instance.base_name);
1241 if (!overloaded_p)
1243 b.append_name (operand_suffixes[instance.op_info->op]);
1244 vector_type_index arg0_type_idx
1245 = instance.op_info->args[1].get_function_type_index
1246 (instance.type.index);
1247 b.append_name (type_suffixes[arg0_type_idx].vector);
1248 vector_type_index ret_type_idx
1249 = instance.op_info->ret.get_function_type_index
1250 (instance.type.index);
1251 b.append_name (type_suffixes[ret_type_idx].vector);
1254 b.append_name (predication_suffixes[instance.pred]);
1255 return b.finish_name ();
1259 SHAPE(vsetvl, vsetvl)
1260 SHAPE(vsetvl, vsetvlmax)
1261 SHAPE(loadstore, loadstore)
1262 SHAPE(indexed_loadstore, indexed_loadstore)
1263 SHAPE(th_loadstore_width, th_loadstore_width)
1264 SHAPE(th_indexed_loadstore_width, th_indexed_loadstore_width)
1265 SHAPE(alu, alu)
1266 SHAPE(alu_frm, alu_frm)
1267 SHAPE(widen_alu, widen_alu)
1268 SHAPE(widen_alu_frm, widen_alu_frm)
1269 SHAPE(no_mask_policy, no_mask_policy)
1270 SHAPE(return_mask, return_mask)
1271 SHAPE(narrow_alu, narrow_alu)
1272 SHAPE(narrow_alu_frm, narrow_alu_frm)
1273 SHAPE(move, move)
1274 SHAPE(mask_alu, mask_alu)
1275 SHAPE(reduc_alu, reduc_alu)
1276 SHAPE(reduc_alu_frm, reduc_alu_frm)
1277 SHAPE(th_extract, th_extract)
1278 SHAPE(scalar_move, scalar_move)
1279 SHAPE(vundefined, vundefined)
1280 SHAPE(misc, misc)
1281 SHAPE(vset, vset)
1282 SHAPE(vget, vget)
1283 SHAPE(vcreate, vcreate)
1284 SHAPE(read_vl, read_vl)
1285 SHAPE(fault_load, fault_load)
1286 SHAPE(vlenb, vlenb)
1287 SHAPE(seg_loadstore, seg_loadstore)
1288 SHAPE(seg_indexed_loadstore, seg_indexed_loadstore)
1289 SHAPE(seg_fault_load, seg_fault_load)
1290 SHAPE(crypto_vv, crypto_vv)
1291 SHAPE(crypto_vi, crypto_vi)
1292 SHAPE(crypto_vv_no_op_type, crypto_vv_no_op_type)
1293 } // end namespace riscv_vector