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)
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/>. */
23 #include "coretypes.h"
29 #include "insn-codes.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. */
40 check_type (tree return_type
, vec
<tree
> &argument_types
)
48 FOR_EACH_VEC_ELT (argument_types
, i
, arg
)
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. */
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
,
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
))
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 */
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
)
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
)
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
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
;
115 for (unsigned int vec_type_idx
= 0;
116 group
.ops_infos
.types
[vec_type_idx
].index
!= NUM_VECTOR_TYPES
;
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. */
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
))
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
)
176 /* vop<sew>_v --> vop<sew>_v_<type>. */
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
;
203 for (unsigned int vec_type_idx
= 0;
204 group
.ops_infos
.types
[vec_type_idx
].index
!= NUM_VECTOR_TYPES
;
207 tree index_type
= group
.ops_infos
.args
[1].get_tree_type (
208 group
.ops_infos
.types
[vec_type_idx
].index
);
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
))
223 b
.append_base_name (instance
.base_name
);
224 /* vop<sew>_v --> vop<sew>_v_<type>. */
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. */
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
,
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
))
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
)))
267 if (strstr (group
.base_name
, "l")
268 && !strstr (group
.base_name
, "u")
269 && TYPE_UNSIGNED (TREE_TYPE (type
)))
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)
277 if (strstr (group
.base_name
, "w") && (sew
== 8 || sew
==16))
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
;
295 for (unsigned int vec_type_idx
= 0;
296 group
.ops_infos
.types
[vec_type_idx
].index
!= NUM_VECTOR_TYPES
;
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
))
311 b
.append_name ("__riscv_th_");
312 b
.append_name (instance
.base_name
);
314 /* vop_v --> vop_v_<type>. */
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
;
342 for (unsigned int vec_type_idx
= 0;
343 group
.ops_infos
.types
[vec_type_idx
].index
!= NUM_VECTOR_TYPES
;
346 tree index_type
= group
.ops_infos
.args
[1].get_tree_type (
347 group
.ops_infos
.types
[vec_type_idx
].index
);
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
))
363 b
.append_name ("__riscv_th_");
364 b
.append_name (instance
.base_name
);
365 /* vop_v --> vop_v_<type>. */
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 ();
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
))
393 b
.append_base_name (instance
.base_name
);
395 /* vop<sew>_<op> --> vop<sew>_<op>_<type>. */
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. */
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");
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
);
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
))
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>. */
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. */
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>. */
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. */
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
);
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. */
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>. */
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. */
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>. */
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
);
647 b
.append_name (operand_suffixes
[instance
.op_info
->op
]);
649 /* vop<sew>_<op> --> vop<sew>_<op>_<type>. */
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
);
668 b
.append_name (operand_suffixes
[instance
.op_info
->op
]);
670 /* vop<sew>_<op> --> vop<sew>_<op>_<type1>_<type2>. */
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
);
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. */
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
)
740 b
.append_base_name (instance
.base_name
);
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
))
767 b
.append_base_name (instance
.base_name
);
769 if (instance
.op_info
->op
== OP_TYPE_mm
|| instance
.op_info
->op
== OP_TYPE_m
)
771 b
.append_name (operand_suffixes
[instance
.op_info
->op
]);
773 /* vop<sew>_<op> --> vop<sew>_<op>_<type>. */
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>. */
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
);
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
);
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
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
);
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
);
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
;
938 auto_vec
<tree
, 8> argument_types
;
939 function_instance
function_instance (group
.base_name
, *group
.base
,
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
);
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
);
956 = exact_div (GET_MODE_SIZE (outer_mode
), GET_MODE_SIZE (inner_mode
))
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
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
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
))
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");
1026 b
.append_name ("ff");
1028 /* vop<sew>_v --> vop<sew>_v_<type>. */
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
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
))
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>. */
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>. */
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
))
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>. */
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
));
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
))
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>. */
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>. */
1187 /* vop<nf>e<sew> --> vop<nf>e<sew>ff. */
1188 b
.append_name ("ff");
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
))
1216 b
.append_base_name (instance
.base_name
);
1217 b
.append_name (operand_suffixes
[instance
.op_info
->op
]);
1221 if (instance
.op_info
->op
== OP_TYPE_vv
)
1222 b
.append_name (type_suffixes
[instance
.type
.index
].vector
);
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
))
1250 b
.append_base_name (instance
.base_name
);
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 ();
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
))
1270 b
.append_base_name (instance
.base_name
);
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
)
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
)
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
)
1314 SHAPE(vcreate
, vcreate
)
1315 SHAPE(read_vl
, read_vl
)
1316 SHAPE(fault_load
, fault_load
)
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