/* function_base implementation for RISC-V 'V' Extension for GNU compiler. Copyright (C) 2022-2023 Free Software Foundation, Inc. Contributed by Ju-Zhe Zhong (juzhe.zhong@rivai.ai), RiVAI Technologies Ltd. This file is part of GCC. GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GCC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GCC; see the file COPYING3. If not see . */ #include "config.h" #include "system.h" #include "coretypes.h" #include "tm.h" #include "tree.h" #include "rtl.h" #include "tm_p.h" #include "memmodel.h" #include "insn-codes.h" #include "optabs.h" #include "recog.h" #include "expr.h" #include "basic-block.h" #include "function.h" #include "fold-const.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimplify.h" #include "explow.h" #include "emit-rtl.h" #include "tree-vector-builder.h" #include "rtx-vector-builder.h" #include "riscv-vector-builtins.h" #include "riscv-vector-builtins-shapes.h" #include "riscv-vector-builtins-bases.h" using namespace riscv_vector; namespace riscv_vector { /* Enumerates types of loads/stores operations. It's only used in here so we don't define it in riscv-vector-builtins-bases.h. */ enum lst_type { LST_UNIT_STRIDE, LST_STRIDED, LST_INDEXED, }; /* Helper function to fold vleff and vlsegff. */ static gimple * fold_fault_load (gimple_folder &f) { /* fold fault_load (const *base, size_t *new_vl, size_t vl) ====> fault_load (const *base, size_t vl) new_vl = MEM_REF[read_vl ()]. */ auto_vec vargs (gimple_call_num_args (f.call) - 1); for (unsigned i = 0; i < gimple_call_num_args (f.call); i++) { /* Exclude size_t *new_vl argument. */ if (i == gimple_call_num_args (f.call) - 2) continue; vargs.quick_push (gimple_call_arg (f.call, i)); } gimple *repl = gimple_build_call_vec (gimple_call_fn (f.call), vargs); gimple_call_set_lhs (repl, f.lhs); /* Handle size_t *new_vl by read_vl. */ tree new_vl = gimple_call_arg (f.call, gimple_call_num_args (f.call) - 2); if (integer_zerop (new_vl)) { /* This case happens when user passes the nullptr to new_vl argument. In this case, we just need to ignore the new_vl argument and return fault_load instruction directly. */ return repl; } tree tmp_var = create_tmp_var (size_type_node, "new_vl"); tree decl = get_read_vl_decl (); gimple *g = gimple_build_call (decl, 0); gimple_call_set_lhs (g, tmp_var); tree indirect = fold_build2 (MEM_REF, size_type_node, gimple_call_arg (f.call, gimple_call_num_args (f.call) - 2), build_int_cst (build_pointer_type (size_type_node), 0)); gassign *assign = gimple_build_assign (indirect, tmp_var); gsi_insert_after (f.gsi, assign, GSI_SAME_STMT); gsi_insert_after (f.gsi, g, GSI_SAME_STMT); return repl; } /* Implements vsetvl && vsetvlmax. */ template class vsetvl : public function_base { public: bool apply_vl_p () const override { return false; } rtx expand (function_expander &e) const override { if (VLMAX_P) e.add_input_operand (Pmode, gen_rtx_REG (Pmode, 0)); else e.add_input_operand (0); tree type = builtin_types[e.type.index].vector; machine_mode mode = TYPE_MODE (type); machine_mode inner_mode = GET_MODE_INNER (mode); /* SEW. */ e.add_input_operand (Pmode, gen_int_mode (GET_MODE_BITSIZE (inner_mode), Pmode)); /* LMUL. */ e.add_input_operand (Pmode, gen_int_mode (get_vlmul (mode), Pmode)); /* TA. */ e.add_input_operand (Pmode, gen_int_mode (1, Pmode)); /* MU. */ e.add_input_operand (Pmode, gen_int_mode (0, Pmode)); return e.generate_insn (code_for_vsetvl_no_side_effects (Pmode)); } }; /* Implements * vle.v/vse.v/vlm.v/vsm.v/vlse.v/vsse.v/vluxei.v/vloxei.v/vsuxei.v/vsoxei.v * codegen. */ template class loadstore : public function_base { public: bool apply_tail_policy_p () const override { return !STORE_P; } bool apply_mask_policy_p () const override { return !STORE_P; } unsigned int call_properties (const function_instance &) const override { if (STORE_P) return CP_WRITE_MEMORY; else return CP_READ_MEMORY; } bool can_be_overloaded_p (enum predication_type_index pred) const override { if (STORE_P || LST_TYPE == LST_INDEXED) return true; return pred != PRED_TYPE_none; } rtx expand (function_expander &e) const override { if (LST_TYPE == LST_INDEXED) { int unspec = ORDERED_P ? UNSPEC_ORDERED : UNSPEC_UNORDERED; if (STORE_P) return e.use_exact_insn ( code_for_pred_indexed_store (unspec, e.vector_mode (), e.index_mode ())); else { unsigned src_eew_bitsize = GET_MODE_BITSIZE (GET_MODE_INNER (e.index_mode ())); unsigned dst_eew_bitsize = GET_MODE_BITSIZE (GET_MODE_INNER (e.vector_mode ())); if (dst_eew_bitsize == src_eew_bitsize) return e.use_exact_insn ( code_for_pred_indexed_load_same_eew (unspec, e.vector_mode ())); else if (dst_eew_bitsize > src_eew_bitsize) { unsigned factor = dst_eew_bitsize / src_eew_bitsize; switch (factor) { case 2: return e.use_exact_insn ( code_for_pred_indexed_load_x2_greater_eew ( unspec, e.vector_mode ())); case 4: return e.use_exact_insn ( code_for_pred_indexed_load_x4_greater_eew ( unspec, e.vector_mode ())); case 8: return e.use_exact_insn ( code_for_pred_indexed_load_x8_greater_eew ( unspec, e.vector_mode ())); default: gcc_unreachable (); } } else { unsigned factor = src_eew_bitsize / dst_eew_bitsize; switch (factor) { case 2: return e.use_exact_insn ( code_for_pred_indexed_load_x2_smaller_eew ( unspec, e.vector_mode ())); case 4: return e.use_exact_insn ( code_for_pred_indexed_load_x4_smaller_eew ( unspec, e.vector_mode ())); case 8: return e.use_exact_insn ( code_for_pred_indexed_load_x8_smaller_eew ( unspec, e.vector_mode ())); default: gcc_unreachable (); } } } } else if (LST_TYPE == LST_STRIDED) { if (STORE_P) return e.use_contiguous_store_insn ( code_for_pred_strided_store (e.vector_mode ())); else return e.use_contiguous_load_insn ( code_for_pred_strided_load (e.vector_mode ())); } else { if (STORE_P) return e.use_contiguous_store_insn ( code_for_pred_store (e.vector_mode ())); else return e.use_contiguous_load_insn ( code_for_pred_mov (e.vector_mode ())); } } }; /* Implements vadd/vsub/vand/vor/vxor/vsll/vsra/vsrl/ vmin/vmax/vminu/vmaxu/vdiv/vrem/vdivu/ vremu/vsadd/vsaddu/vssub/vssubu vfadd/vfsub/ */ template class binop : public function_base { public: bool has_rounding_mode_operand_p () const override { return CODE == SS_PLUS || CODE == SS_MINUS || CODE == US_PLUS || CODE == US_MINUS; } rtx expand (function_expander &e) const override { switch (e.op_info->op) { case OP_TYPE_vx: case OP_TYPE_vf: return e.use_exact_insn (code_for_pred_scalar (CODE, e.vector_mode ())); case OP_TYPE_vv: return e.use_exact_insn (code_for_pred (CODE, e.vector_mode ())); default: gcc_unreachable (); } } }; /* Implements vrsub. */ class vrsub : public function_base { public: rtx expand (function_expander &e) const override { return e.use_exact_insn ( code_for_pred_sub_reverse_scalar (e.vector_mode ())); } }; /* Implements vneg/vnot. */ template class unop : public function_base { public: rtx expand (function_expander &e) const override { return e.use_exact_insn (code_for_pred (CODE, e.vector_mode ())); } }; /* Implements vsext.vf2/vsext.vf4/vsext.vf8/vzext.vf2/vzext.vf4/vzext.vf8. */ template class ext : public function_base { public: rtx expand (function_expander &e) const override { switch (e.op_info->op) { case OP_TYPE_vf2: return e.use_exact_insn (code_for_pred_vf2 (CODE, e.vector_mode ())); case OP_TYPE_vf4: return e.use_exact_insn (code_for_pred_vf4 (CODE, e.vector_mode ())); case OP_TYPE_vf8: return e.use_exact_insn (code_for_pred_vf8 (CODE, e.vector_mode ())); default: gcc_unreachable (); } } }; /* Implements vmulh/vmulhu/vmulhsu. */ template class vmulh : public function_base { public: rtx expand (function_expander &e) const override { switch (e.op_info->op) { case OP_TYPE_vx: return e.use_exact_insn ( code_for_pred_mulh_scalar (UNSPEC, e.vector_mode ())); case OP_TYPE_vv: return e.use_exact_insn ( code_for_pred_mulh (UNSPEC, e.vector_mode ())); default: gcc_unreachable (); } } }; /* Implements vwadd/vwsub/vwmul/vfwadd/vfwsub/vfwmul. */ template class widen_binop : public function_base { public: rtx expand (function_expander &e) const override { switch (e.op_info->op) { case OP_TYPE_vv: return e.use_exact_insn ( code_for_pred_dual_widen (CODE1, CODE2, e.vector_mode ())); case OP_TYPE_vx: return e.use_exact_insn ( code_for_pred_dual_widen_scalar (CODE1, CODE2, e.vector_mode ())); case OP_TYPE_wv: if (CODE1 == PLUS) return e.use_exact_insn ( code_for_pred_single_widen_add (CODE2, e.vector_mode ())); else return e.use_exact_insn ( code_for_pred_single_widen_sub (CODE2, e.vector_mode ())); case OP_TYPE_wx: return e.use_exact_insn ( code_for_pred_single_widen_scalar (CODE1, CODE2, e.vector_mode ())); default: gcc_unreachable (); } } }; template class widen_binop : public function_base { public: rtx expand (function_expander &e) const override { switch (e.op_info->op) { case OP_TYPE_vv: return e.use_exact_insn ( code_for_pred_dual_widen (CODE, e.vector_mode ())); case OP_TYPE_vf: return e.use_exact_insn ( code_for_pred_dual_widen_scalar (CODE, e.vector_mode ())); case OP_TYPE_wv: return e.use_exact_insn ( code_for_pred_single_widen (CODE, e.vector_mode ())); case OP_TYPE_wf: return e.use_exact_insn ( code_for_pred_single_widen_scalar (CODE, e.vector_mode ())); default: gcc_unreachable (); } } }; /* Implements vwmulsu. */ class vwmulsu : public function_base { public: rtx expand (function_expander &e) const override { switch (e.op_info->op) { case OP_TYPE_vv: return e.use_exact_insn (code_for_pred_widen_mulsu (e.vector_mode ())); case OP_TYPE_vx: return e.use_exact_insn ( code_for_pred_widen_mulsu_scalar (e.vector_mode ())); default: gcc_unreachable (); } } }; /* Implements vwcvt. */ template class vwcvt : public function_base { public: rtx expand (function_expander &e) const override { return e.use_exact_insn (code_for_pred (CODE, e.vector_mode ())); } }; /* Implements vadc. */ class vadc : public function_base { public: bool apply_mask_policy_p () const override { return false; } bool use_mask_predication_p () const override { return false; } rtx expand (function_expander &e) const override { switch (e.op_info->op) { case OP_TYPE_vvm: return e.use_exact_insn (code_for_pred_adc (e.vector_mode ())); case OP_TYPE_vxm: return e.use_exact_insn (code_for_pred_adc_scalar (e.vector_mode ())); default: gcc_unreachable (); } } }; /* Implements vsbc. */ class vsbc : public function_base { public: bool apply_mask_policy_p () const override { return false; } bool use_mask_predication_p () const override { return false; } rtx expand (function_expander &e) const override { switch (e.op_info->op) { case OP_TYPE_vvm: return e.use_exact_insn (code_for_pred_sbc (e.vector_mode ())); case OP_TYPE_vxm: return e.use_exact_insn (code_for_pred_sbc_scalar (e.vector_mode ())); default: gcc_unreachable (); } } }; /* Implements vmadc. */ class vmadc : public function_base { public: bool apply_tail_policy_p () const override { return false; } bool apply_mask_policy_p () const override { return false; } bool use_mask_predication_p () const override { return false; } bool has_merge_operand_p () const override { return false; } rtx expand (function_expander &e) const override { switch (e.op_info->op) { case OP_TYPE_vvm: return e.use_exact_insn (code_for_pred_madc (e.vector_mode ())); case OP_TYPE_vxm: return e.use_exact_insn (code_for_pred_madc_scalar (e.vector_mode ())); case OP_TYPE_vv: return e.use_exact_insn ( code_for_pred_madc_overflow (e.vector_mode ())); case OP_TYPE_vx: return e.use_exact_insn ( code_for_pred_madc_overflow_scalar (e.vector_mode ())); default: gcc_unreachable (); } } }; /* Implements vmsbc. */ class vmsbc : public function_base { public: bool apply_tail_policy_p () const override { return false; } bool apply_mask_policy_p () const override { return false; } bool use_mask_predication_p () const override { return false; } bool has_merge_operand_p () const override { return false; } rtx expand (function_expander &e) const override { switch (e.op_info->op) { case OP_TYPE_vvm: return e.use_exact_insn (code_for_pred_msbc (e.vector_mode ())); case OP_TYPE_vxm: return e.use_exact_insn (code_for_pred_msbc_scalar (e.vector_mode ())); case OP_TYPE_vv: return e.use_exact_insn ( code_for_pred_msbc_overflow (e.vector_mode ())); case OP_TYPE_vx: return e.use_exact_insn ( code_for_pred_msbc_overflow_scalar (e.vector_mode ())); default: gcc_unreachable (); } } }; /* Implements vnsrl/vnsra. */ template class vnshift : public function_base { public: rtx expand (function_expander &e) const override { switch (e.op_info->op) { case OP_TYPE_wx: return e.use_exact_insn ( code_for_pred_narrow_scalar (CODE, e.vector_mode ())); case OP_TYPE_wv: return e.use_exact_insn (code_for_pred_narrow (CODE, e.vector_mode ())); default: gcc_unreachable (); } } }; /* Implements vncvt. */ class vncvt_x : public function_base { public: rtx expand (function_expander &e) const override { return e.use_exact_insn (code_for_pred_trunc (e.vector_mode ())); } }; /* Implements vmerge/vfmerge. */ class vmerge : public function_base { public: bool apply_mask_policy_p () const override { return false; } bool use_mask_predication_p () const override { return false; } rtx expand (function_expander &e) const override { switch (e.op_info->op) { case OP_TYPE_vvm: return e.use_exact_insn (code_for_pred_merge (e.vector_mode ())); case OP_TYPE_vxm: case OP_TYPE_vfm: return e.use_exact_insn (code_for_pred_merge_scalar (e.vector_mode ())); default: gcc_unreachable (); } } }; /* Implements vmv.v.x/vmv.v.v/vfmv.v.f. */ class vmv_v : public function_base { public: rtx expand (function_expander &e) const override { switch (e.op_info->op) { case OP_TYPE_v: return e.use_exact_insn (code_for_pred_mov (e.vector_mode ())); case OP_TYPE_x: case OP_TYPE_f: return e.use_exact_insn (code_for_pred_broadcast (e.vector_mode ())); default: gcc_unreachable (); } } }; /* Implements vaadd/vasub/vsmul/vssra/vssrl. */ template class sat_op : public function_base { public: bool has_rounding_mode_operand_p () const override { return true; } rtx expand (function_expander &e) const override { switch (e.op_info->op) { case OP_TYPE_vx: return e.use_exact_insn ( code_for_pred_scalar (UNSPEC, e.vector_mode ())); case OP_TYPE_vv: return e.use_exact_insn (code_for_pred (UNSPEC, e.vector_mode ())); default: gcc_unreachable (); } } }; /* Implements vnclip/vnclipu. */ template class vnclip : public function_base { public: bool has_rounding_mode_operand_p () const override { return true; } rtx expand (function_expander &e) const override { switch (e.op_info->op) { case OP_TYPE_wx: return e.use_exact_insn ( code_for_pred_narrow_clip_scalar (UNSPEC, e.vector_mode ())); case OP_TYPE_wv: return e.use_exact_insn ( code_for_pred_narrow_clip (UNSPEC, e.vector_mode ())); default: gcc_unreachable (); } } }; /* Implements vmseq/vmsne/vmslt/vmsgt/vmsle/vmsge. */ template class icmp : public function_base { public: rtx expand (function_expander &e) const override { switch (e.op_info->op) { case OP_TYPE_vx: { if (CODE == GE || CODE == GEU) return e.use_compare_insn (CODE, code_for_pred_ge_scalar ( e.vector_mode ())); else if (CODE == EQ || CODE == NE) return e.use_compare_insn (CODE, code_for_pred_eqne_scalar ( e.vector_mode ())); else return e.use_compare_insn (CODE, code_for_pred_cmp_scalar ( e.vector_mode ())); } case OP_TYPE_vv: { if (CODE == LT || CODE == LTU || CODE == GE || CODE == GEU) return e.use_compare_insn (CODE, code_for_pred_ltge (e.vector_mode ())); else return e.use_compare_insn (CODE, code_for_pred_cmp (e.vector_mode ())); } default: gcc_unreachable (); } } }; /* Implements vmacc/vnmsac/vmadd/vnmsub. */ class vmacc : public function_base { public: bool has_merge_operand_p () const override { return false; } rtx expand (function_expander &e) const override { if (e.op_info->op == OP_TYPE_vx) return e.use_ternop_insn (true, code_for_pred_mul_plus_scalar ( e.vector_mode ())); if (e.op_info->op == OP_TYPE_vv) return e.use_ternop_insn (true, code_for_pred_mul_plus (e.vector_mode ())); gcc_unreachable (); } }; class vnmsac : public function_base { public: bool has_merge_operand_p () const override { return false; } rtx expand (function_expander &e) const override { if (e.op_info->op == OP_TYPE_vx) return e.use_ternop_insn (true, code_for_pred_minus_mul_scalar ( e.vector_mode ())); if (e.op_info->op == OP_TYPE_vv) return e.use_ternop_insn (true, code_for_pred_minus_mul (e.vector_mode ())); gcc_unreachable (); } }; class vmadd : public function_base { public: bool has_merge_operand_p () const override { return false; } rtx expand (function_expander &e) const override { if (e.op_info->op == OP_TYPE_vx) return e.use_ternop_insn (false, code_for_pred_mul_plus_scalar ( e.vector_mode ())); if (e.op_info->op == OP_TYPE_vv) return e.use_ternop_insn (false, code_for_pred_mul_plus (e.vector_mode ())); gcc_unreachable (); } }; class vnmsub : public function_base { public: bool has_merge_operand_p () const override { return false; } rtx expand (function_expander &e) const override { if (e.op_info->op == OP_TYPE_vx) return e.use_ternop_insn (false, code_for_pred_minus_mul_scalar ( e.vector_mode ())); if (e.op_info->op == OP_TYPE_vv) return e.use_ternop_insn (false, code_for_pred_minus_mul (e.vector_mode ())); gcc_unreachable (); } }; /* Implements vwmacc. */ class vwmacc : public function_base { public: bool has_merge_operand_p () const override { return false; } rtx expand (function_expander &e) const override { if (e.op_info->op == OP_TYPE_vx) return e.use_widen_ternop_insn ( code_for_pred_widen_mul_plus_scalar (SIGN_EXTEND, e.vector_mode ())); if (e.op_info->op == OP_TYPE_vv) return e.use_widen_ternop_insn ( code_for_pred_widen_mul_plus (SIGN_EXTEND, e.vector_mode ())); gcc_unreachable (); } }; class vwmaccu : public function_base { public: bool has_merge_operand_p () const override { return false; } rtx expand (function_expander &e) const override { if (e.op_info->op == OP_TYPE_vx) return e.use_widen_ternop_insn ( code_for_pred_widen_mul_plus_scalar (ZERO_EXTEND, e.vector_mode ())); if (e.op_info->op == OP_TYPE_vv) return e.use_widen_ternop_insn ( code_for_pred_widen_mul_plus (ZERO_EXTEND, e.vector_mode ())); gcc_unreachable (); } }; class vwmaccsu : public function_base { public: bool has_merge_operand_p () const override { return false; } rtx expand (function_expander &e) const override { if (e.op_info->op == OP_TYPE_vx) return e.use_widen_ternop_insn ( code_for_pred_widen_mul_plussu_scalar (e.vector_mode ())); if (e.op_info->op == OP_TYPE_vv) return e.use_widen_ternop_insn ( code_for_pred_widen_mul_plussu (e.vector_mode ())); gcc_unreachable (); } }; class vwmaccus : public function_base { public: bool has_merge_operand_p () const override { return false; } rtx expand (function_expander &e) const override { return e.use_widen_ternop_insn ( code_for_pred_widen_mul_plusus_scalar (e.vector_mode ())); } }; /* Implements vmand/vmnand/vmandn/vmxor/vmor/vmnor/vmorn/vmxnor */ template class mask_logic : public function_base { public: bool apply_tail_policy_p () const override { return false; } bool apply_mask_policy_p () const override { return false; } rtx expand (function_expander &e) const override { return e.use_exact_insn (code_for_pred (CODE, e.vector_mode ())); } }; template class mask_nlogic : public function_base { public: bool apply_tail_policy_p () const override { return false; } bool apply_mask_policy_p () const override { return false; } rtx expand (function_expander &e) const override { return e.use_exact_insn (code_for_pred_n (CODE, e.vector_mode ())); } }; template class mask_notlogic : public function_base { public: bool apply_tail_policy_p () const override { return false; } bool apply_mask_policy_p () const override { return false; } rtx expand (function_expander &e) const override { return e.use_exact_insn (code_for_pred_not (CODE, e.vector_mode ())); } }; /* Implements vmmv. */ class vmmv : public function_base { public: bool apply_tail_policy_p () const override { return false; } bool apply_mask_policy_p () const override { return false; } rtx expand (function_expander &e) const override { return e.use_exact_insn (code_for_pred_mov (e.vector_mode ())); } }; /* Implements vmclr. */ class vmclr : public function_base { public: bool can_be_overloaded_p (enum predication_type_index) const override { return false; } rtx expand (function_expander &e) const override { machine_mode mode = TYPE_MODE (TREE_TYPE (e.exp)); e.add_all_one_mask_operand (mode); e.add_vundef_operand (mode); e.add_input_operand (mode, CONST0_RTX (mode)); e.add_input_operand (call_expr_nargs (e.exp) - 1); e.add_input_operand (Pmode, get_avl_type_rtx (avl_type::NONVLMAX)); return e.generate_insn (code_for_pred_mov (e.vector_mode ())); } }; /* Implements vmset. */ class vmset : public function_base { public: bool can_be_overloaded_p (enum predication_type_index) const override { return false; } rtx expand (function_expander &e) const override { machine_mode mode = TYPE_MODE (TREE_TYPE (e.exp)); e.add_all_one_mask_operand (mode); e.add_vundef_operand (mode); e.add_input_operand (mode, CONSTM1_RTX (mode)); e.add_input_operand (call_expr_nargs (e.exp) - 1); e.add_input_operand (Pmode, get_avl_type_rtx (avl_type::NONVLMAX)); return e.generate_insn (code_for_pred_mov (e.vector_mode ())); } }; /* Implements vmnot. */ class vmnot : public function_base { public: bool apply_tail_policy_p () const override { return false; } bool apply_mask_policy_p () const override { return false; } rtx expand (function_expander &e) const override { return e.use_exact_insn (code_for_pred_not (e.vector_mode ())); } }; /* Implements vcpop. */ class vcpop : public function_base { public: bool apply_tail_policy_p () const override { return false; } bool apply_mask_policy_p () const override { return false; } bool has_merge_operand_p () const override { return false; } rtx expand (function_expander &e) const override { return e.use_exact_insn (code_for_pred_popcount (e.vector_mode (), Pmode)); } }; /* Implements vfirst. */ class vfirst : public function_base { public: bool apply_tail_policy_p () const override { return false; } bool apply_mask_policy_p () const override { return false; } bool has_merge_operand_p () const override { return false; } rtx expand (function_expander &e) const override { return e.use_exact_insn (code_for_pred_ffs (e.vector_mode (), Pmode)); } }; /* Implements vmsbf/vmsif/vmsof. */ template class mask_misc : public function_base { public: bool apply_tail_policy_p () const override { return false; } rtx expand (function_expander &e) const override { return e.use_exact_insn (code_for_pred (UNSPEC, e.vector_mode ())); } }; /* Implements viota. */ class viota : public function_base { public: bool can_be_overloaded_p (enum predication_type_index pred) const override { return pred == PRED_TYPE_tu || pred == PRED_TYPE_tum || pred == PRED_TYPE_tumu || pred == PRED_TYPE_mu; } rtx expand (function_expander &e) const override { return e.use_exact_insn (code_for_pred_iota (e.vector_mode ())); } }; /* Implements vid. */ class vid : public function_base { public: bool can_be_overloaded_p (enum predication_type_index pred) const override { return pred == PRED_TYPE_tu || pred == PRED_TYPE_tum || pred == PRED_TYPE_tumu || pred == PRED_TYPE_mu; } rtx expand (function_expander &e) const override { return e.use_exact_insn (code_for_pred_series (e.vector_mode ())); } }; /* Implements vfrsub/vfrdiv. */ template class reverse_binop : public function_base { public: rtx expand (function_expander &e) const override { return e.use_exact_insn ( code_for_pred_reverse_scalar (CODE, e.vector_mode ())); } }; class vfmacc : public function_base { public: bool has_merge_operand_p () const override { return false; } rtx expand (function_expander &e) const override { if (e.op_info->op == OP_TYPE_vf) return e.use_ternop_insn (true, code_for_pred_mul_scalar (PLUS, e.vector_mode ())); if (e.op_info->op == OP_TYPE_vv) return e.use_ternop_insn (true, code_for_pred_mul (PLUS, e.vector_mode ())); gcc_unreachable (); } }; class vfnmsac : public function_base { public: bool has_merge_operand_p () const override { return false; } rtx expand (function_expander &e) const override { if (e.op_info->op == OP_TYPE_vf) return e.use_ternop_insn ( true, code_for_pred_mul_neg_scalar (PLUS, e.vector_mode ())); if (e.op_info->op == OP_TYPE_vv) return e.use_ternop_insn (true, code_for_pred_mul_neg (PLUS, e.vector_mode ())); gcc_unreachable (); } }; class vfmadd : public function_base { public: bool has_merge_operand_p () const override { return false; } rtx expand (function_expander &e) const override { if (e.op_info->op == OP_TYPE_vf) return e.use_ternop_insn (false, code_for_pred_mul_scalar (PLUS, e.vector_mode ())); if (e.op_info->op == OP_TYPE_vv) return e.use_ternop_insn (false, code_for_pred_mul (PLUS, e.vector_mode ())); gcc_unreachable (); } }; class vfnmsub : public function_base { public: bool has_merge_operand_p () const override { return false; } rtx expand (function_expander &e) const override { if (e.op_info->op == OP_TYPE_vf) return e.use_ternop_insn ( false, code_for_pred_mul_neg_scalar (PLUS, e.vector_mode ())); if (e.op_info->op == OP_TYPE_vv) return e.use_ternop_insn (false, code_for_pred_mul_neg (PLUS, e.vector_mode ())); gcc_unreachable (); } }; class vfnmacc : public function_base { public: bool has_merge_operand_p () const override { return false; } rtx expand (function_expander &e) const override { if (e.op_info->op == OP_TYPE_vf) return e.use_ternop_insn ( true, code_for_pred_mul_neg_scalar (MINUS, e.vector_mode ())); if (e.op_info->op == OP_TYPE_vv) return e.use_ternop_insn (true, code_for_pred_mul_neg (MINUS, e.vector_mode ())); gcc_unreachable (); } }; class vfmsac : public function_base { public: bool has_merge_operand_p () const override { return false; } rtx expand (function_expander &e) const override { if (e.op_info->op == OP_TYPE_vf) return e.use_ternop_insn (true, code_for_pred_mul_scalar (MINUS, e.vector_mode ())); if (e.op_info->op == OP_TYPE_vv) return e.use_ternop_insn (true, code_for_pred_mul (MINUS, e.vector_mode ())); gcc_unreachable (); } }; class vfnmadd : public function_base { public: bool has_merge_operand_p () const override { return false; } rtx expand (function_expander &e) const override { if (e.op_info->op == OP_TYPE_vf) return e.use_ternop_insn ( false, code_for_pred_mul_neg_scalar (MINUS, e.vector_mode ())); if (e.op_info->op == OP_TYPE_vv) return e.use_ternop_insn (false, code_for_pred_mul_neg (MINUS, e.vector_mode ())); gcc_unreachable (); } }; class vfmsub : public function_base { public: bool has_merge_operand_p () const override { return false; } rtx expand (function_expander &e) const override { if (e.op_info->op == OP_TYPE_vf) return e.use_ternop_insn (false, code_for_pred_mul_scalar (MINUS, e.vector_mode ())); if (e.op_info->op == OP_TYPE_vv) return e.use_ternop_insn (false, code_for_pred_mul (MINUS, e.vector_mode ())); gcc_unreachable (); } }; class vfwmacc : public function_base { public: bool has_merge_operand_p () const override { return false; } rtx expand (function_expander &e) const override { if (e.op_info->op == OP_TYPE_vf) return e.use_widen_ternop_insn ( code_for_pred_widen_mul_scalar (PLUS, e.vector_mode ())); if (e.op_info->op == OP_TYPE_vv) return e.use_widen_ternop_insn ( code_for_pred_widen_mul (PLUS, e.vector_mode ())); gcc_unreachable (); } }; class vfwnmacc : public function_base { public: bool has_merge_operand_p () const override { return false; } rtx expand (function_expander &e) const override { if (e.op_info->op == OP_TYPE_vf) return e.use_widen_ternop_insn ( code_for_pred_widen_mul_neg_scalar (MINUS, e.vector_mode ())); if (e.op_info->op == OP_TYPE_vv) return e.use_widen_ternop_insn ( code_for_pred_widen_mul_neg (MINUS, e.vector_mode ())); gcc_unreachable (); } }; class vfwmsac : public function_base { public: bool has_merge_operand_p () const override { return false; } rtx expand (function_expander &e) const override { if (e.op_info->op == OP_TYPE_vf) return e.use_widen_ternop_insn ( code_for_pred_widen_mul_scalar (MINUS, e.vector_mode ())); if (e.op_info->op == OP_TYPE_vv) return e.use_widen_ternop_insn ( code_for_pred_widen_mul (MINUS, e.vector_mode ())); gcc_unreachable (); } }; class vfwnmsac : public function_base { public: bool has_merge_operand_p () const override { return false; } rtx expand (function_expander &e) const override { if (e.op_info->op == OP_TYPE_vf) return e.use_widen_ternop_insn ( code_for_pred_widen_mul_neg_scalar (PLUS, e.vector_mode ())); if (e.op_info->op == OP_TYPE_vv) return e.use_widen_ternop_insn ( code_for_pred_widen_mul_neg (PLUS, e.vector_mode ())); gcc_unreachable (); } }; /* Implements vfsqrt7/vfrec7/vfclass/vfsgnj/vfsgnjn/vfsgnjx. */ template class float_misc : public function_base { public: rtx expand (function_expander &e) const override { if (e.op_info->op == OP_TYPE_vf) return e.use_exact_insn (code_for_pred_scalar (UNSPEC, e.vector_mode ())); if (e.op_info->op == OP_TYPE_vv || e.op_info->op == OP_TYPE_v) return e.use_exact_insn (code_for_pred (UNSPEC, e.vector_mode ())); gcc_unreachable (); } }; /* Implements vmfeq/vmfne/vmflt/vmfgt/vmfle/vmfge. */ template class fcmp : public function_base { public: rtx expand (function_expander &e) const override { switch (e.op_info->op) { case OP_TYPE_vf: { if (CODE == EQ || CODE == NE) return e.use_compare_insn (CODE, code_for_pred_eqne_scalar ( e.vector_mode ())); else return e.use_compare_insn (CODE, code_for_pred_cmp_scalar ( e.vector_mode ())); } case OP_TYPE_vv: { return e.use_compare_insn (CODE, code_for_pred_cmp (e.vector_mode ())); } default: gcc_unreachable (); } } }; /* Implements vfclass. */ class vfclass : public function_base { public: rtx expand (function_expander &e) const override { return e.use_exact_insn (code_for_pred_class (e.arg_mode (0))); } }; /* Implements vfcvt.x. */ template class vfcvt_x : public function_base { public: rtx expand (function_expander &e) const override { return e.use_exact_insn (code_for_pred_fcvt_x_f (UNSPEC, e.arg_mode (0))); } }; /* Implements vfcvt.rtz.x. */ template class vfcvt_rtz_x : public function_base { public: rtx expand (function_expander &e) const override { return e.use_exact_insn (code_for_pred (CODE, e.arg_mode (0))); } }; class vfcvt_f : public function_base { public: rtx expand (function_expander &e) const override { if (e.op_info->op == OP_TYPE_x_v) return e.use_exact_insn (code_for_pred (FLOAT, e.vector_mode ())); if (e.op_info->op == OP_TYPE_xu_v) return e.use_exact_insn ( code_for_pred (UNSIGNED_FLOAT, e.vector_mode ())); gcc_unreachable (); } }; /* Implements vfwcvt.x. */ template class vfwcvt_x : public function_base { public: rtx expand (function_expander &e) const override { return e.use_exact_insn ( code_for_pred_widen_fcvt_x_f (UNSPEC, e.vector_mode ())); } }; /* Implements vfwcvt.rtz.x. */ template class vfwcvt_rtz_x : public function_base { public: rtx expand (function_expander &e) const override { return e.use_exact_insn (code_for_pred_widen (CODE, e.vector_mode ())); } }; class vfwcvt_f : public function_base { public: rtx expand (function_expander &e) const override { if (e.op_info->op == OP_TYPE_f_v) return e.use_exact_insn (code_for_pred_extend (e.vector_mode ())); if (e.op_info->op == OP_TYPE_x_v) return e.use_exact_insn (code_for_pred_widen (FLOAT, e.vector_mode ())); if (e.op_info->op == OP_TYPE_xu_v) return e.use_exact_insn ( code_for_pred_widen (UNSIGNED_FLOAT, e.vector_mode ())); gcc_unreachable (); } }; /* Implements vfncvt.x. */ template class vfncvt_x : public function_base { public: rtx expand (function_expander &e) const override { return e.use_exact_insn ( code_for_pred_narrow_fcvt_x_f (UNSPEC, e.arg_mode (0))); } }; /* Implements vfncvt.rtz.x. */ template class vfncvt_rtz_x : public function_base { public: rtx expand (function_expander &e) const override { return e.use_exact_insn (code_for_pred_narrow (CODE, e.vector_mode ())); } }; class vfncvt_f : public function_base { public: rtx expand (function_expander &e) const override { if (e.op_info->op == OP_TYPE_f_w) return e.use_exact_insn (code_for_pred_trunc (e.vector_mode ())); if (e.op_info->op == OP_TYPE_x_w) return e.use_exact_insn (code_for_pred_narrow (FLOAT, e.arg_mode (0))); if (e.op_info->op == OP_TYPE_xu_w) return e.use_exact_insn ( code_for_pred_narrow (UNSIGNED_FLOAT, e.arg_mode (0))); gcc_unreachable (); } }; class vfncvt_rod_f : public function_base { public: rtx expand (function_expander &e) const override { return e.use_exact_insn (code_for_pred_rod_trunc (e.vector_mode ())); } }; /* Implements reduction instructions. */ template class reducop : public function_base { public: bool apply_mask_policy_p () const override { return false; } rtx expand (function_expander &e) const override { return e.use_exact_insn ( code_for_pred_reduc (CODE, e.vector_mode (), e.ret_mode ())); } }; /* Implements widen reduction instructions. */ template class widen_reducop : public function_base { public: bool apply_mask_policy_p () const override { return false; } rtx expand (function_expander &e) const override { return e.use_exact_insn (code_for_pred_widen_reduc_plus (UNSPEC, e.vector_mode (), e.ret_mode ())); } }; /* Implements floating-point reduction instructions. */ template class freducop : public function_base { public: bool apply_mask_policy_p () const override { return false; } rtx expand (function_expander &e) const override { return e.use_exact_insn ( code_for_pred_reduc_plus (UNSPEC, e.vector_mode (), e.ret_mode ())); } }; /* Implements widening floating-point reduction instructions. */ template class widen_freducop : public function_base { public: bool apply_mask_policy_p () const override { return false; } rtx expand (function_expander &e) const override { return e.use_exact_insn (code_for_pred_widen_reduc_plus (UNSPEC, e.vector_mode (), e.ret_mode ())); } }; /* Implements vmv/vfmv instructions. */ class vmv : public function_base { public: bool apply_vl_p () const override { return false; } bool apply_tail_policy_p () const override { return false; } bool apply_mask_policy_p () const override { return false; } bool use_mask_predication_p () const override { return false; } bool has_merge_operand_p () const override { return false; } rtx expand (function_expander &e) const override { return e.use_exact_insn (code_for_pred_extract_first (e.vector_mode ())); } }; /* Implements vmv.s.x/vfmv.s.f. */ class vmv_s : public function_base { public: rtx expand (function_expander &e) const override { return e.use_scalar_move_insn (code_for_pred_broadcast (e.vector_mode ())); } }; template class slideop : public function_base { public: bool has_merge_operand_p () const override { if (UNSPEC == UNSPEC_VSLIDEUP) return false; return true; } rtx expand (function_expander &e) const override { return e.use_exact_insn (code_for_pred_slide (UNSPEC, e.vector_mode ())); } }; class vrgather : public function_base { public: rtx expand (function_expander &e) const override { switch (e.op_info->op) { case OP_TYPE_vx: return e.use_exact_insn ( code_for_pred_gather_scalar (e.vector_mode ())); case OP_TYPE_vv: return e.use_exact_insn (code_for_pred_gather (e.vector_mode ())); default: gcc_unreachable (); } } }; class vrgatherei16 : public function_base { public: rtx expand (function_expander &e) const override { return e.use_exact_insn (code_for_pred_gatherei16 (e.vector_mode ())); } }; class vcompress : public function_base { public: bool apply_mask_policy_p () const override { return false; } bool use_mask_predication_p () const override { return false; } rtx expand (function_expander &e) const override { return e.use_exact_insn (code_for_pred_compress (e.vector_mode ())); } }; class vundefined : public function_base { public: bool apply_vl_p () const override { return false; } rtx expand (function_expander &e) const override { return e.generate_insn (code_for_vundefined (e.vector_mode ())); } }; class vreinterpret : public function_base { public: bool apply_vl_p () const override { return false; } rtx expand (function_expander &e) const override { e.add_input_operand (0); return e.generate_insn (code_for_vreinterpret (e.ret_mode ())); } }; class vlmul_ext : public function_base { public: bool apply_vl_p () const override { return false; } rtx expand (function_expander &e) const override { tree arg = CALL_EXPR_ARG (e.exp, 0); rtx src = expand_normal (arg); emit_move_insn (gen_lowpart (e.vector_mode (), e.target), src); return e.target; } }; class vlmul_trunc : public function_base { public: bool apply_vl_p () const override { return false; } rtx expand (function_expander &e) const override { rtx src = expand_normal (CALL_EXPR_ARG (e.exp, 0)); emit_move_insn (e.target, gen_lowpart (GET_MODE (e.target), src)); return e.target; } }; class vset : public function_base { public: bool apply_vl_p () const override { return false; } gimple *fold (gimple_folder &f) const override { tree rhs_tuple = gimple_call_arg (f.call, 0); /* LMUL > 1 non-tuple vector types are not structure, we can't use __val[index] to set the subpart. */ if (!riscv_v_ext_tuple_mode_p (TYPE_MODE (TREE_TYPE (rhs_tuple)))) return NULL; tree index = gimple_call_arg (f.call, 1); tree rhs_vector = gimple_call_arg (f.call, 2); /* Replace the call with two statements: a copy of the full tuple to the call result, followed by an update of the individual vector. The fold routines expect the replacement statement to have the same lhs as the original call, so return the copy statement rather than the field update. */ gassign *copy = gimple_build_assign (unshare_expr (f.lhs), rhs_tuple); /* Get a reference to the individual vector. */ tree field = tuple_type_field (TREE_TYPE (f.lhs)); tree lhs_array = build3 (COMPONENT_REF, TREE_TYPE (field), f.lhs, field, NULL_TREE); tree lhs_vector = build4 (ARRAY_REF, TREE_TYPE (rhs_vector), lhs_array, index, NULL_TREE, NULL_TREE); gassign *update = gimple_build_assign (lhs_vector, rhs_vector); gsi_insert_after (f.gsi, update, GSI_SAME_STMT); return copy; } rtx expand (function_expander &e) const override { rtx dest = expand_normal (CALL_EXPR_ARG (e.exp, 0)); gcc_assert (riscv_v_ext_vector_mode_p (GET_MODE (dest))); rtx index = expand_normal (CALL_EXPR_ARG (e.exp, 1)); rtx src = expand_normal (CALL_EXPR_ARG (e.exp, 2)); poly_int64 offset = INTVAL (index) * GET_MODE_SIZE (GET_MODE (src)); emit_move_insn (e.target, dest); rtx subreg = simplify_gen_subreg (GET_MODE (src), e.target, GET_MODE (e.target), offset); emit_move_insn (subreg, src); return e.target; } }; class vget : public function_base { public: bool apply_vl_p () const override { return false; } gimple *fold (gimple_folder &f) const override { /* Fold into a normal gimple component access. */ tree rhs_tuple = gimple_call_arg (f.call, 0); /* LMUL > 1 non-tuple vector types are not structure, we can't use __val[index] to get the subpart. */ if (!riscv_v_ext_tuple_mode_p (TYPE_MODE (TREE_TYPE (rhs_tuple)))) return NULL; tree index = gimple_call_arg (f.call, 1); tree field = tuple_type_field (TREE_TYPE (rhs_tuple)); tree rhs_array = build3 (COMPONENT_REF, TREE_TYPE (field), rhs_tuple, field, NULL_TREE); tree rhs_vector = build4 (ARRAY_REF, TREE_TYPE (f.lhs), rhs_array, index, NULL_TREE, NULL_TREE); return gimple_build_assign (f.lhs, rhs_vector); } rtx expand (function_expander &e) const override { rtx src = expand_normal (CALL_EXPR_ARG (e.exp, 0)); gcc_assert (riscv_v_ext_vector_mode_p (GET_MODE (src))); rtx index = expand_normal (CALL_EXPR_ARG (e.exp, 1)); poly_int64 offset = INTVAL (index) * GET_MODE_SIZE (GET_MODE (e.target)); rtx subreg = simplify_gen_subreg (GET_MODE (e.target), src, GET_MODE (src), offset); return subreg; } }; class read_vl : public function_base { public: unsigned int call_properties (const function_instance &) const override { return CP_READ_CSR; } rtx expand (function_expander &e) const override { if (Pmode == SImode) emit_insn (gen_read_vlsi (e.target)); else emit_insn (gen_read_vldi_zero_extend (e.target)); return e.target; } }; class vleff : public function_base { public: unsigned int call_properties (const function_instance &) const override { return CP_READ_MEMORY | CP_WRITE_CSR; } bool can_be_overloaded_p (enum predication_type_index pred) const override { return pred != PRED_TYPE_none; } gimple *fold (gimple_folder &f) const override { return fold_fault_load (f); } rtx expand (function_expander &e) const override { return e.use_contiguous_load_insn ( code_for_pred_fault_load (e.vector_mode ())); } }; /* Implements vlenb. */ class vlenb : public function_base { public: bool apply_vl_p () const override { return false; } rtx expand (function_expander &e) const override { machine_mode mode = GET_MODE (e.target); rtx vlenb = gen_int_mode (BYTES_PER_RISCV_VECTOR, mode); emit_move_insn (e.target, vlenb); return e.target; } }; /* Implements vlseg.v. */ class vlseg : public function_base { public: unsigned int call_properties (const function_instance &) const override { return CP_READ_MEMORY; } bool can_be_overloaded_p (enum predication_type_index pred) const override { return pred != PRED_TYPE_none; } rtx expand (function_expander &e) const override { return e.use_exact_insn ( code_for_pred_unit_strided_load (e.vector_mode ())); } }; /* Implements vsseg.v. */ class vsseg : public function_base { public: bool apply_tail_policy_p () const override { return false; } bool apply_mask_policy_p () const override { return false; } unsigned int call_properties (const function_instance &) const override { return CP_WRITE_MEMORY; } bool can_be_overloaded_p (enum predication_type_index) const override { return true; } rtx expand (function_expander &e) const override { return e.use_exact_insn ( code_for_pred_unit_strided_store (e.vector_mode ())); } }; /* Implements vlsseg.v. */ class vlsseg : public function_base { public: unsigned int call_properties (const function_instance &) const override { return CP_READ_MEMORY; } bool can_be_overloaded_p (enum predication_type_index pred) const override { return pred != PRED_TYPE_none; } rtx expand (function_expander &e) const override { return e.use_exact_insn ( code_for_pred_strided_load (e.vector_mode ())); } }; /* Implements vssseg.v. */ class vssseg : public function_base { public: bool apply_tail_policy_p () const override { return false; } bool apply_mask_policy_p () const override { return false; } unsigned int call_properties (const function_instance &) const override { return CP_WRITE_MEMORY; } bool can_be_overloaded_p (enum predication_type_index) const override { return true; } rtx expand (function_expander &e) const override { return e.use_exact_insn ( code_for_pred_strided_store (e.vector_mode ())); } }; template class seg_indexed_load : public function_base { public: unsigned int call_properties (const function_instance &) const override { return CP_READ_MEMORY; } bool can_be_overloaded_p (enum predication_type_index) const override { return true; } rtx expand (function_expander &e) const override { return e.use_exact_insn ( code_for_pred_indexed_load (UNSPEC, e.vector_mode (), e.index_mode ())); } }; template class seg_indexed_store : public function_base { public: bool apply_tail_policy_p () const override { return false; } bool apply_mask_policy_p () const override { return false; } unsigned int call_properties (const function_instance &) const override { return CP_WRITE_MEMORY; } bool can_be_overloaded_p (enum predication_type_index) const override { return true; } rtx expand (function_expander &e) const override { return e.use_exact_insn ( code_for_pred_indexed_store (UNSPEC, e.vector_mode (), e.index_mode ())); } }; /* Implements vlsegff.v. */ class vlsegff : public function_base { public: unsigned int call_properties (const function_instance &) const override { return CP_READ_MEMORY | CP_WRITE_CSR; } bool can_be_overloaded_p (enum predication_type_index pred) const override { return pred != PRED_TYPE_none; } gimple *fold (gimple_folder &f) const override { return fold_fault_load (f); } rtx expand (function_expander &e) const override { return e.use_exact_insn (code_for_pred_fault_load (e.vector_mode ())); } }; static CONSTEXPR const vsetvl vsetvl_obj; static CONSTEXPR const vsetvl vsetvlmax_obj; static CONSTEXPR const loadstore vle_obj; static CONSTEXPR const loadstore vse_obj; static CONSTEXPR const loadstore vlm_obj; static CONSTEXPR const loadstore vsm_obj; static CONSTEXPR const loadstore vlse_obj; static CONSTEXPR const loadstore vsse_obj; static CONSTEXPR const loadstore vluxei8_obj; static CONSTEXPR const loadstore vluxei16_obj; static CONSTEXPR const loadstore vluxei32_obj; static CONSTEXPR const loadstore vluxei64_obj; static CONSTEXPR const loadstore vloxei8_obj; static CONSTEXPR const loadstore vloxei16_obj; static CONSTEXPR const loadstore vloxei32_obj; static CONSTEXPR const loadstore vloxei64_obj; static CONSTEXPR const loadstore vsuxei8_obj; static CONSTEXPR const loadstore vsuxei16_obj; static CONSTEXPR const loadstore vsuxei32_obj; static CONSTEXPR const loadstore vsuxei64_obj; static CONSTEXPR const loadstore vsoxei8_obj; static CONSTEXPR const loadstore vsoxei16_obj; static CONSTEXPR const loadstore vsoxei32_obj; static CONSTEXPR const loadstore vsoxei64_obj; static CONSTEXPR const binop vadd_obj; static CONSTEXPR const binop vsub_obj; static CONSTEXPR const vrsub vrsub_obj; static CONSTEXPR const binop vand_obj; static CONSTEXPR const binop vor_obj; static CONSTEXPR const binop vxor_obj; static CONSTEXPR const binop vsll_obj; static CONSTEXPR const binop vsra_obj; static CONSTEXPR const binop vsrl_obj; static CONSTEXPR const binop vmin_obj; static CONSTEXPR const binop vmax_obj; static CONSTEXPR const binop vminu_obj; static CONSTEXPR const binop vmaxu_obj; static CONSTEXPR const binop vmul_obj; static CONSTEXPR const vmulh vmulh_obj; static CONSTEXPR const vmulh vmulhu_obj; static CONSTEXPR const vmulh vmulhsu_obj; static CONSTEXPR const binop
vdiv_obj; static CONSTEXPR const binop vrem_obj; static CONSTEXPR const binop vdivu_obj; static CONSTEXPR const binop vremu_obj; static CONSTEXPR const unop vneg_obj; static CONSTEXPR const unop vnot_obj; static CONSTEXPR const ext vsext_obj; static CONSTEXPR const ext vzext_obj; static CONSTEXPR const widen_binopvwadd_obj; static CONSTEXPR const widen_binopvwsub_obj; static CONSTEXPR const widen_binopvwmul_obj; static CONSTEXPR const widen_binopvwaddu_obj; static CONSTEXPR const widen_binopvwsubu_obj; static CONSTEXPR const widen_binopvwmulu_obj; static CONSTEXPR const vwmulsu vwmulsu_obj; static CONSTEXPR const vwcvt vwcvt_x_obj; static CONSTEXPR const vwcvt vwcvtu_x_obj; static CONSTEXPR const vadc vadc_obj; static CONSTEXPR const vsbc vsbc_obj; static CONSTEXPR const vmadc vmadc_obj; static CONSTEXPR const vmsbc vmsbc_obj; static CONSTEXPR const vnshift vnsrl_obj; static CONSTEXPR const vnshift vnsra_obj; static CONSTEXPR const vncvt_x vncvt_x_obj; static CONSTEXPR const vmerge vmerge_obj; static CONSTEXPR const vmv_v vmv_v_obj; static CONSTEXPR const icmp vmseq_obj; static CONSTEXPR const icmp vmsne_obj; static CONSTEXPR const icmp vmslt_obj; static CONSTEXPR const icmp vmsgt_obj; static CONSTEXPR const icmp vmsle_obj; static CONSTEXPR const icmp vmsge_obj; static CONSTEXPR const icmp vmsltu_obj; static CONSTEXPR const icmp vmsgtu_obj; static CONSTEXPR const icmp vmsleu_obj; static CONSTEXPR const icmp vmsgeu_obj; static CONSTEXPR const vmacc vmacc_obj; static CONSTEXPR const vnmsac vnmsac_obj; static CONSTEXPR const vmadd vmadd_obj; static CONSTEXPR const vnmsub vnmsub_obj; static CONSTEXPR const vwmacc vwmacc_obj; static CONSTEXPR const vwmaccu vwmaccu_obj; static CONSTEXPR const vwmaccsu vwmaccsu_obj; static CONSTEXPR const vwmaccus vwmaccus_obj; static CONSTEXPR const binop vsadd_obj; static CONSTEXPR const binop vssub_obj; static CONSTEXPR const binop vsaddu_obj; static CONSTEXPR const binop vssubu_obj; static CONSTEXPR const sat_op vaaddu_obj; static CONSTEXPR const sat_op vaadd_obj; static CONSTEXPR const sat_op vasubu_obj; static CONSTEXPR const sat_op vasub_obj; static CONSTEXPR const sat_op vsmul_obj; static CONSTEXPR const sat_op vssrl_obj; static CONSTEXPR const sat_op vssra_obj; static CONSTEXPR const vnclip vnclip_obj; static CONSTEXPR const vnclip vnclipu_obj; static CONSTEXPR const mask_logic vmand_obj; static CONSTEXPR const mask_nlogic vmnand_obj; static CONSTEXPR const mask_notlogic vmandn_obj; static CONSTEXPR const mask_logic vmxor_obj; static CONSTEXPR const mask_logic vmor_obj; static CONSTEXPR const mask_nlogic vmnor_obj; static CONSTEXPR const mask_notlogic vmorn_obj; static CONSTEXPR const mask_nlogic vmxnor_obj; static CONSTEXPR const vmmv vmmv_obj; static CONSTEXPR const vmclr vmclr_obj; static CONSTEXPR const vmset vmset_obj; static CONSTEXPR const vmnot vmnot_obj; static CONSTEXPR const vcpop vcpop_obj; static CONSTEXPR const vfirst vfirst_obj; static CONSTEXPR const mask_misc vmsbf_obj; static CONSTEXPR const mask_misc vmsif_obj; static CONSTEXPR const mask_misc vmsof_obj; static CONSTEXPR const viota viota_obj; static CONSTEXPR const vid vid_obj; static CONSTEXPR const binop vfadd_obj; static CONSTEXPR const binop vfsub_obj; static CONSTEXPR const reverse_binop vfrsub_obj; static CONSTEXPR const widen_binop vfwadd_obj; static CONSTEXPR const widen_binop vfwsub_obj; static CONSTEXPR const binop vfmul_obj; static CONSTEXPR const binop
vfdiv_obj; static CONSTEXPR const reverse_binop
vfrdiv_obj; static CONSTEXPR const widen_binop vfwmul_obj; static CONSTEXPR const vfmacc vfmacc_obj; static CONSTEXPR const vfnmsac vfnmsac_obj; static CONSTEXPR const vfmadd vfmadd_obj; static CONSTEXPR const vfnmsub vfnmsub_obj; static CONSTEXPR const vfnmacc vfnmacc_obj; static CONSTEXPR const vfmsac vfmsac_obj; static CONSTEXPR const vfnmadd vfnmadd_obj; static CONSTEXPR const vfmsub vfmsub_obj; static CONSTEXPR const vfwmacc vfwmacc_obj; static CONSTEXPR const vfwnmacc vfwnmacc_obj; static CONSTEXPR const vfwmsac vfwmsac_obj; static CONSTEXPR const vfwnmsac vfwnmsac_obj; static CONSTEXPR const unop vfsqrt_obj; static CONSTEXPR const float_misc vfrsqrt7_obj; static CONSTEXPR const float_misc vfrec7_obj; static CONSTEXPR const binop vfmin_obj; static CONSTEXPR const binop vfmax_obj; static CONSTEXPR const float_misc vfsgnj_obj; static CONSTEXPR const float_misc vfsgnjn_obj; static CONSTEXPR const float_misc vfsgnjx_obj; static CONSTEXPR const unop vfneg_obj; static CONSTEXPR const unop vfabs_obj; static CONSTEXPR const fcmp vmfeq_obj; static CONSTEXPR const fcmp vmfne_obj; static CONSTEXPR const fcmp vmflt_obj; static CONSTEXPR const fcmp vmfgt_obj; static CONSTEXPR const fcmp vmfle_obj; static CONSTEXPR const fcmp vmfge_obj; static CONSTEXPR const vfclass vfclass_obj; static CONSTEXPR const vmerge vfmerge_obj; static CONSTEXPR const vmv_v vfmv_v_obj; static CONSTEXPR const vfcvt_x vfcvt_x_obj; static CONSTEXPR const vfcvt_x vfcvt_xu_obj; static CONSTEXPR const vfcvt_rtz_x vfcvt_rtz_x_obj; static CONSTEXPR const vfcvt_rtz_x vfcvt_rtz_xu_obj; static CONSTEXPR const vfcvt_f vfcvt_f_obj; static CONSTEXPR const vfwcvt_x vfwcvt_x_obj; static CONSTEXPR const vfwcvt_x vfwcvt_xu_obj; static CONSTEXPR const vfwcvt_rtz_x vfwcvt_rtz_x_obj; static CONSTEXPR const vfwcvt_rtz_x vfwcvt_rtz_xu_obj; static CONSTEXPR const vfwcvt_f vfwcvt_f_obj; static CONSTEXPR const vfncvt_x vfncvt_x_obj; static CONSTEXPR const vfncvt_x vfncvt_xu_obj; static CONSTEXPR const vfncvt_rtz_x vfncvt_rtz_x_obj; static CONSTEXPR const vfncvt_rtz_x vfncvt_rtz_xu_obj; static CONSTEXPR const vfncvt_f vfncvt_f_obj; static CONSTEXPR const vfncvt_rod_f vfncvt_rod_f_obj; static CONSTEXPR const reducop vredsum_obj; static CONSTEXPR const reducop vredmaxu_obj; static CONSTEXPR const reducop vredmax_obj; static CONSTEXPR const reducop vredminu_obj; static CONSTEXPR const reducop vredmin_obj; static CONSTEXPR const reducop vredand_obj; static CONSTEXPR const reducop vredor_obj; static CONSTEXPR const reducop vredxor_obj; static CONSTEXPR const widen_reducop vwredsum_obj; static CONSTEXPR const widen_reducop vwredsumu_obj; static CONSTEXPR const freducop vfredusum_obj; static CONSTEXPR const freducop vfredosum_obj; static CONSTEXPR const reducop vfredmax_obj; static CONSTEXPR const reducop vfredmin_obj; static CONSTEXPR const widen_freducop vfwredusum_obj; static CONSTEXPR const widen_freducop vfwredosum_obj; static CONSTEXPR const vmv vmv_x_obj; static CONSTEXPR const vmv_s vmv_s_obj; static CONSTEXPR const vmv vfmv_f_obj; static CONSTEXPR const vmv_s vfmv_s_obj; static CONSTEXPR const slideop vslideup_obj; static CONSTEXPR const slideop vslidedown_obj; static CONSTEXPR const slideop vslide1up_obj; static CONSTEXPR const slideop vslide1down_obj; static CONSTEXPR const slideop vfslide1up_obj; static CONSTEXPR const slideop vfslide1down_obj; static CONSTEXPR const vrgather vrgather_obj; static CONSTEXPR const vrgatherei16 vrgatherei16_obj; static CONSTEXPR const vcompress vcompress_obj; static CONSTEXPR const vundefined vundefined_obj; static CONSTEXPR const vreinterpret vreinterpret_obj; static CONSTEXPR const vlmul_ext vlmul_ext_obj; static CONSTEXPR const vlmul_trunc vlmul_trunc_obj; static CONSTEXPR const vset vset_obj; static CONSTEXPR const vget vget_obj; static CONSTEXPR const read_vl read_vl_obj; static CONSTEXPR const vleff vleff_obj; static CONSTEXPR const vlenb vlenb_obj; static CONSTEXPR const vlseg vlseg_obj; static CONSTEXPR const vsseg vsseg_obj; static CONSTEXPR const vlsseg vlsseg_obj; static CONSTEXPR const vssseg vssseg_obj; static CONSTEXPR const seg_indexed_load vluxseg_obj; static CONSTEXPR const seg_indexed_load vloxseg_obj; static CONSTEXPR const seg_indexed_store vsuxseg_obj; static CONSTEXPR const seg_indexed_store vsoxseg_obj; static CONSTEXPR const vlsegff vlsegff_obj; /* Declare the function base NAME, pointing it to an instance of class _obj. */ #define BASE(NAME) \ namespace bases { const function_base *const NAME = &NAME##_obj; } BASE (vsetvl) BASE (vsetvlmax) BASE (vle) BASE (vse) BASE (vlm) BASE (vsm) BASE (vlse) BASE (vsse) BASE (vluxei8) BASE (vluxei16) BASE (vluxei32) BASE (vluxei64) BASE (vloxei8) BASE (vloxei16) BASE (vloxei32) BASE (vloxei64) BASE (vsuxei8) BASE (vsuxei16) BASE (vsuxei32) BASE (vsuxei64) BASE (vsoxei8) BASE (vsoxei16) BASE (vsoxei32) BASE (vsoxei64) BASE (vadd) BASE (vsub) BASE (vrsub) BASE (vand) BASE (vor) BASE (vxor) BASE (vsll) BASE (vsra) BASE (vsrl) BASE (vmin) BASE (vmax) BASE (vminu) BASE (vmaxu) BASE (vmul) BASE (vmulh) BASE (vmulhu) BASE (vmulhsu) BASE (vdiv) BASE (vrem) BASE (vdivu) BASE (vremu) BASE (vneg) BASE (vnot) BASE (vsext) BASE (vzext) BASE (vwadd) BASE (vwsub) BASE (vwmul) BASE (vwaddu) BASE (vwsubu) BASE (vwmulu) BASE (vwmulsu) BASE (vwcvt_x) BASE (vwcvtu_x) BASE (vadc) BASE (vsbc) BASE (vmadc) BASE (vmsbc) BASE (vnsrl) BASE (vnsra) BASE (vncvt_x) BASE (vmerge) BASE (vmv_v) BASE (vmseq) BASE (vmsne) BASE (vmslt) BASE (vmsgt) BASE (vmsle) BASE (vmsge) BASE (vmsltu) BASE (vmsgtu) BASE (vmsleu) BASE (vmsgeu) BASE (vmacc) BASE (vnmsac) BASE (vmadd) BASE (vnmsub) BASE (vwmacc) BASE (vwmaccu) BASE (vwmaccsu) BASE (vwmaccus) BASE (vsadd) BASE (vssub) BASE (vsaddu) BASE (vssubu) BASE (vaadd) BASE (vasub) BASE (vaaddu) BASE (vasubu) BASE (vsmul) BASE (vssra) BASE (vssrl) BASE (vnclip) BASE (vnclipu) BASE (vmand) BASE (vmnand) BASE (vmandn) BASE (vmxor) BASE (vmor) BASE (vmnor) BASE (vmorn) BASE (vmxnor) BASE (vmmv) BASE (vmclr) BASE (vmset) BASE (vmnot) BASE (vcpop) BASE (vfirst) BASE (vmsbf) BASE (vmsif) BASE (vmsof) BASE (viota) BASE (vid) BASE (vfadd) BASE (vfsub) BASE (vfrsub) BASE (vfwadd) BASE (vfwsub) BASE (vfmul) BASE (vfdiv) BASE (vfrdiv) BASE (vfwmul) BASE (vfmacc) BASE (vfnmsac) BASE (vfmadd) BASE (vfnmsub) BASE (vfnmacc) BASE (vfmsac) BASE (vfnmadd) BASE (vfmsub) BASE (vfwmacc) BASE (vfwnmacc) BASE (vfwmsac) BASE (vfwnmsac) BASE (vfsqrt) BASE (vfrsqrt7) BASE (vfrec7) BASE (vfmin) BASE (vfmax) BASE (vfsgnj) BASE (vfsgnjn) BASE (vfsgnjx) BASE (vfneg) BASE (vfabs) BASE (vmfeq) BASE (vmfne) BASE (vmflt) BASE (vmfgt) BASE (vmfle) BASE (vmfge) BASE (vfclass) BASE (vfmerge) BASE (vfmv_v) BASE (vfcvt_x) BASE (vfcvt_xu) BASE (vfcvt_rtz_x) BASE (vfcvt_rtz_xu) BASE (vfcvt_f) BASE (vfwcvt_x) BASE (vfwcvt_xu) BASE (vfwcvt_rtz_x) BASE (vfwcvt_rtz_xu) BASE (vfwcvt_f) BASE (vfncvt_x) BASE (vfncvt_xu) BASE (vfncvt_rtz_x) BASE (vfncvt_rtz_xu) BASE (vfncvt_f) BASE (vfncvt_rod_f) BASE (vredsum) BASE (vredmaxu) BASE (vredmax) BASE (vredminu) BASE (vredmin) BASE (vredand) BASE (vredor) BASE (vredxor) BASE (vwredsum) BASE (vwredsumu) BASE (vfredusum) BASE (vfredosum) BASE (vfredmax) BASE (vfredmin) BASE (vfwredosum) BASE (vfwredusum) BASE (vmv_x) BASE (vmv_s) BASE (vfmv_f) BASE (vfmv_s) BASE (vslideup) BASE (vslidedown) BASE (vslide1up) BASE (vslide1down) BASE (vfslide1up) BASE (vfslide1down) BASE (vrgather) BASE (vrgatherei16) BASE (vcompress) BASE (vundefined) BASE (vreinterpret) BASE (vlmul_ext) BASE (vlmul_trunc) BASE (vset) BASE (vget) BASE (read_vl) BASE (vleff) BASE (vlenb) BASE (vlseg) BASE (vsseg) BASE (vlsseg) BASE (vssseg) BASE (vluxseg) BASE (vloxseg) BASE (vsuxseg) BASE (vsoxseg) BASE (vlsegff) } // end namespace riscv_vector