Add config file so b4 uses inbox.sourceware.org automatically
[official-gcc.git] / gcc / config / riscv / riscv-vector-builtins-shapes.cc
blob33395414aae999f738336a19d111bd0ac448c6d8
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 group.required_extensions);
77 b.add_unique_function (function_instance, (*group.shape), return_type,
78 argument_types, group.required_extensions);
81 /* Determine whether the intrinsic supports the currently
82 processed vector type */
83 static bool
84 supports_vectype_p (const function_group_info &group, unsigned int vec_type_idx)
86 int index = group.ops_infos.types[vec_type_idx].index;
87 if (index < VECTOR_TYPE_vbfloat16mf4_t || index > VECTOR_TYPE_vbfloat16m8_t)
88 return true;
89 /* Only judge for bf16 vector type */
90 if (*group.shape == shapes::loadstore
91 || *group.shape == shapes::indexed_loadstore
92 || *group.shape == shapes::vundefined
93 || *group.shape == shapes::misc
94 || *group.shape == shapes::vset
95 || *group.shape == shapes::vget
96 || *group.shape == shapes::vcreate
97 || *group.shape == shapes::fault_load
98 || *group.shape == shapes::seg_loadstore
99 || *group.shape == shapes::seg_indexed_loadstore
100 || *group.shape == shapes::seg_fault_load)
101 return true;
102 return false;
105 /* Add a function instance for every operand && predicate && args
106 combination in GROUP. Take the function base name from GROUP && operand
107 suffix from operand_suffixes && mode suffix from type_suffixes && predication
108 suffix from predication_suffixes. Use apply_predication to add in
109 the predicate. */
110 static void
111 build_all (function_builder &b, const function_group_info &group)
113 for (unsigned int pred_idx = 0; group.preds[pred_idx] != NUM_PRED_TYPES;
114 ++pred_idx)
115 for (unsigned int vec_type_idx = 0;
116 group.ops_infos.types[vec_type_idx].index != NUM_VECTOR_TYPES;
117 ++vec_type_idx)
119 if (supports_vectype_p (group, vec_type_idx))
120 build_one (b, group, pred_idx, vec_type_idx);
124 /* Declare the function shape NAME, pointing it to an instance
125 of class <NAME>_def. */
126 #define SHAPE(DEF, VAR) \
127 static CONSTEXPR const DEF##_def VAR##_obj; \
128 namespace shapes { const function_shape *const VAR = &VAR##_obj; }
130 #define BASE_NAME_MAX_LEN 17
132 /* Base class for build. */
133 struct build_base : public function_shape
135 void build (function_builder &b,
136 const function_group_info &group) const override
138 build_all (b, group);
142 /* vsetvl_def class. */
143 struct vsetvl_def : public build_base
145 char *get_name (function_builder &b, const function_instance &instance,
146 bool overloaded_p) const override
148 /* vsetvl* instruction doesn't have C++ overloaded functions. */
149 if (overloaded_p)
150 return nullptr;
151 b.append_base_name (instance.base_name);
152 b.append_name (type_suffixes[instance.type.index].vsetvl);
153 return b.finish_name ();
157 /* loadstore_def class. */
158 struct loadstore_def : public build_base
160 char *get_name (function_builder &b, const function_instance &instance,
161 bool overloaded_p) const override
163 /* Return nullptr if it can not be overloaded. */
164 if (overloaded_p && !instance.base->can_be_overloaded_p (instance.pred))
165 return nullptr;
167 b.append_base_name (instance.base_name);
169 tree type = builtin_types[instance.type.index].vector;
170 machine_mode mode = TYPE_MODE (type);
171 int sew = GET_MODE_BITSIZE (GET_MODE_INNER (mode));
172 /* vop --> vop<sew>. */
173 if (GET_MODE_CLASS (mode) != MODE_VECTOR_BOOL)
174 b.append_sew (sew);
176 /* vop<sew>_v --> vop<sew>_v_<type>. */
177 if (!overloaded_p)
179 /* vop<sew> --> vop<sew>_v. */
180 b.append_name (operand_suffixes[instance.op_info->op]);
181 /* vop<sew>_v --> vop<sew>_v_<type>. */
182 b.append_name (type_suffixes[instance.type.index].vector);
185 /* According to rvv-intrinsic-doc, it does not add "_m" suffix
186 for vop_m C++ overloaded API. */
187 if (overloaded_p && instance.pred == PRED_TYPE_m)
188 return b.finish_name ();
189 b.append_name (predication_suffixes[instance.pred]);
190 return b.finish_name ();
194 /* indexed_loadstore_def class. */
195 struct indexed_loadstore_def : public function_shape
197 void build (function_builder &b,
198 const function_group_info &group) const override
200 for (unsigned int pred_idx = 0; group.preds[pred_idx] != NUM_PRED_TYPES;
201 ++pred_idx)
203 for (unsigned int vec_type_idx = 0;
204 group.ops_infos.types[vec_type_idx].index != NUM_VECTOR_TYPES;
205 ++vec_type_idx)
207 tree index_type = group.ops_infos.args[1].get_tree_type (
208 group.ops_infos.types[vec_type_idx].index);
209 if (!index_type)
210 continue;
211 build_one (b, group, pred_idx, vec_type_idx);
216 char *get_name (function_builder &b, const function_instance &instance,
217 bool overloaded_p) const override
219 /* Return nullptr if it can not be overloaded. */
220 if (overloaded_p && !instance.base->can_be_overloaded_p (instance.pred))
221 return nullptr;
223 b.append_base_name (instance.base_name);
224 /* vop<sew>_v --> vop<sew>_v_<type>. */
225 if (!overloaded_p)
227 /* vop<sew> --> vop<sew>_v. */
228 b.append_name (operand_suffixes[instance.op_info->op]);
229 /* vop<sew>_v --> vop<sew>_v_<type>. */
230 b.append_name (type_suffixes[instance.type.index].vector);
233 /* According to rvv-intrinsic-doc, it does not add "_m" suffix
234 for vop_m C++ overloaded API. */
235 if (overloaded_p && instance.pred == PRED_TYPE_m)
236 return b.finish_name ();
237 b.append_name (predication_suffixes[instance.pred]);
238 return b.finish_name ();
242 /* Add one function instance for GROUP, using operand suffix at index OI,
243 mode suffix at index PAIR && bi and predication suffix at index pred_idx. */
244 static void
245 build_th_loadstore (function_builder &b, const function_group_info &group,
246 unsigned int pred_idx, unsigned int vec_type_idx)
248 auto_vec<tree, 5> argument_types;
249 function_instance function_instance (group.base_name, *group.base,
250 *group.shape,
251 group.ops_infos.types[vec_type_idx],
252 group.preds[pred_idx], &group.ops_infos);
253 tree return_type = group.ops_infos.ret.get_tree_type (
254 group.ops_infos.types[vec_type_idx].index);
255 b.allocate_argument_types (function_instance, argument_types);
256 b.apply_predication (function_instance, return_type, argument_types);
258 if (TARGET_XTHEADVECTOR && !check_type (return_type, argument_types))
259 return;
261 tree type = builtin_types[group.ops_infos.types[vec_type_idx].index].vector;
262 if (strstr (group.base_name, "l")
263 && strstr (group.base_name, "u")
264 && !TYPE_UNSIGNED (TREE_TYPE (type)))
265 return;
267 if (strstr (group.base_name, "l")
268 && !strstr (group.base_name, "u")
269 && TYPE_UNSIGNED (TREE_TYPE (type)))
270 return;
272 machine_mode mode = TYPE_MODE (type);
273 int sew = GET_MODE_BITSIZE (GET_MODE_INNER (mode));
274 if (strstr (group.base_name, "h") && sew == 8)
275 return;
277 if (strstr (group.base_name, "w") && (sew == 8 || sew ==16))
278 return;
280 b.add_overloaded_function (function_instance, *group.shape,
281 group.required_extensions);
282 b.add_unique_function (function_instance, (*group.shape), return_type,
283 argument_types, group.required_extensions);
286 /* th_loadstore_width_def class. */
287 struct th_loadstore_width_def : public build_base
289 void build (function_builder &b,
290 const function_group_info &group) const override
292 for (unsigned int pred_idx = 0; group.preds[pred_idx] != NUM_PRED_TYPES;
293 ++pred_idx)
295 for (unsigned int vec_type_idx = 0;
296 group.ops_infos.types[vec_type_idx].index != NUM_VECTOR_TYPES;
297 ++vec_type_idx)
299 build_th_loadstore (b, group, pred_idx, vec_type_idx);
304 char *get_name (function_builder &b, const function_instance &instance,
305 bool overloaded_p) const override
307 /* Return nullptr if it can not be overloaded. */
308 if (overloaded_p && !instance.base->can_be_overloaded_p (instance.pred))
309 return nullptr;
311 b.append_name ("__riscv_th_");
312 b.append_name (instance.base_name);
314 /* vop_v --> vop_v_<type>. */
315 if (!overloaded_p)
317 /* vop --> vop_v. */
318 b.append_name (operand_suffixes[instance.op_info->op]);
319 /* vop_v --> vop_v_<type>. */
320 b.append_name (type_suffixes[instance.type.index].vector);
323 /* According to rvv-intrinsic-doc, it does not add "_m" suffix
324 for vop_m C++ overloaded API. */
325 if (overloaded_p && instance.pred == PRED_TYPE_m)
326 return b.finish_name ();
327 b.append_name (predication_suffixes[instance.pred]);
328 return b.finish_name ();
333 /* th_indexed_loadstore_width_def class. */
334 struct th_indexed_loadstore_width_def : public function_shape
336 void build (function_builder &b,
337 const function_group_info &group) const override
339 for (unsigned int pred_idx = 0; group.preds[pred_idx] != NUM_PRED_TYPES;
340 ++pred_idx)
342 for (unsigned int vec_type_idx = 0;
343 group.ops_infos.types[vec_type_idx].index != NUM_VECTOR_TYPES;
344 ++vec_type_idx)
346 tree index_type = group.ops_infos.args[1].get_tree_type (
347 group.ops_infos.types[vec_type_idx].index);
348 if (!index_type)
349 continue;
350 build_th_loadstore (b, group, pred_idx, vec_type_idx);
355 char *get_name (function_builder &b, const function_instance &instance,
356 bool overloaded_p) const override
359 /* Return nullptr if it can not be overloaded. */
360 if (overloaded_p && !instance.base->can_be_overloaded_p (instance.pred))
361 return nullptr;
363 b.append_name ("__riscv_th_");
364 b.append_name (instance.base_name);
365 /* vop_v --> vop_v_<type>. */
366 if (!overloaded_p)
368 /* vop --> vop_v. */
369 b.append_name (operand_suffixes[instance.op_info->op]);
370 /* vop_v --> vop_v_<type>. */
371 b.append_name (type_suffixes[instance.type.index].vector);
374 /* According to rvv-intrinsic-doc, it does not add "_m" suffix
375 for vop_m C++ overloaded API. */
376 if (overloaded_p && instance.pred == PRED_TYPE_m)
377 return b.finish_name ();
378 b.append_name (predication_suffixes[instance.pred]);
379 return b.finish_name ();
383 /* alu_def class. */
384 struct alu_def : public build_base
386 char *get_name (function_builder &b, const function_instance &instance,
387 bool overloaded_p) const override
389 /* Return nullptr if it can not be overloaded. */
390 if (overloaded_p && !instance.base->can_be_overloaded_p (instance.pred))
391 return nullptr;
393 b.append_base_name (instance.base_name);
395 /* vop<sew>_<op> --> vop<sew>_<op>_<type>. */
396 if (!overloaded_p)
398 b.append_name (operand_suffixes[instance.op_info->op]);
399 b.append_name (type_suffixes[instance.type.index].vector);
402 /* According to rvv-intrinsic-doc, it does not add "_m" suffix
403 for vop_m C++ overloaded API. */
404 if (overloaded_p && instance.pred == PRED_TYPE_m)
405 return b.finish_name ();
406 b.append_name (predication_suffixes[instance.pred]);
407 return b.finish_name ();
410 bool check (function_checker &c) const override
412 /* Check whether rounding mode argument is a valid immediate. */
413 if (c.base->has_rounding_mode_operand_p ())
415 /* Some invalid overload intrinsic like below will have zero for
416 c.arg_num (). Thus, make sure arg_num is big enough here.
417 __riscv_vaadd () will make c.arg_num () == 0. */
418 if (!c.any_type_float_p () && c.arg_num () >= 2)
419 return c.require_immediate (c.arg_num () - 2, VXRM_RNU, VXRM_ROD);
420 /* TODO: We will support floating-point intrinsic modeling
421 rounding mode in the future. */
423 return true;
427 /* The base class for frm build. */
428 struct build_frm_base : public build_base
430 /* Normalize vf<op>_frm to vf<op>. */
431 static void normalize_base_name (char *to, const char *from, int limit)
433 strncpy (to, from, limit - 1);
434 char *suffix = strstr (to, "_frm");
436 if (suffix)
437 *suffix = '\0';
439 to[limit - 1] = '\0';
442 bool check (function_checker &c) const override
444 gcc_assert (c.any_type_float_p ());
446 /* Check whether rounding mode argument is a valid immediate.
447 Some invalid overload intrinsic like below will have zero for
448 c.arg_num (). Thus, make sure arg_num is big enough here.
449 __riscv_vaadd () will make c.arg_num () == 0. */
450 if (c.base->has_rounding_mode_operand_p () && c.arg_num () >= 2)
452 unsigned int frm_num = c.arg_num () - 2;
454 return c.require_immediate (frm_num, FRM_STATIC_MIN, FRM_STATIC_MAX);
457 return true;
461 /* alu_frm_def class. */
462 struct alu_frm_def : public build_frm_base
464 char *get_name (function_builder &b, const function_instance &instance,
465 bool overloaded_p) const override
467 char base_name[BASE_NAME_MAX_LEN] = {};
469 /* Return nullptr if it can not be overloaded. */
470 if (overloaded_p && !instance.base->can_be_overloaded_p (instance.pred))
471 return nullptr;
473 normalize_base_name (base_name, instance.base_name, sizeof (base_name));
475 b.append_base_name (base_name);
477 /* vop<sew>_<op> --> vop<sew>_<op>_<type>. */
478 if (!overloaded_p)
480 b.append_name (operand_suffixes[instance.op_info->op]);
481 b.append_name (type_suffixes[instance.type.index].vector);
484 /* According to rvv-intrinsic-doc, it does not add "_rm" suffix
485 for vop_rm C++ overloaded API. */
486 if (!overloaded_p)
487 b.append_name ("_rm");
489 /* According to rvv-intrinsic-doc, it does not add "_m" suffix
490 for vop_m C++ overloaded API. */
491 if (overloaded_p && instance.pred == PRED_TYPE_m)
492 return b.finish_name ();
494 b.append_name (predication_suffixes[instance.pred]);
496 return b.finish_name ();
500 /* widen_alu_frm_def class. */
501 struct widen_alu_frm_def : public build_frm_base
503 char *get_name (function_builder &b, const function_instance &instance,
504 bool overloaded_p) const override
506 char base_name[BASE_NAME_MAX_LEN] = {};
508 normalize_base_name (base_name, instance.base_name, sizeof (base_name));
510 b.append_base_name (base_name);
512 /* vop<sew> --> vop<sew>_<op>. */
513 b.append_name (operand_suffixes[instance.op_info->op]);
515 /* vop<sew>_<op> --> vop<sew>_<op>_<type>. */
516 if (!overloaded_p)
517 b.append_name (type_suffixes[instance.type.index].vector);
519 /* According to rvv-intrinsic-doc, it does not add "_rm" suffix
520 for vop_rm C++ overloaded API. */
521 if (!overloaded_p)
522 b.append_name ("_rm");
524 /* According to rvv-intrinsic-doc, it does not add "_m" suffix
525 for vop_m C++ overloaded API. */
526 if (overloaded_p && instance.pred == PRED_TYPE_m)
527 return b.finish_name ();
529 b.append_name (predication_suffixes[instance.pred]);
531 return b.finish_name ();
535 /* narrow_alu_frm_def class. */
536 struct narrow_alu_frm_def : public build_frm_base
538 char *get_name (function_builder &b, const function_instance &instance,
539 bool overloaded_p) const override
541 char base_name[BASE_NAME_MAX_LEN] = {};
543 normalize_base_name (base_name, instance.base_name, sizeof (base_name));
545 b.append_base_name (base_name);
547 if (!overloaded_p)
549 /* vop --> vop_<op>. */
550 b.append_name (operand_suffixes[instance.op_info->op]);
551 /* vop_<op> --> vop_<op>_<type>. */
552 vector_type_index ret_type_idx
553 = instance.op_info->ret.get_function_type_index (instance.type.index);
554 b.append_name (type_suffixes[ret_type_idx].vector);
557 /* According to rvv-intrinsic-doc, it does not add "_rm" suffix
558 for vop_rm C++ overloaded API. */
559 if (!overloaded_p)
560 b.append_name ("_rm");
562 /* According to rvv-intrinsic-doc, it does not add "_m" suffix
563 for vop_m C++ overloaded API. */
564 if (overloaded_p && instance.pred == PRED_TYPE_m)
565 return b.finish_name ();
567 b.append_name (predication_suffixes[instance.pred]);
569 return b.finish_name ();
573 /* reduc_alu_frm_def class. */
574 struct reduc_alu_frm_def : public build_frm_base
576 char *get_name (function_builder &b, const function_instance &instance,
577 bool overloaded_p) const override
579 char base_name[BASE_NAME_MAX_LEN] = {};
581 normalize_base_name (base_name, instance.base_name, sizeof (base_name));
583 b.append_base_name (base_name);
585 /* vop_<op> --> vop<sew>_<op>_<type>. */
586 if (!overloaded_p)
588 b.append_name (operand_suffixes[instance.op_info->op]);
589 b.append_name (type_suffixes[instance.type.index].vector);
590 vector_type_index ret_type_idx
591 = instance.op_info->ret.get_function_type_index (instance.type.index);
592 b.append_name (type_suffixes[ret_type_idx].vector);
595 /* According to rvv-intrinsic-doc, it does not add "_rm" suffix
596 for vop_rm C++ overloaded API. */
597 if (!overloaded_p)
598 b.append_name ("_rm");
600 /* According to rvv-intrinsic-doc, it does not add "_m" suffix
601 for vop_m C++ overloaded API. */
602 if (overloaded_p && instance.pred == PRED_TYPE_m)
603 return b.finish_name ();
605 b.append_name (predication_suffixes[instance.pred]);
607 return b.finish_name ();
611 /* widen_alu_def class. Handle vwadd/vwsub. Unlike
612 vadd.vx/vadd.vv/vwmul.vv/vwmul.vx, vwadd.vv/vwadd.vx/vwadd.wv/vwadd.wx has
613 'OP' suffix in overloaded API. */
614 struct widen_alu_def : public build_base
616 char *get_name (function_builder &b, const function_instance &instance,
617 bool overloaded_p) const override
619 b.append_base_name (instance.base_name);
621 /* vop<sew> --> vop<sew>_<op>. */
622 b.append_name (operand_suffixes[instance.op_info->op]);
624 /* vop<sew>_<op> --> vop<sew>_<op>_<type>. */
625 if (!overloaded_p)
626 b.append_name (type_suffixes[instance.type.index].vector);
628 /* According to rvv-intrinsic-doc, it does not add "_m" suffix
629 for vop_m C++ overloaded API. */
630 if (overloaded_p && instance.pred == PRED_TYPE_m)
631 return b.finish_name ();
632 b.append_name (predication_suffixes[instance.pred]);
633 return b.finish_name ();
637 /* no_mask_policy_def class. Such instructions belong to this class
638 doesn't need mask policy. */
639 struct no_mask_policy_def : public build_base
641 char *get_name (function_builder &b, const function_instance &instance,
642 bool overloaded_p) const override
644 b.append_base_name (instance.base_name);
646 if (!overloaded_p)
647 b.append_name (operand_suffixes[instance.op_info->op]);
649 /* vop<sew>_<op> --> vop<sew>_<op>_<type>. */
650 if (!overloaded_p)
651 b.append_name (type_suffixes[instance.type.index].vector);
653 b.append_name (predication_suffixes[instance.pred]);
654 return b.finish_name ();
658 /* return_mask_def class. Such instructions belong to this class
659 is returning mask value. */
660 struct return_mask_def : public build_base
662 char *get_name (function_builder &b, const function_instance &instance,
663 bool overloaded_p) const override
665 b.append_base_name (instance.base_name);
667 if (!overloaded_p)
668 b.append_name (operand_suffixes[instance.op_info->op]);
670 /* vop<sew>_<op> --> vop<sew>_<op>_<type1>_<type2>. */
671 if (!overloaded_p)
673 b.append_name (type_suffixes[instance.type.index].vector);
674 vector_type_index ret_type_idx
675 = instance.op_info->ret.get_function_type_index (instance.type.index);
676 b.append_name (type_suffixes[ret_type_idx].vector);
679 if (overloaded_p && instance.pred == PRED_TYPE_m)
680 return b.finish_name ();
681 b.append_name (predication_suffixes[instance.pred]);
682 return b.finish_name ();
686 /* narrow_alu_def class. Handle narrowing instructions like vnsrl.wv. */
687 struct narrow_alu_def : public build_base
689 char *get_name (function_builder &b, const function_instance &instance,
690 bool overloaded_p) const override
692 b.append_base_name (instance.base_name);
694 if (!overloaded_p)
696 /* vop --> vop_<op>. */
697 b.append_name (operand_suffixes[instance.op_info->op]);
698 /* vop_<op> --> vop_<op>_<type>. */
699 vector_type_index ret_type_idx
700 = instance.op_info->ret.get_function_type_index (instance.type.index);
701 b.append_name (type_suffixes[ret_type_idx].vector);
704 /* According to rvv-intrinsic-doc, it does not add "_m" suffix
705 for vop_m C++ overloaded API. */
706 if (overloaded_p && instance.pred == PRED_TYPE_m)
707 return b.finish_name ();
708 b.append_name (predication_suffixes[instance.pred]);
709 return b.finish_name ();
712 bool check (function_checker &c) const override
714 /* Check whether rounding mode argument is a valid immediate. */
715 if (c.base->has_rounding_mode_operand_p ())
717 /* Some invalid overload intrinsic like below will have zero for
718 c.arg_num (). Thus, make sure arg_num is big enough here.
719 __riscv_vaadd () will make c.arg_num () == 0. */
720 if (!c.any_type_float_p () && c.arg_num () >= 2)
721 return c.require_immediate (c.arg_num () - 2, VXRM_RNU, VXRM_ROD);
722 /* TODO: We will support floating-point intrinsic modeling
723 rounding mode in the future. */
725 return true;
729 /* move_def class. Handle vmv.v.v/vmv.v.x. */
730 struct move_def : public build_base
732 char *get_name (function_builder &b, const function_instance &instance,
733 bool overloaded_p) const override
735 /* vmv.v.x/vfmv.v.f (PRED_none) can not be overloaded. */
736 if ((instance.op_info->op == OP_TYPE_x || instance.op_info->op == OP_TYPE_f)
737 && overloaded_p && instance.pred == PRED_TYPE_none)
738 return nullptr;
740 b.append_base_name (instance.base_name);
742 if (!overloaded_p)
744 b.append_name (operand_suffixes[instance.op_info->op]);
745 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 /* mask_alu_def class. */
758 struct mask_alu_def : public build_base
760 char *get_name (function_builder &b, const function_instance &instance,
761 bool overloaded_p) const override
763 /* Return nullptr if it can not be overloaded. */
764 if (overloaded_p && !instance.base->can_be_overloaded_p (instance.pred))
765 return nullptr;
767 b.append_base_name (instance.base_name);
769 if (instance.op_info->op == OP_TYPE_mm || instance.op_info->op == OP_TYPE_m)
770 if (!overloaded_p)
771 b.append_name (operand_suffixes[instance.op_info->op]);
773 /* vop<sew>_<op> --> vop<sew>_<op>_<type>. */
774 if (!overloaded_p)
775 b.append_name (type_suffixes[instance.type.index].vector);
777 /* According to rvv-intrinsic-doc, it does not add "_m" suffix
778 for vop_m C++ overloaded API. */
779 if (overloaded_p && instance.pred == PRED_TYPE_m)
780 return b.finish_name ();
781 b.append_name (predication_suffixes[instance.pred]);
782 return b.finish_name ();
786 /* reduc_alu_def class. */
787 struct reduc_alu_def : public build_base
789 char *get_name (function_builder &b, const function_instance &instance,
790 bool overloaded_p) const override
792 b.append_base_name (instance.base_name);
794 /* vop_<op> --> vop<sew>_<op>_<type>. */
795 if (!overloaded_p)
797 b.append_name (operand_suffixes[instance.op_info->op]);
798 b.append_name (type_suffixes[instance.type.index].vector);
799 vector_type_index ret_type_idx
800 = instance.op_info->ret.get_function_type_index (instance.type.index);
801 b.append_name (type_suffixes[ret_type_idx].vector);
804 /* According to rvv-intrinsic-doc, it does not add "_m" suffix
805 for vop_m C++ overloaded API. */
806 if (overloaded_p && instance.pred == PRED_TYPE_m)
807 return b.finish_name ();
808 b.append_name (predication_suffixes[instance.pred]);
809 return b.finish_name ();
813 /* th_extract_def class. */
814 struct th_extract_def : public build_base
816 char *get_name (function_builder &b, const function_instance &instance,
817 bool overloaded_p) const override
819 b.append_name ("__riscv_th_");
820 b.append_name (instance.base_name);
822 if (overloaded_p)
823 return b.finish_name ();
824 b.append_name (type_suffixes[instance.type.index].vector);
825 b.append_name (type_suffixes[instance.type.index].scalar);
826 return b.finish_name ();
830 /* scalar_move_def class. */
831 struct scalar_move_def : public build_base
833 char *get_name (function_builder &b, const function_instance &instance,
834 bool overloaded_p) const override
836 b.append_base_name (instance.base_name);
837 if (overloaded_p)
838 return b.finish_name ();
839 b.append_name (operand_suffixes[instance.op_info->op]);
840 b.append_name (type_suffixes[instance.type.index].vector);
841 b.append_name (type_suffixes[instance.type.index].scalar);
842 return b.finish_name ();
846 /* vundefined_def class. */
847 struct vundefined_def : public build_base
849 char *get_name (function_builder &b, const function_instance &instance,
850 bool overloaded_p) const override
852 if (overloaded_p)
853 return nullptr;
854 b.append_base_name (instance.base_name);
855 b.append_name (type_suffixes[instance.type.index].vector);
856 return b.finish_name ();
860 /* misc_def class. */
861 struct misc_def : public build_base
863 char *get_name (function_builder &b, const function_instance &instance,
864 bool overloaded_p) const override
866 b.append_base_name (instance.base_name);
868 if (!overloaded_p)
870 b.append_name (operand_suffixes[instance.op_info->op]);
871 vector_type_index arg0_type_idx
872 = instance.op_info->args[0].get_function_type_index (
873 instance.type.index);
874 b.append_name (type_suffixes[arg0_type_idx].vector);
877 vector_type_index ret_type_idx
878 = instance.op_info->ret.get_function_type_index (instance.type.index);
879 b.append_name (type_suffixes[ret_type_idx].vector);
880 return b.finish_name ();
884 /* vset_def class. */
885 struct vset_def : public build_base
887 char *get_name (function_builder &b, const function_instance &instance,
888 bool overloaded_p) const override
890 b.append_base_name (instance.base_name);
892 if (!overloaded_p)
894 b.append_name (operand_suffixes[instance.op_info->op]);
895 vector_type_index arg_type_idx
896 = instance.op_info->args[2].get_function_type_index (
897 instance.type.index);
898 b.append_name (type_suffixes[arg_type_idx].vector);
900 vector_type_index ret_type_idx
901 = instance.op_info->ret.get_function_type_index (instance.type.index);
902 b.append_name (type_suffixes[ret_type_idx].vector);
904 return b.finish_name ();
907 bool check (function_checker &c) const override
909 poly_int64 outer_size = GET_MODE_SIZE (c.arg_mode (0));
910 poly_int64 inner_size = GET_MODE_SIZE (c.arg_mode (2));
911 unsigned int nvecs = exact_div (outer_size, inner_size).to_constant ();
912 return c.require_immediate (1, 0, nvecs - 1);
916 /* vget_def class. */
917 struct vget_def : public misc_def
919 bool check (function_checker &c) const override
921 poly_int64 outer_size = GET_MODE_SIZE (c.arg_mode (0));
922 poly_int64 inner_size = GET_MODE_SIZE (c.ret_mode ());
923 unsigned int nvecs = exact_div (outer_size, inner_size).to_constant ();
924 return c.require_immediate (1, 0, nvecs - 1);
928 /* vcreate_def class. */
929 struct vcreate_def : public build_base
931 void build (function_builder &b,
932 const function_group_info &group) const override
934 for (unsigned int vec_type_idx = 0;
935 group.ops_infos.types[vec_type_idx].index != NUM_VECTOR_TYPES;
936 ++vec_type_idx)
938 auto_vec<tree, 8> argument_types;
939 function_instance function_instance (group.base_name, *group.base,
940 *group.shape,
941 group.ops_infos.types[vec_type_idx],
942 group.preds[0], &group.ops_infos);
944 tree return_type = group.ops_infos.ret.get_tree_type (
945 group.ops_infos.types[vec_type_idx].index);
947 if (!return_type)
948 continue;
950 tree arg_type = function_instance.op_info->args[0].get_tree_type (
951 function_instance.type.index);
953 machine_mode outer_mode = TYPE_MODE (return_type);
954 machine_mode inner_mode = TYPE_MODE (arg_type);
955 unsigned int nargs
956 = exact_div (GET_MODE_SIZE (outer_mode), GET_MODE_SIZE (inner_mode))
957 .to_constant ();
959 for (unsigned int i = 0; i < nargs; i++)
960 argument_types.quick_push (arg_type);
962 b.add_unique_function (function_instance, (*group.shape), return_type,
963 argument_types, group.required_extensions);
967 char *get_name (function_builder &b, const function_instance &instance,
968 bool overloaded_p) const override
970 if (overloaded_p)
971 return nullptr;
972 b.append_base_name (instance.base_name);
973 b.append_name (operand_suffixes[instance.op_info->op]);
975 if (instance.op_info->ret.base_type != RVV_BASE_vector)
977 vector_type_index arg_type_idx
978 = instance.op_info->args[0].get_function_type_index (
979 instance.type.index);
980 b.append_name (type_suffixes[arg_type_idx].vector);
983 vector_type_index ret_type_idx
984 = instance.op_info->ret.get_function_type_index (instance.type.index);
985 b.append_name (type_suffixes[ret_type_idx].vector);
986 return b.finish_name ();
990 /* read_vl_def class. */
991 struct read_vl_def : public function_shape
993 void build (function_builder &b,
994 const function_group_info &group) const override
996 auto_vec<tree> argument_types;
997 b.add_unique_function (get_read_vl_instance (), (*group.shape),
998 size_type_node, argument_types,
999 group.required_extensions);
1002 char *get_name (function_builder &b, const function_instance &instance,
1003 bool overloaded_p) const override
1005 if (overloaded_p)
1006 return nullptr;
1007 b.append_base_name (instance.base_name);
1008 return b.finish_name ();
1012 /* fault_load_def class. */
1013 struct fault_load_def : public build_base
1015 char *get_name (function_builder &b, const function_instance &instance,
1016 bool overloaded_p) const override
1018 if (overloaded_p && !instance.base->can_be_overloaded_p (instance.pred))
1019 return nullptr;
1020 tree type = builtin_types[instance.type.index].vector;
1021 machine_mode mode = TYPE_MODE (type);
1022 int sew = GET_MODE_BITSIZE (GET_MODE_INNER (mode));
1023 b.append_name ("__riscv_");
1024 b.append_name ("vle");
1025 b.append_sew (sew);
1026 b.append_name ("ff");
1028 /* vop<sew>_v --> vop<sew>_v_<type>. */
1029 if (!overloaded_p)
1031 /* vop<sew> --> vop<sew>_v. */
1032 b.append_name (operand_suffixes[instance.op_info->op]);
1033 /* vop<sew>_v --> vop<sew>_v_<type>. */
1034 b.append_name (type_suffixes[instance.type.index].vector);
1037 /* According to rvv-intrinsic-doc, it does not add "_m" suffix
1038 for vop_m C++ overloaded API. */
1039 if (overloaded_p && instance.pred == PRED_TYPE_m)
1040 return b.finish_name ();
1041 b.append_name (predication_suffixes[instance.pred]);
1042 return b.finish_name ();
1046 /* vlenb_def class. */
1047 struct vlenb_def : public function_shape
1049 void build (function_builder &b,
1050 const function_group_info &group) const override
1052 auto_vec<tree> argument_types;
1053 function_instance function_instance (group.base_name, *group.base,
1054 *group.shape, group.ops_infos.types[0],
1055 group.preds[0], &group.ops_infos);
1056 b.add_unique_function (function_instance, (*group.shape),
1057 long_unsigned_type_node, argument_types,
1058 group.required_extensions);
1061 char *get_name (function_builder &b, const function_instance &instance,
1062 bool overloaded_p) const override
1064 if (overloaded_p)
1065 return nullptr;
1066 b.append_base_name (instance.base_name);
1067 return b.finish_name ();
1071 /* seg_loadstore_def class. */
1072 struct seg_loadstore_def : public build_base
1074 char *get_name (function_builder &b, const function_instance &instance,
1075 bool overloaded_p) const override
1077 /* Return nullptr if it can not be overloaded. */
1078 if (overloaded_p && !instance.base->can_be_overloaded_p (instance.pred))
1079 return nullptr;
1081 b.append_base_name (instance.base_name);
1083 tree type = builtin_types[instance.type.index].vector;
1084 machine_mode mode = TYPE_MODE (type);
1086 int nf = get_nf (mode);
1087 /* vop --> vop<nf>. */
1088 b.append_nf (nf);
1090 /* vop<nf> --> vop<nf>e. */
1091 b.append_name ("e");
1093 int sew = GET_MODE_BITSIZE (GET_MODE_INNER (mode));
1094 /* vop<nf>e --> vop<nf>e<sew>. */
1095 b.append_sew (sew);
1097 if (!overloaded_p)
1099 /* vop<nf>e<sew> --> vop<nf>e<sew>_v. */
1100 b.append_name (operand_suffixes[instance.op_info->op]);
1101 /* vop<nf>e<sew>_v --> vop<nf>e<sew>_v_<type>. */
1102 b.append_name (type_suffixes[instance.type.index].vector);
1105 /* According to rvv-intrinsic-doc, it does not add "_m" suffix
1106 for vop_m C++ overloaded API. */
1107 if (overloaded_p && instance.pred == PRED_TYPE_m)
1108 return b.finish_name ();
1109 b.append_name (predication_suffixes[instance.pred]);
1110 return b.finish_name ();
1114 /* seg_indexed_loadstore_def class. */
1115 struct seg_indexed_loadstore_def : public indexed_loadstore_def
1117 char *get_name (function_builder &b, const function_instance &instance,
1118 bool overloaded_p) const override
1120 /* Return nullptr if it can not be overloaded. */
1121 if (overloaded_p && !instance.base->can_be_overloaded_p (instance.pred))
1122 return nullptr;
1124 b.append_base_name (instance.base_name);
1126 tree type = builtin_types[instance.type.index].vector;
1127 machine_mode mode = TYPE_MODE (type);
1129 int nf = get_nf (mode);
1130 /* vop --> vop<nf>. */
1131 b.append_nf (nf);
1133 /* vop<nf> --> vop<nf>ei. */
1134 b.append_name ("ei");
1136 /* vop<nf>ei --> vop<nf>ei<eew>. */
1137 vector_type_index arg1_type_idx
1138 = instance.op_info->args[1].get_function_type_index (instance.type.index);
1139 tree index_type = builtin_types[arg1_type_idx].vector;
1140 machine_mode index_mode = TYPE_MODE (index_type);
1141 int eew = GET_MODE_BITSIZE (GET_MODE_INNER (index_mode));
1142 b.append_sew (eew);
1144 if (!overloaded_p)
1146 /* vop<sew> --> vop<sew>_v. */
1147 b.append_name (operand_suffixes[instance.op_info->op]);
1148 /* vop<sew>_v --> vop<sew>_v_<type>. */
1149 b.append_name (type_suffixes[instance.type.index].vector);
1152 /* According to rvv-intrinsic-doc, it does not add "_m" suffix
1153 for vop_m C++ overloaded API. */
1154 if (overloaded_p && instance.pred == PRED_TYPE_m)
1155 return b.finish_name ();
1156 b.append_name (predication_suffixes[instance.pred]);
1157 return b.finish_name ();
1161 /* seg_fault_load_def class. */
1162 struct seg_fault_load_def : public build_base
1164 char *get_name (function_builder &b, const function_instance &instance,
1165 bool overloaded_p) const override
1167 /* Return nullptr if it can not be overloaded. */
1168 if (overloaded_p && !instance.base->can_be_overloaded_p (instance.pred))
1169 return nullptr;
1171 b.append_name ("__riscv_vlseg");
1173 tree type = builtin_types[instance.type.index].vector;
1174 machine_mode mode = TYPE_MODE (type);
1176 int nf = get_nf (mode);
1177 /* vop --> vop<nf>. */
1178 b.append_nf (nf);
1180 /* vop<nf> --> vop<nf>e. */
1181 b.append_name ("e");
1183 int sew = GET_MODE_BITSIZE (GET_MODE_INNER (mode));
1184 /* vop<nf>e --> vop<nf>e<sew>. */
1185 b.append_sew (sew);
1187 /* vop<nf>e<sew> --> vop<nf>e<sew>ff. */
1188 b.append_name ("ff");
1190 if (!overloaded_p)
1192 /* vop<nf>e<sew>ff --> vop<nf>e<sew>ff_v. */
1193 b.append_name (operand_suffixes[instance.op_info->op]);
1194 /* vop<nf>e<sew>ff_v --> vop<nf>e<sew>ff_v_<type>. */
1195 b.append_name (type_suffixes[instance.type.index].vector);
1198 /* According to rvv-intrinsic-doc, it does not add "_m" suffix
1199 for vop_m C++ overloaded API. */
1200 if (overloaded_p && instance.pred == PRED_TYPE_m)
1201 return b.finish_name ();
1202 b.append_name (predication_suffixes[instance.pred]);
1203 return b.finish_name ();
1207 /* vsm4r/vaes* class. */
1208 struct crypto_vv_def : public build_base
1210 char *get_name (function_builder &b, const function_instance &instance,
1211 bool overloaded_p) const override
1213 /* Return nullptr if it can not be overloaded. */
1214 if (overloaded_p && !instance.base->can_be_overloaded_p (instance.pred))
1215 return nullptr;
1216 b.append_base_name (instance.base_name);
1217 b.append_name (operand_suffixes[instance.op_info->op]);
1219 if (!overloaded_p)
1221 if (instance.op_info->op == OP_TYPE_vv)
1222 b.append_name (type_suffixes[instance.type.index].vector);
1223 else
1225 vector_type_index arg0_type_idx
1226 = instance.op_info->args[1].get_function_type_index
1227 (instance.type.index);
1228 b.append_name (type_suffixes[arg0_type_idx].vector);
1229 vector_type_index ret_type_idx
1230 = instance.op_info->ret.get_function_type_index
1231 (instance.type.index);
1232 b.append_name (type_suffixes[ret_type_idx].vector);
1236 b.append_name (predication_suffixes[instance.pred]);
1237 return b.finish_name ();
1241 /* vaeskf1/vaeskf2/vsm4k/vsm3c class. */
1242 struct crypto_vi_def : public build_base
1244 char *get_name (function_builder &b, const function_instance &instance,
1245 bool overloaded_p) const override
1247 /* Return nullptr if it can not be overloaded. */
1248 if (overloaded_p && !instance.base->can_be_overloaded_p (instance.pred))
1249 return nullptr;
1250 b.append_base_name (instance.base_name);
1251 if (!overloaded_p)
1253 b.append_name (operand_suffixes[instance.op_info->op]);
1254 b.append_name (type_suffixes[instance.type.index].vector);
1256 b.append_name (predication_suffixes[instance.pred]);
1257 return b.finish_name ();
1261 /* vaesz class. */
1262 struct crypto_vv_no_op_type_def : public build_base
1264 char *get_name (function_builder &b, const function_instance &instance,
1265 bool overloaded_p) const override
1267 /* Return nullptr if it can not be overloaded. */
1268 if (overloaded_p && !instance.base->can_be_overloaded_p (instance.pred))
1269 return nullptr;
1270 b.append_base_name (instance.base_name);
1272 if (!overloaded_p)
1274 b.append_name (operand_suffixes[instance.op_info->op]);
1275 vector_type_index arg0_type_idx
1276 = instance.op_info->args[1].get_function_type_index
1277 (instance.type.index);
1278 b.append_name (type_suffixes[arg0_type_idx].vector);
1279 vector_type_index ret_type_idx
1280 = instance.op_info->ret.get_function_type_index
1281 (instance.type.index);
1282 b.append_name (type_suffixes[ret_type_idx].vector);
1285 b.append_name (predication_suffixes[instance.pred]);
1286 return b.finish_name ();
1290 SHAPE(vsetvl, vsetvl)
1291 SHAPE(vsetvl, vsetvlmax)
1292 SHAPE(loadstore, loadstore)
1293 SHAPE(indexed_loadstore, indexed_loadstore)
1294 SHAPE(th_loadstore_width, th_loadstore_width)
1295 SHAPE(th_indexed_loadstore_width, th_indexed_loadstore_width)
1296 SHAPE(alu, alu)
1297 SHAPE(alu_frm, alu_frm)
1298 SHAPE(widen_alu, widen_alu)
1299 SHAPE(widen_alu_frm, widen_alu_frm)
1300 SHAPE(no_mask_policy, no_mask_policy)
1301 SHAPE(return_mask, return_mask)
1302 SHAPE(narrow_alu, narrow_alu)
1303 SHAPE(narrow_alu_frm, narrow_alu_frm)
1304 SHAPE(move, move)
1305 SHAPE(mask_alu, mask_alu)
1306 SHAPE(reduc_alu, reduc_alu)
1307 SHAPE(reduc_alu_frm, reduc_alu_frm)
1308 SHAPE(th_extract, th_extract)
1309 SHAPE(scalar_move, scalar_move)
1310 SHAPE(vundefined, vundefined)
1311 SHAPE(misc, misc)
1312 SHAPE(vset, vset)
1313 SHAPE(vget, vget)
1314 SHAPE(vcreate, vcreate)
1315 SHAPE(read_vl, read_vl)
1316 SHAPE(fault_load, fault_load)
1317 SHAPE(vlenb, vlenb)
1318 SHAPE(seg_loadstore, seg_loadstore)
1319 SHAPE(seg_indexed_loadstore, seg_indexed_loadstore)
1320 SHAPE(seg_fault_load, seg_fault_load)
1321 SHAPE(crypto_vv, crypto_vv)
1322 SHAPE(crypto_vi, crypto_vi)
1323 SHAPE(crypto_vv_no_op_type, crypto_vv_no_op_type)
1324 } // end namespace riscv_vector