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 b
.add_unique_function (function_instance
, (*group
.shape
), return_type
,
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
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
;
90 for (unsigned int vec_type_idx
= 0;
91 group
.ops_infos
.types
[vec_type_idx
].index
!= NUM_VECTOR_TYPES
;
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. */
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
))
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
)
148 /* vop<sew>_v --> vop<sew>_v_<type>. */
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
;
175 for (unsigned int vec_type_idx
= 0;
176 group
.ops_infos
.types
[vec_type_idx
].index
!= NUM_VECTOR_TYPES
;
179 tree index_type
= group
.ops_infos
.args
[1].get_tree_type (
180 group
.ops_infos
.types
[vec_type_idx
].index
);
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
))
195 b
.append_base_name (instance
.base_name
);
196 /* vop<sew>_v --> vop<sew>_v_<type>. */
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. */
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
,
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
))
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
)))
239 if (strstr (group
.base_name
, "l")
240 && !strstr (group
.base_name
, "u")
241 && TYPE_UNSIGNED (TREE_TYPE (type
)))
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)
249 if (strstr (group
.base_name
, "w") && (sew
== 8 || sew
==16))
252 b
.add_overloaded_function (function_instance
, *group
.shape
);
253 b
.add_unique_function (function_instance
, (*group
.shape
), return_type
,
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
;
266 for (unsigned int vec_type_idx
= 0;
267 group
.ops_infos
.types
[vec_type_idx
].index
!= NUM_VECTOR_TYPES
;
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
))
282 b
.append_name ("__riscv_th_");
283 b
.append_name (instance
.base_name
);
285 /* vop_v --> vop_v_<type>. */
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
;
313 for (unsigned int vec_type_idx
= 0;
314 group
.ops_infos
.types
[vec_type_idx
].index
!= NUM_VECTOR_TYPES
;
317 tree index_type
= group
.ops_infos
.args
[1].get_tree_type (
318 group
.ops_infos
.types
[vec_type_idx
].index
);
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
))
334 b
.append_name ("__riscv_th_");
335 b
.append_name (instance
.base_name
);
336 /* vop_v --> vop_v_<type>. */
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 ();
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
))
364 b
.append_base_name (instance
.base_name
);
366 /* vop<sew>_<op> --> vop<sew>_<op>_<type>. */
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. */
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");
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
);
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
))
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>. */
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. */
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>. */
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. */
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
);
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. */
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>. */
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. */
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>. */
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
);
618 b
.append_name (operand_suffixes
[instance
.op_info
->op
]);
620 /* vop<sew>_<op> --> vop<sew>_<op>_<type>. */
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
);
639 b
.append_name (operand_suffixes
[instance
.op_info
->op
]);
641 /* vop<sew>_<op> --> vop<sew>_<op>_<type1>_<type2>. */
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
);
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. */
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
)
711 b
.append_base_name (instance
.base_name
);
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
))
738 b
.append_base_name (instance
.base_name
);
740 if (instance
.op_info
->op
== OP_TYPE_mm
|| instance
.op_info
->op
== OP_TYPE_m
)
742 b
.append_name (operand_suffixes
[instance
.op_info
->op
]);
744 /* vop<sew>_<op> --> vop<sew>_<op>_<type>. */
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>. */
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
);
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
);
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
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
);
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
);
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
;
909 auto_vec
<tree
, 8> argument_types
;
910 function_instance
function_instance (group
.base_name
, *group
.base
,
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
);
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
);
927 = exact_div (GET_MODE_SIZE (outer_mode
), GET_MODE_SIZE (inner_mode
))
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
,
938 char *get_name (function_builder
&b
, const function_instance
&instance
,
939 bool overloaded_p
) const override
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
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
))
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");
996 b
.append_name ("ff");
998 /* vop<sew>_v --> vop<sew>_v_<type>. */
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
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
))
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>. */
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>. */
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
))
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>. */
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
));
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
))
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>. */
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>. */
1156 /* vop<nf>e<sew> --> vop<nf>e<sew>ff. */
1157 b
.append_name ("ff");
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
))
1185 b
.append_base_name (instance
.base_name
);
1186 b
.append_name (operand_suffixes
[instance
.op_info
->op
]);
1190 if (instance
.op_info
->op
== OP_TYPE_vv
)
1191 b
.append_name (type_suffixes
[instance
.type
.index
].vector
);
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
))
1219 b
.append_base_name (instance
.base_name
);
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 ();
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
))
1239 b
.append_base_name (instance
.base_name
);
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
)
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
)
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
)
1283 SHAPE(vcreate
, vcreate
)
1284 SHAPE(read_vl
, read_vl
)
1285 SHAPE(fault_load
, fault_load
)
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