Thanks Robin. A couple comments here: + machine_mode op2mode = Pmode; + if (inner == E_QImode || inner == E_HImode || inner == E_SImode) + op2mode = inner; Remove it. + change it into + e.add_input_operand (src2, op2mode == VOIDmode ? GET_MODE (src2) : op2mode); Very confusing here. +(define_code_attr BINOP_TO_UPPERCASE [ + (plus "PLUS") + (minus "MINUS") + (and "AND") + (ior "IOR") + (xor "XOR") + (ashift "ASHIFT") + (ashiftrt "ASHIFTRT") + (lshiftrt "LSHIFTRT") + (smax "SMAX") + (umax "UMAX") + (smin "SMIN") + (umin "UMIN") + (mult "MULT") + (div "DIV") + (udiv "UDIV") + (mod "MOD") + (umod "UMOD") +]) Remove it. Thanks. juzhe.zhong@rivai.ai From: Robin Dapp Date: 2023-05-10 23:24 To: gcc-patches; juzhe.zhong@rivai.ai; Kito Cheng; Michael Collison; palmer; jeffreyalaw CC: rdapp.gcc Subject: [PATCH] riscv: Add vectorized binops and insn_expander helpers. Hi, this patch adds basic binary integer operations support. It is based on Michael Collison's work and makes use of the existing helpers in riscv-c.cc. It introduces emit_nonvlmax_binop which, in turn, uses emit_pred_binop. Setting the destination as well as the mask and the length is factored out into separate functions. There are several things still missing, most notably the scalar variants (.vx) as well as multiplication variants and more. Bootstrapped and regtested. Regards Robin -- gcc/ChangeLog: * config/riscv/autovec.md (3): Add integer binops. * config/riscv/riscv-protos.h (emit_nonvlmax_binop): Declare. * config/riscv/riscv-v.cc (emit_pred_op): New function. (set_expander_dest_and_mask): New function. (emit_pred_binop): New function. (emit_nonvlmax_binop): New function. * config/riscv/vector-iterators.md: Add new code attribute. --- gcc/config/riscv/autovec.md | 33 ++++++++++ gcc/config/riscv/riscv-protos.h | 2 + gcc/config/riscv/riscv-v.cc | 98 ++++++++++++++++++++++------ gcc/config/riscv/vector-iterators.md | 22 +++++++ 4 files changed, 136 insertions(+), 19 deletions(-) diff --git a/gcc/config/riscv/autovec.md b/gcc/config/riscv/autovec.md index f1c5ff5951b..15f8d007e07 100644 --- a/gcc/config/riscv/autovec.md +++ b/gcc/config/riscv/autovec.md @@ -58,3 +58,36 @@ (define_expand "movmisalign" DONE; } ) + +;; ========================================================================= +;; == Binary integer operations +;; ========================================================================= + +(define_expand "3" + [(set (match_operand:VI 0 "register_operand") + (any_int_binop:VI + (match_operand:VI 1 "") + (match_operand:VI 2 "")))] + "TARGET_VECTOR" +{ + if (!register_operand (operands[2], mode)) + { + rtx cst; + gcc_assert (const_vec_duplicate_p(operands[2], &cst)); + machine_mode inner = mode; + machine_mode op2mode = Pmode; + if (inner == E_QImode || inner == E_HImode || inner == E_SImode) + op2mode = inner; + + riscv_vector::emit_nonvlmax_binop (code_for_pred_scalar + (, mode), + operands[0], operands[1], cst, + NULL_RTX, mode, op2mode); + } + else + riscv_vector::emit_nonvlmax_binop (code_for_pred + (, mode), + operands[0], operands[1], operands[2], + NULL_RTX, mode); + DONE; +}) diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h index c0293a306f9..75cdb90b9c9 100644 --- a/gcc/config/riscv/riscv-protos.h +++ b/gcc/config/riscv/riscv-protos.h @@ -169,6 +169,8 @@ void emit_hard_vlmax_vsetvl (machine_mode, rtx); void emit_vlmax_op (unsigned, rtx, rtx, machine_mode); void emit_vlmax_op (unsigned, rtx, rtx, rtx, machine_mode); void emit_nonvlmax_op (unsigned, rtx, rtx, rtx, machine_mode); +void emit_nonvlmax_binop (unsigned, rtx, rtx, rtx, rtx, machine_mode, + machine_mode = VOIDmode); enum vlmul_type get_vlmul (machine_mode); unsigned int get_ratio (machine_mode); unsigned int get_nf (machine_mode); diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc index 7ca49ca67c1..3c43dfc5eea 100644 --- a/gcc/config/riscv/riscv-v.cc +++ b/gcc/config/riscv/riscv-v.cc @@ -53,7 +53,7 @@ namespace riscv_vector { template class insn_expander { public: - insn_expander () : m_opno (0) {} + insn_expander () : m_opno (0), has_dest(false) {} void add_output_operand (rtx x, machine_mode mode) { create_output_operand (&m_ops[m_opno++], x, mode); @@ -84,6 +84,44 @@ public: add_input_operand (gen_int_mode (type, Pmode), Pmode); } + void set_dest_and_mask (rtx mask, rtx dest, machine_mode mask_mode) + { + dest_mode = GET_MODE (dest); + has_dest = true; + + add_output_operand (dest, dest_mode); + + if (mask) + add_input_operand (mask, GET_MODE (mask)); + else + add_all_one_mask_operand (mask_mode); + + add_vundef_operand (dest_mode); + } + + void set_len_and_policy (rtx len, bool vlmax_p) + { + gcc_assert (has_dest); + gcc_assert (len || vlmax_p); + + if (len) + add_input_operand (len, Pmode); + else + { + rtx vlmax = gen_reg_rtx (Pmode); + emit_vlmax_vsetvl (dest_mode, vlmax); + add_input_operand (vlmax, Pmode); + } + + if (GET_MODE_CLASS (dest_mode) != MODE_VECTOR_BOOL) + add_policy_operand (get_prefer_tail_policy (), get_prefer_mask_policy ()); + + if (vlmax_p) + add_avl_type_operand (avl_type::VLMAX); + else + add_avl_type_operand (avl_type::NONVLMAX); + } + void expand (enum insn_code icode, bool temporary_volatile_p = false) { if (temporary_volatile_p) @@ -97,6 +135,8 @@ public: private: int m_opno; + bool has_dest; + machine_mode dest_mode; expand_operand m_ops[MAX_OPERANDS]; }; @@ -190,11 +230,11 @@ autovec_use_vlmax_p (void) } /* Emit an RVV unmask && vl mov from SRC to DEST. */ +template static void -emit_pred_op (unsigned icode, rtx mask, rtx dest, rtx src, rtx len, - machine_mode mask_mode, bool vlmax_p) +set_expander_dest_and_mask (insn_expander &e, rtx mask, rtx dest, + machine_mode mask_mode) { - insn_expander<8> e; machine_mode mode = GET_MODE (dest); e.add_output_operand (dest, mode); @@ -205,29 +245,41 @@ emit_pred_op (unsigned icode, rtx mask, rtx dest, rtx src, rtx len, e.add_all_one_mask_operand (mask_mode); e.add_vundef_operand (mode); +} - e.add_input_operand (src, GET_MODE (src)); - if (len) - e.add_input_operand (len, Pmode); - else - { - rtx vlmax = gen_reg_rtx (Pmode); - emit_vlmax_vsetvl (mode, vlmax); - e.add_input_operand (vlmax, Pmode); - } +/* Emit an RVV unmask && vl mov from SRC to DEST. */ +static void +emit_pred_op (unsigned icode, rtx mask, rtx dest, rtx src, rtx len, + machine_mode mask_mode, bool vlmax_p) +{ + insn_expander<8> e; + e.set_dest_and_mask (mask, dest, mask_mode); - if (GET_MODE_CLASS (mode) != MODE_VECTOR_BOOL) - e.add_policy_operand (get_prefer_tail_policy (), get_prefer_mask_policy ()); + e.add_input_operand (src, GET_MODE (src)); - if (vlmax_p) - e.add_avl_type_operand (avl_type::VLMAX); - else - e.add_avl_type_operand (avl_type::NONVLMAX); + e.set_len_and_policy (len, vlmax_p); e.expand ((enum insn_code) icode, MEM_P (dest) || MEM_P (src)); } +/* Emit an RVV unmask && vl mov from SRC to DEST. */ +static void +emit_pred_binop (unsigned icode, rtx mask, rtx dest, rtx src1, rtx src2, + rtx len, machine_mode mask_mode, machine_mode op2mode, + bool vlmax_p) +{ + insn_expander<9> e; + e.set_dest_and_mask (mask, dest, mask_mode); + + e.add_input_operand (src1, GET_MODE (src1)); + e.add_input_operand (src2, op2mode == VOIDmode ? GET_MODE (src2) : op2mode); + + e.set_len_and_policy (len, vlmax_p); + + e.expand ((enum insn_code) icode, MEM_P (dest) || MEM_P (src1) || MEM_P (src2)); +} + void emit_vlmax_op (unsigned icode, rtx dest, rtx src, machine_mode mask_mode) { @@ -248,6 +300,14 @@ emit_nonvlmax_op (unsigned icode, rtx dest, rtx src, rtx len, emit_pred_op (icode, NULL_RTX, dest, src, len, mask_mode, false); } +void +emit_nonvlmax_binop (unsigned icode, rtx dest, rtx src1, rtx src2, rtx len, + machine_mode mask_mode, machine_mode op2mode) +{ + emit_pred_binop (icode, NULL_RTX, dest, src1, src2, len, mask_mode, op2mode, + false); +} + static void expand_const_vector (rtx target, rtx src, machine_mode mask_mode) { diff --git a/gcc/config/riscv/vector-iterators.md b/gcc/config/riscv/vector-iterators.md index 29c9d77674b..42848627c8c 100644 --- a/gcc/config/riscv/vector-iterators.md +++ b/gcc/config/riscv/vector-iterators.md @@ -1401,6 +1401,26 @@ (define_code_iterator any_int_binop [plus minus and ior xor ashift ashiftrt lshi smax umax smin umin mult div udiv mod umod ]) +(define_code_attr BINOP_TO_UPPERCASE [ + (plus "PLUS") + (minus "MINUS") + (and "AND") + (ior "IOR") + (xor "XOR") + (ashift "ASHIFT") + (ashiftrt "ASHIFTRT") + (lshiftrt "LSHIFTRT") + (smax "SMAX") + (umax "UMAX") + (smin "SMIN") + (umin "UMIN") + (mult "MULT") + (div "DIV") + (udiv "UDIV") + (mod "MOD") + (umod "UMOD") +]) + (define_code_iterator any_int_unop [neg not]) (define_code_iterator any_commutative_binop [plus and ior xor @@ -1409,6 +1429,8 @@ (define_code_iterator any_commutative_binop [plus and ior xor (define_code_iterator any_non_commutative_binop [minus div udiv mod umod]) +(define_code_iterator any_immediate_binop [plus minus and ior xor]) + (define_code_iterator any_sat_int_binop [ss_plus ss_minus us_plus us_minus]) (define_code_iterator sat_int_plus_binop [ss_plus us_plus]) (define_code_iterator sat_int_minus_binop [ss_minus us_minus]) -- 2.40.0