/* function_base implementation for RISC-V 'V' Extension for GNU compiler. Copyright (C) 2022-2024 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, }; enum frm_op_type { NO_FRM, HAS_FRM, }; /* 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); if (TARGET_XTHEADVECTOR) { 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)); } else { /* Normalize same RATO (SEW/LMUL) into same vsetvl instruction. - e8,mf8/e16,mf4/e32,mf2/e64,m1 --> e8mf8 - e8,mf4/e16,mf2/e32,m1/e64,m2 --> e8mf4 - e8,mf2/e16,m1/e32,m2/e64,m4 --> e8mf2 - e8,m1/e16,m2/e32,m4/e64,m8 --> e8m1 - e8,m2/e16,m4/e32,m8 --> e8m2 - e8,m4/e16,m8 --> e8m4 - e8,m8 --> e8m8 */ /* SEW. */ e.add_input_operand (Pmode, gen_int_mode (8, Pmode)); /* LMUL. */ machine_mode e8_mode = get_vector_mode (QImode, GET_MODE_NUNITS (mode)).require (); e.add_input_operand (Pmode, gen_int_mode (get_vlmul (e8_mode), Pmode)); } /* TAIL_ANY. */ e.add_input_operand (Pmode, gen_int_mode (get_prefer_tail_policy (), Pmode)); /* MASK_ANY. */ e.add_input_operand (Pmode, gen_int_mode (get_prefer_mask_policy (), 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 FRM_OP == HAS_FRM; } bool may_require_frm_p () const override { return MAY_REQUIRE_FRM; } rtx expand (function_expander &e) const override { switch (e.op_info->op) { case OP_TYPE_vx: gcc_assert (FRM_OP == NO_FRM); 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: bool has_rounding_mode_operand_p () const override { return FRM_OP == HAS_FRM; } bool may_require_frm_p () const override { return true; } 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. */ 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 (); } } }; /* Implement vfwadd/vfwsub/vfwmul. */ template class widen_binop_fp : public function_base { public: bool has_rounding_mode_operand_p () const override { return FRM_OP == HAS_FRM; } bool may_require_frm_p () const override { return true; } 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: if (CODE == PLUS) return e.use_exact_insn ( code_for_pred_single_widen_add (e.vector_mode ())); else return e.use_exact_insn ( code_for_pred_single_widen_sub (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; } bool may_require_vxrm_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; } bool may_require_vxrm_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: bool has_rounding_mode_operand_p () const override { return FRM_OP == HAS_FRM; } bool may_require_frm_p () const override { return true; } rtx expand (function_expander &e) const override { return e.use_exact_insn ( code_for_pred_reverse_scalar (CODE, e.vector_mode ())); } }; template class vfmacc : public function_base { public: bool has_rounding_mode_operand_p () const override { return FRM_OP == HAS_FRM; } bool may_require_frm_p () const override { return true; } 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 (); } }; template class vfnmsac : public function_base { public: bool has_rounding_mode_operand_p () const override { return FRM_OP == HAS_FRM; } bool may_require_frm_p () const override { return true; } 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 (); } }; template class vfmadd : public function_base { public: bool has_rounding_mode_operand_p () const override { return FRM_OP == HAS_FRM; } bool may_require_frm_p () const override { return true; } 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 (); } }; template class vfnmsub : public function_base { public: bool has_rounding_mode_operand_p () const override { return FRM_OP == HAS_FRM; } bool may_require_frm_p () const override { return true; } 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 (); } }; template class vfnmacc : public function_base { public: bool has_rounding_mode_operand_p () const override { return FRM_OP == HAS_FRM; } bool may_require_frm_p () const override { return true; } 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 (); } }; template class vfmsac : public function_base { public: bool has_rounding_mode_operand_p () const override { return FRM_OP == HAS_FRM; } bool may_require_frm_p () const override { return true; } 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 (); } }; template class vfnmadd : public function_base { public: bool has_rounding_mode_operand_p () const override { return FRM_OP == HAS_FRM; } bool may_require_frm_p () const override { return true; } 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 (); } }; template class vfmsub : public function_base { public: bool has_rounding_mode_operand_p () const override { return FRM_OP == HAS_FRM; } bool may_require_frm_p () const override { return true; } 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 (); } }; template class vfwmacc : public function_base { public: bool has_rounding_mode_operand_p () const override { return FRM_OP == HAS_FRM; } bool may_require_frm_p () const override { return true; } 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 (); } }; template class vfwnmacc : public function_base { public: bool has_rounding_mode_operand_p () const override { return FRM_OP == HAS_FRM; } bool may_require_frm_p () const override { return true; } 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 (); } }; template class vfwmsac : public function_base { public: bool has_rounding_mode_operand_p () const override { return FRM_OP == HAS_FRM; } bool may_require_frm_p () const override { return true; } 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 (); } }; template class vfwnmsac : public function_base { public: bool has_rounding_mode_operand_p () const override { return FRM_OP == HAS_FRM; } bool may_require_frm_p () const override { return true; } 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/vfsgnjx. */ template class float_misc : public function_base { public: bool has_rounding_mode_operand_p () const override { return FRM_OP == HAS_FRM; } bool may_require_frm_p () const override { return true; } 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 vfsgnjn. */ class vfsgnjn : 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_ncopysign_scalar (e.vector_mode ())); if (e.op_info->op == OP_TYPE_vv) return e.use_exact_insn (code_for_pred_ncopysign (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: bool has_rounding_mode_operand_p () const override { return FRM_OP == HAS_FRM; } bool may_require_frm_p () const override { return true; } 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))); } }; template class vfcvt_f : public function_base { public: bool has_rounding_mode_operand_p () const override { return FRM_OP == HAS_FRM; } bool may_require_frm_p () const override { return true; } 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: bool has_rounding_mode_operand_p () const override { return FRM_OP == HAS_FRM; } bool may_require_frm_p () const override { return true; } 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: bool has_rounding_mode_operand_p () const override { return FRM_OP == HAS_FRM; } bool may_require_frm_p () const override { return true; } 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 ())); } }; template class vfncvt_f : public function_base { public: bool has_rounding_mode_operand_p () const override { return FRM_OP == HAS_FRM; } bool may_require_frm_p () const override { return true; } 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 (UNSPEC, e.vector_mode ())); } }; /* Implements floating-point reduction instructions. */ template class freducop : public function_base { public: bool has_rounding_mode_operand_p () const override { return FRM_OP == HAS_FRM; } bool may_require_frm_p () const override { return true; } bool apply_mask_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 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 { if (!e.target) return NULL_RTX; 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 { if (!e.target) return NULL_RTX; 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 vcreate : public function_base { public: gimple *fold (gimple_folder &f) const override { unsigned int nargs = gimple_call_num_args (f.call); tree lhs_type = TREE_TYPE (f.lhs); /* 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 (lhs_type))) return NULL; /* Replace the call with a clobber of the result (to prevent it from becoming upwards exposed) followed by stores into each individual vector of tuple. The fold routines expect the replacement statement to have the same lhs as the original call, so return the clobber statement rather than the final vector store. */ gassign *clobber = gimple_build_assign (f.lhs, build_clobber (lhs_type)); for (unsigned int i = nargs; i-- > 0; ) { tree rhs_vector = gimple_call_arg (f.call, i); tree field = tuple_type_field (TREE_TYPE (f.lhs)); tree lhs_array = build3 (COMPONENT_REF, TREE_TYPE (field), unshare_expr (f.lhs), field, NULL_TREE); tree lhs_vector = build4 (ARRAY_REF, TREE_TYPE (rhs_vector), lhs_array, size_int (i), NULL_TREE, NULL_TREE); gassign *assign = gimple_build_assign (lhs_vector, rhs_vector); gsi_insert_after (f.gsi, assign, GSI_SAME_STMT); } return clobber; } rtx expand (function_expander &e) const override { if (!e.target) return NULL_RTX; gcc_assert (riscv_v_ext_vector_mode_p (GET_MODE (e.target))); unsigned int nargs = call_expr_nargs (e.exp); for (unsigned int i = 0; i < nargs; i++) { rtx src = expand_normal (CALL_EXPR_ARG (e.exp, i)); poly_int64 offset = i * GET_MODE_SIZE (GET_MODE (src)); rtx subreg = simplify_gen_subreg (GET_MODE (src), e.target, GET_MODE (e.target), offset); emit_move_insn (subreg, src); } return e.target; } }; 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 ())); } }; /* Implements * th.vl(b/h/w)[u].v/th.vs(b/h/w)[u].v/th.vls(b/h/w)[u].v/th.vss(b/h/w)[u].v/ * th.vlx(b/h/w)[u].v/th.vs[u]x(b/h/w).v * codegen. */ template class th_loadstore_width : 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 { gcc_assert (TARGET_XTHEADVECTOR); if (LST_TYPE == LST_INDEXED) { if (STORE_P) return e.use_exact_insn ( code_for_pred_indexed_store_width (UNSPEC, UNSPEC, e.vector_mode ())); else return e.use_exact_insn ( code_for_pred_indexed_load_width (UNSPEC, e.vector_mode ())); } else if (LST_TYPE == LST_STRIDED) { if (STORE_P) return e.use_contiguous_store_insn ( code_for_pred_strided_store_width (UNSPEC, e.vector_mode ())); else return e.use_contiguous_load_insn ( code_for_pred_strided_load_width (UNSPEC, e.vector_mode ())); } else { if (STORE_P) return e.use_contiguous_store_insn ( code_for_pred_store_width (UNSPEC, e.vector_mode ())); else return e.use_contiguous_load_insn ( code_for_pred_mov_width (UNSPEC, e.vector_mode ())); } } }; /* Implements vext.x.v. */ class th_extract : 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 { gcc_assert (TARGET_XTHEADVECTOR); return e.use_exact_insn (code_for_pred_th_extract (e.vector_mode ())); } }; /* Below implements are vector crypto */ /* Implements vandn.[vv,vx] */ class vandn : 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_vandn (e.vector_mode ())); case OP_TYPE_vx: return e.use_exact_insn (code_for_pred_vandn_scalar (e.vector_mode ())); default: gcc_unreachable (); } } }; /* Implements vrol/vror/clz/ctz. */ template class bitmanip : public function_base { public: bool apply_tail_policy_p () const override { return (CODE == CLZ || CODE == CTZ) ? false : true; } bool apply_mask_policy_p () const override { return (CODE == CLZ || CODE == CTZ) ? false : true; } bool has_merge_operand_p () const override { return (CODE == CLZ || CODE == CTZ) ? false : true; } rtx expand (function_expander &e) const override { switch (e.op_info->op) { case OP_TYPE_v: case OP_TYPE_vv: return e.use_exact_insn (code_for_pred_v (CODE, e.vector_mode ())); case OP_TYPE_vx: return e.use_exact_insn (code_for_pred_v_scalar (CODE, e.vector_mode ())); default: gcc_unreachable (); } } }; /* Implements vbrev/vbrev8/vrev8. */ template class b_reverse : public function_base { public: rtx expand (function_expander &e) const override { return e.use_exact_insn (code_for_pred_v (UNSPEC, e.vector_mode ())); } }; class vwsll : 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_vwsll (e.vector_mode ())); case OP_TYPE_vx: return e.use_exact_insn (code_for_pred_vwsll_scalar (e.vector_mode ())); default: gcc_unreachable (); } } }; /* Implements clmul */ template class clmul : 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_vclmul (UNSPEC, e.vector_mode ())); case OP_TYPE_vx: return e.use_exact_insn (code_for_pred_vclmul_scalar (UNSPEC, e.vector_mode ())); default: gcc_unreachable (); } } }; /* Implements vghsh/vsh2ms/vsha2c[hl]. */ template class vg_nhab : public function_base { public: 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_v (UNSPEC, e.vector_mode ())); } }; /* Implements vgmul/vaes*. */ template class crypto_vv : public function_base { public: 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 { poly_uint64 nunits = 0U; switch (e.op_info->op) { case OP_TYPE_vv: if (UNSPEC == UNSPEC_VGMUL) return e.use_exact_insn (code_for_pred_crypto_vv (UNSPEC, UNSPEC, e.vector_mode ())); else return e.use_exact_insn (code_for_pred_crypto_vv (UNSPEC + 1, UNSPEC + 1, e.vector_mode ())); case OP_TYPE_vs: /* Calculate the ratio between arg0 and arg1*/ gcc_assert (multiple_p (GET_MODE_BITSIZE (e.arg_mode (0)), GET_MODE_BITSIZE (e.arg_mode (1)), &nunits)); if (maybe_eq (nunits, 1U)) return e.use_exact_insn (code_for_pred_crypto_vvx1_scalar (UNSPEC + 2, UNSPEC + 2, e.vector_mode ())); else if (maybe_eq (nunits, 2U)) return e.use_exact_insn (code_for_pred_crypto_vvx2_scalar (UNSPEC + 2, UNSPEC + 2, e.vector_mode ())); else if (maybe_eq (nunits, 4U)) return e.use_exact_insn (code_for_pred_crypto_vvx4_scalar (UNSPEC + 2, UNSPEC + 2, e.vector_mode ())); else if (maybe_eq (nunits, 8U)) return e.use_exact_insn (code_for_pred_crypto_vvx8_scalar (UNSPEC + 2, UNSPEC + 2, e.vector_mode ())); else return e.use_exact_insn (code_for_pred_crypto_vvx16_scalar (UNSPEC + 2, UNSPEC + 2, e.vector_mode ())); default: gcc_unreachable (); } } }; /* Implements vaeskf1/vsm4k. */ template class crypto_vi : 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_crypto_vi_scalar (UNSPEC, e.vector_mode ())); } }; /* Implements vaeskf2/vsm3c. */ template class vaeskf2_vsm3c : public function_base { public: 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_vi_nomaskedoff_scalar (UNSPEC, e.vector_mode ())); } }; /* Implements vsm3me. */ class vsm3me : 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_vsm3me (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 binop vfadd_frm_obj; static CONSTEXPR const binop vfsub_frm_obj; static CONSTEXPR const reverse_binop vfrsub_obj; static CONSTEXPR const reverse_binop vfrsub_frm_obj; static CONSTEXPR const widen_binop_fp vfwadd_obj; static CONSTEXPR const widen_binop_fp vfwadd_frm_obj; static CONSTEXPR const widen_binop_fp vfwsub_obj; static CONSTEXPR const widen_binop_fp vfwsub_frm_obj; static CONSTEXPR const binop vfmul_obj; static CONSTEXPR const binop vfmul_frm_obj; static CONSTEXPR const binop vfdiv_obj; static CONSTEXPR const binop vfdiv_frm_obj; static CONSTEXPR const reverse_binop
vfrdiv_obj; static CONSTEXPR const reverse_binop vfrdiv_frm_obj; static CONSTEXPR const widen_binop_fp vfwmul_obj; static CONSTEXPR const widen_binop_fp vfwmul_frm_obj; static CONSTEXPR const vfmacc vfmacc_obj; static CONSTEXPR const vfmacc vfmacc_frm_obj; static CONSTEXPR const vfnmsac vfnmsac_obj; static CONSTEXPR const vfnmsac vfnmsac_frm_obj; static CONSTEXPR const vfmadd vfmadd_obj; static CONSTEXPR const vfmadd vfmadd_frm_obj; static CONSTEXPR const vfnmsub vfnmsub_obj; static CONSTEXPR const vfnmsub vfnmsub_frm_obj; static CONSTEXPR const vfnmacc vfnmacc_obj; static CONSTEXPR const vfnmacc vfnmacc_frm_obj; static CONSTEXPR const vfmsac vfmsac_obj; static CONSTEXPR const vfmsac vfmsac_frm_obj; static CONSTEXPR const vfnmadd vfnmadd_obj; static CONSTEXPR const vfnmadd vfnmadd_frm_obj; static CONSTEXPR const vfmsub vfmsub_obj; static CONSTEXPR const vfmsub vfmsub_frm_obj; static CONSTEXPR const vfwmacc vfwmacc_obj; static CONSTEXPR const vfwmacc vfwmacc_frm_obj; static CONSTEXPR const vfwnmacc vfwnmacc_obj; static CONSTEXPR const vfwnmacc vfwnmacc_frm_obj; static CONSTEXPR const vfwmsac vfwmsac_obj; static CONSTEXPR const vfwmsac vfwmsac_frm_obj; static CONSTEXPR const vfwnmsac vfwnmsac_obj; static CONSTEXPR const vfwnmsac vfwnmsac_frm_obj; static CONSTEXPR const unop vfsqrt_obj; static CONSTEXPR const unop vfsqrt_frm_obj; static CONSTEXPR const float_misc vfrsqrt7_obj; static CONSTEXPR const float_misc vfrec7_obj; static CONSTEXPR const float_misc vfrec7_frm_obj; static CONSTEXPR const binop vfmin_obj; static CONSTEXPR const binop vfmax_obj; static CONSTEXPR const float_misc vfsgnj_obj; static CONSTEXPR const vfsgnjn 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_x_frm_obj; static CONSTEXPR const vfcvt_x vfcvt_xu_obj; static CONSTEXPR const vfcvt_x vfcvt_xu_frm_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 vfcvt_f vfcvt_f_frm_obj; static CONSTEXPR const vfwcvt_x vfwcvt_x_obj; static CONSTEXPR const vfwcvt_x vfwcvt_x_frm_obj; static CONSTEXPR const vfwcvt_x vfwcvt_xu_obj; static CONSTEXPR const vfwcvt_x vfwcvt_xu_frm_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_x_frm_obj; static CONSTEXPR const vfncvt_x vfncvt_xu_obj; static CONSTEXPR const vfncvt_x vfncvt_xu_frm_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_f vfncvt_f_frm_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 reducop vwredsum_obj; static CONSTEXPR const reducop vwredsumu_obj; static CONSTEXPR const freducop vfredusum_obj; static CONSTEXPR const freducop vfredusum_frm_obj; static CONSTEXPR const freducop vfredosum_obj; static CONSTEXPR const freducop vfredosum_frm_obj; static CONSTEXPR const reducop vfredmax_obj; static CONSTEXPR const reducop vfredmin_obj; static CONSTEXPR const freducop vfwredusum_obj; static CONSTEXPR const freducop vfwredusum_frm_obj; static CONSTEXPR const freducop vfwredosum_obj; static CONSTEXPR const freducop vfwredosum_frm_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 vcreate vcreate_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; static CONSTEXPR const th_loadstore_width vlb_obj; static CONSTEXPR const th_loadstore_width vlbu_obj; static CONSTEXPR const th_loadstore_width vlh_obj; static CONSTEXPR const th_loadstore_width vlhu_obj; static CONSTEXPR const th_loadstore_width vlw_obj; static CONSTEXPR const th_loadstore_width vlwu_obj; static CONSTEXPR const th_loadstore_width vsb_obj; static CONSTEXPR const th_loadstore_width vsh_obj; static CONSTEXPR const th_loadstore_width vsw_obj; static CONSTEXPR const th_loadstore_width vlsb_obj; static CONSTEXPR const th_loadstore_width vlsbu_obj; static CONSTEXPR const th_loadstore_width vlsh_obj; static CONSTEXPR const th_loadstore_width vlshu_obj; static CONSTEXPR const th_loadstore_width vlsw_obj; static CONSTEXPR const th_loadstore_width vlswu_obj; static CONSTEXPR const th_loadstore_width vssb_obj; static CONSTEXPR const th_loadstore_width vssh_obj; static CONSTEXPR const th_loadstore_width vssw_obj; static CONSTEXPR const th_loadstore_width vlxb_obj; static CONSTEXPR const th_loadstore_width vlxbu_obj; static CONSTEXPR const th_loadstore_width vlxh_obj; static CONSTEXPR const th_loadstore_width vlxhu_obj; static CONSTEXPR const th_loadstore_width vlxw_obj; static CONSTEXPR const th_loadstore_width vlxwu_obj; static CONSTEXPR const th_loadstore_width vsxb_obj; static CONSTEXPR const th_loadstore_width vsxh_obj; static CONSTEXPR const th_loadstore_width vsxw_obj; static CONSTEXPR const th_loadstore_width vsuxb_obj; static CONSTEXPR const th_loadstore_width vsuxh_obj; static CONSTEXPR const th_loadstore_width vsuxw_obj; static CONSTEXPR const th_extract vext_x_v_obj; /* Crypto Vector */ static CONSTEXPR const vandn vandn_obj; static CONSTEXPR const bitmanip vrol_obj; static CONSTEXPR const bitmanip vror_obj; static CONSTEXPR const b_reverse vbrev_obj; static CONSTEXPR const b_reverse vbrev8_obj; static CONSTEXPR const b_reverse vrev8_obj; static CONSTEXPR const bitmanip vclz_obj; static CONSTEXPR const bitmanip vctz_obj; static CONSTEXPR const vwsll vwsll_obj; static CONSTEXPR const clmul vclmul_obj; static CONSTEXPR const clmul vclmulh_obj; static CONSTEXPR const vg_nhab vghsh_obj; static CONSTEXPR const crypto_vv vgmul_obj; static CONSTEXPR const crypto_vv vaesef_obj; static CONSTEXPR const crypto_vv vaesem_obj; static CONSTEXPR const crypto_vv vaesdf_obj; static CONSTEXPR const crypto_vv vaesdm_obj; static CONSTEXPR const crypto_vv vaesz_obj; static CONSTEXPR const crypto_vi vaeskf1_obj; static CONSTEXPR const vaeskf2_vsm3c vaeskf2_obj; static CONSTEXPR const vg_nhab vsha2ms_obj; static CONSTEXPR const vg_nhab vsha2ch_obj; static CONSTEXPR const vg_nhab vsha2cl_obj; static CONSTEXPR const crypto_vi vsm4k_obj; static CONSTEXPR const crypto_vv vsm4r_obj; static CONSTEXPR const vsm3me vsm3me_obj; static CONSTEXPR const vaeskf2_vsm3c vsm3c_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 (vfadd_frm) BASE (vfsub) BASE (vfsub_frm) BASE (vfrsub) BASE (vfrsub_frm) BASE (vfwadd) BASE (vfwadd_frm) BASE (vfwsub) BASE (vfwsub_frm) BASE (vfmul) BASE (vfmul_frm) BASE (vfdiv) BASE (vfdiv_frm) BASE (vfrdiv) BASE (vfrdiv_frm) BASE (vfwmul) BASE (vfwmul_frm) BASE (vfmacc) BASE (vfmacc_frm) BASE (vfnmsac) BASE (vfnmsac_frm) BASE (vfmadd) BASE (vfmadd_frm) BASE (vfnmsub) BASE (vfnmsub_frm) BASE (vfnmacc) BASE (vfnmacc_frm) BASE (vfmsac) BASE (vfmsac_frm) BASE (vfnmadd) BASE (vfnmadd_frm) BASE (vfmsub) BASE (vfmsub_frm) BASE (vfwmacc) BASE (vfwmacc_frm) BASE (vfwnmacc) BASE (vfwnmacc_frm) BASE (vfwmsac) BASE (vfwmsac_frm) BASE (vfwnmsac) BASE (vfwnmsac_frm) BASE (vfsqrt) BASE (vfsqrt_frm) BASE (vfrsqrt7) BASE (vfrec7) BASE (vfrec7_frm) 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_x_frm) BASE (vfcvt_xu) BASE (vfcvt_xu_frm) BASE (vfcvt_rtz_x) BASE (vfcvt_rtz_xu) BASE (vfcvt_f) BASE (vfcvt_f_frm) BASE (vfwcvt_x) BASE (vfwcvt_x_frm) BASE (vfwcvt_xu) BASE (vfwcvt_xu_frm) BASE (vfwcvt_rtz_x) BASE (vfwcvt_rtz_xu) BASE (vfwcvt_f) BASE (vfncvt_x) BASE (vfncvt_x_frm) BASE (vfncvt_xu) BASE (vfncvt_xu_frm) BASE (vfncvt_rtz_x) BASE (vfncvt_rtz_xu) BASE (vfncvt_f) BASE (vfncvt_f_frm) 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 (vfredusum_frm) BASE (vfredosum) BASE (vfredosum_frm) BASE (vfredmax) BASE (vfredmin) BASE (vfwredosum) BASE (vfwredosum_frm) BASE (vfwredusum) BASE (vfwredusum_frm) 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 (vcreate) 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) BASE (vlb) BASE (vlh) BASE (vlw) BASE (vlbu) BASE (vlhu) BASE (vlwu) BASE (vsb) BASE (vsh) BASE (vsw) BASE (vlsb) BASE (vlsh) BASE (vlsw) BASE (vlsbu) BASE (vlshu) BASE (vlswu) BASE (vssb) BASE (vssh) BASE (vssw) BASE (vlxb) BASE (vlxh) BASE (vlxw) BASE (vlxbu) BASE (vlxhu) BASE (vlxwu) BASE (vsxb) BASE (vsxh) BASE (vsxw) BASE (vsuxb) BASE (vsuxh) BASE (vsuxw) BASE (vext_x_v) /* Crypto vector */ BASE (vandn) BASE (vbrev) BASE (vbrev8) BASE (vrev8) BASE (vclz) BASE (vctz) BASE (vrol) BASE (vror) BASE (vwsll) BASE (vclmul) BASE (vclmulh) BASE (vghsh) BASE (vgmul) BASE (vaesef) BASE (vaesem) BASE (vaesdf) BASE (vaesdm) BASE (vaesz) BASE (vaeskf1) BASE (vaeskf2) BASE (vsha2ms) BASE (vsha2ch) BASE (vsha2cl) BASE (vsm4k) BASE (vsm4r) BASE (vsm3me) BASE (vsm3c) } // end namespace riscv_vector