Message ID | 0fe6c64c-46e2-3e5f-38d6-a20e26234592@gmail.com |
---|---|
State | New |
Headers | show |
Series | RISC-V: Implement autovec abs, vneg, vnot. | expand |
>> + TAIL_UNDEFINED = -1, >> + MASK_UNDEFINED = -1, Why you add this ? >> + void add_policy_operands (enum tail_policy vta = TAIL_UNDEFINED, >> + enum mask_policy vma = MASK_UNDEFINED) No, you should just specify this as TAIL_ANY or MASK_ANY as default value. >>const_vlmax_p (machine_mode mode) >>{ >>- poly_uint64 nuints = GET_MODE_NUNITS (mode); >>+ poly_uint64 nunits = GET_MODE_NUNITS (mode); >>- return nuints.is_constant () >>+ return nunits.is_constant () >> /* The vsetivli can only hold register 0~31. */ >>- ? (IN_RANGE (nuints.to_constant (), 0, 31)) >>+ ? (IN_RANGE (nunits.to_constant (), 0, 31)) >> /* Only allowed in VLS-VLMAX mode. */ >> : false; >>} Meaningless change ? >> /* For the instruction that doesn't require TA, we still need a default value >> to emit vsetvl. We pick up the default value according to prefer policy. */ >> - return (bool) (get_prefer_tail_policy () & 0x1 >> - || (get_prefer_tail_policy () >> 1 & 0x1)); >> + return (bool) (get_preferred_tail_policy () & 0x1 >> + || (get_preferred_tail_policy () >> 1 & 0x1)); >> } >> /* Get default mask policy. */ >> @@ -576,8 +576,8 @@ get_default_ma () >> { >> /* For the instruction that doesn't require MA, we still need a default value >> to emit vsetvl. We pick up the default value according to prefer policy. */ >> - return (bool) (get_prefer_mask_policy () & 0x1 >> - || (get_prefer_mask_policy () >> 1 & 0x1)); >> + return (bool) (get_preferred_mask_policy () & 0x1 >> + || (get_preferred_mask_policy () >> 1 & 0x1)); Why you change it ? >> +/* Emit an RVV comparison. */ >> +static void >> +emit_pred_cmp (unsigned icode, rtx mask, rtx dest, rtx cmp, >> + rtx src1, rtx src2, >> + rtx len, machine_mode mask_mode) >> +{ >> + insn_expander<9> e; >> + >> + e.set_dest_and_mask (dest, mask, mask_mode); >> + >> + e.add_input_operand (cmp, GET_MODE (cmp)); >> + >> + e.add_source_operand (src1, GET_MODE (src1)); >> + e.add_source_operand (src2, GET_MODE (src2)); You are using comparison helper which I added one in my downstream when I am working on comparison autovec patterns: I think you can normalize my code with yours: /* Emit an RVV comparison. If one of SRC1 and SRC2 is a scalar operand, its data_mode is specified using SCALAR_MODE. */ static void emit_pred_comparison (unsigned icode, rtx_code rcode, rtx mask, rtx dest, rtx src1, rtx src2, rtx len, machine_mode mask_mode, machine_mode scalar_mode = VOIDmode) { insn_expander<9> e; e.set_dest_and_mask (mask, dest, mask_mode); machine_mode data_mode = GET_MODE (src1); gcc_assert (VECTOR_MODE_P (GET_MODE (src1)) || VECTOR_MODE_P (GET_MODE (src2))); if (!insn_operand_matches ((enum insn_code) icode, e.opno () + 1, src1)) src1 = force_reg (data_mode, src1); if (!insn_operand_matches ((enum insn_code) icode, e.opno () + 2, src2)) { if (VECTOR_MODE_P (GET_MODE (src2))) src2 = force_reg (data_mode, src2); else src2 = force_reg (scalar_mode, src2); } rtx comparison = gen_rtx_fmt_ee (rcode, mask_mode, src1, src2); if (!VECTOR_MODE_P (GET_MODE (src2))) comparison = gen_rtx_fmt_ee (rcode, mask_mode, src1, gen_rtx_VEC_DUPLICATE (data_mode, src2)); e.add_fixed_operand (comparison); e.add_fixed_operand (src1); if (CONST_INT_P (src2)) e.add_integer_operand (src2); else e.add_fixed_operand (src2); e.set_len_and_policy (len, true, false, true); e.expand ((enum insn_code) icode, false); } static void emit_len_comparison (unsigned icode, rtx_code rcode, rtx dest, rtx src1, rtx src2, rtx len, machine_mode mask_mode, machine_mode scalar_mode) { emit_pred_comparison (icode, rcode, NULL_RTX, dest, src1, src2, len, mask_mode, scalar_mode); } /* Expand an RVV integer comparison using the RVV equivalent of: (set TARGET (CODE OP0 OP1)). */ void expand_vec_cmp_int (rtx target, rtx_code code, rtx op0, rtx op1) { machine_mode mask_mode = GET_MODE (target); machine_mode data_mode = GET_MODE (op0); insn_code icode; bool scalar_p = false; if (CONST_VECTOR_P (op1)) { rtx elt; if (const_vec_duplicate_p (op1, &elt)) op1 = elt; scalar_p = true; } switch (code) { case LE: case LEU: case GT: case GTU: if (scalar_p) icode = code_for_pred_cmp_scalar (data_mode); else icode = code_for_pred_cmp (data_mode); break; case EQ: case NE: if (scalar_p) icode = code_for_pred_eqne_scalar (data_mode); else icode = code_for_pred_cmp (data_mode); break; case LT: case LTU: if (scalar_p) icode = code_for_pred_cmp_scalar (data_mode); else icode = code_for_pred_ltge (data_mode); break; case GE: case GEU: if (scalar_p) icode = code_for_pred_ge_scalar (data_mode); else icode = code_for_pred_ltge (data_mode); break; default: break; } emit_len_comparison (icode, code, target, op0, op1, NULL, mask_mode, GET_MODE_INNER (data_mode)); } This is how I use it: (define_expand "vec_cmp<mode><vm>" [(set (match_operand:<VM> 0 "register_operand") (match_operator:<VM> 1 "comparison_operator" [(match_operand:VI 2 "register_operand") (match_operand:VI 3 "nonmemory_operand")]))] "TARGET_VECTOR" { riscv_vector::expand_vec_cmp_int (operands[0], GET_CODE (operands[1]), operands[2], operands[3]); DONE; } ) I am almost done all comparison autovec patterns, soon will send them after testing. Thanks. juzhe.zhong@rivai.ai From: Robin Dapp Date: 2023-05-19 19:32 To: gcc-patches; Kito Cheng; juzhe.zhong@rivai.ai; palmer; Michael Collison; jeffreyalaw CC: rdapp.gcc Subject: [PATCH] RISC-V: Implement autovec abs, vneg, vnot. Hi, this patch implements autovec expanders of abs<mode>2, vneg<mode>2 and vnot<mode>2 for integers. I also tried to refactor the helper code in riscv-v.cc a bit. Guess it's not enough to warrant a separate patch though. Regards Robin gcc/ChangeLog: * config/riscv/autovec.md (<optab><mode>2): Fix typo. (abs<mode>2): New expander. * config/riscv/riscv-protos.h (emit_len_masked_op): Declare. (emit_len_cmp): Declare. (enum tail_policy): Add undefined. (enum mask_policy): Add undefined. * config/riscv/riscv-v.cc (const_vlmax_p): Fix typo. (emit_pred_op): Swap mask and dest. (emit_pred_binop): Dito. (emit_pred_cmp_op): Dito. (emit_vlmax_reg_op): Dito. (emit_len_masked_op): New function. (emit_len_cmp): New function. (emit_index_op): Use helper function. (get_prefer_tail_policy): Rename. (get_preferred_tail_policy): To this. (get_prefer_mask_policy): Rename. (get_preferred_mask_policy): To this. (slide1_sew64_helper): Dito. * config/riscv/riscv-vector-builtins.cc (get_tail_policy_for_pred): Dito. (get_mask_policy_for_pred): Dito. * config/riscv/riscv-vsetvl.cc (get_default_ta): Dito. (get_default_ma): Dito. gcc/testsuite/ChangeLog: * gcc.target/riscv/rvv/autovec/unop/abs-run.c: New test. * gcc.target/riscv/rvv/autovec/unop/abs-rv32gcv.c: New test. * gcc.target/riscv/rvv/autovec/unop/abs-rv64gcv.c: New test. * gcc.target/riscv/rvv/autovec/unop/abs-template.h: New test. * gcc.target/riscv/rvv/autovec/unop/vneg-run.c: New test. * gcc.target/riscv/rvv/autovec/unop/vneg-rv32gcv.c: New test. * gcc.target/riscv/rvv/autovec/unop/vneg-rv64gcv.c: New test. * gcc.target/riscv/rvv/autovec/unop/vneg-template.h: New test. * gcc.target/riscv/rvv/autovec/unop/vnot-run.c: New test. * gcc.target/riscv/rvv/autovec/unop/vnot-rv32gcv.c: New test. * gcc.target/riscv/rvv/autovec/unop/vnot-rv64gcv.c: New test. * gcc.target/riscv/rvv/autovec/unop/vnot-template.h: New test. --- gcc/config/riscv/autovec.md | 51 +++++- gcc/config/riscv/riscv-protos.h | 8 +- gcc/config/riscv/riscv-v.cc | 146 ++++++++++++++---- gcc/config/riscv/riscv-vector-builtins.cc | 4 +- gcc/config/riscv/riscv-vsetvl.cc | 8 +- .../riscv/rvv/autovec/unop/abs-run.c | 29 ++++ .../riscv/rvv/autovec/unop/abs-rv32gcv.c | 7 + .../riscv/rvv/autovec/unop/abs-rv64gcv.c | 7 + .../riscv/rvv/autovec/unop/abs-template.h | 26 ++++ .../riscv/rvv/autovec/unop/vneg-run.c | 29 ++++ .../riscv/rvv/autovec/unop/vneg-rv32gcv.c | 6 + .../riscv/rvv/autovec/unop/vneg-rv64gcv.c | 6 + .../riscv/rvv/autovec/unop/vneg-template.h | 17 ++ .../riscv/rvv/autovec/unop/vnot-run.c | 33 ++++ .../riscv/rvv/autovec/unop/vnot-rv32gcv.c | 6 + .../riscv/rvv/autovec/unop/vnot-rv64gcv.c | 6 + .../riscv/rvv/autovec/unop/vnot-template.h | 21 +++ gcc/testsuite/gcc.target/riscv/rvv/rvv.exp | 2 + 18 files changed, 377 insertions(+), 35 deletions(-) create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-run.c create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-rv32gcv.c create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-rv64gcv.c create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-template.h create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-run.c create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-rv32gcv.c create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-rv64gcv.c create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-template.h create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-run.c create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-rv32gcv.c create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-rv64gcv.c create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-template.h diff --git a/gcc/config/riscv/autovec.md b/gcc/config/riscv/autovec.md index ce0b46537ad..8060a5cdf90 100644 --- a/gcc/config/riscv/autovec.md +++ b/gcc/config/riscv/autovec.md @@ -161,7 +161,7 @@ (define_expand "<optab><mode>3" }) ;; ------------------------------------------------------------------------- -;; ---- [INT] Binary shifts by scalar. +;; ---- [INT] Binary shifts by vector. ;; ------------------------------------------------------------------------- ;; Includes: ;; - vsll.vv/vsra.vv/vsrl.vv @@ -180,3 +180,52 @@ (define_expand "v<optab><mode>3" NULL_RTX, <VM>mode); DONE; }) + +;; ========================================================================= +;; == Unary arithmetic +;; ========================================================================= + +;; ------------------------------------------------------------------------------- +;; ---- [INT] Unary operations +;; ------------------------------------------------------------------------------- +;; Includes: +;; - vneg.v/vnot.v +;; ------------------------------------------------------------------------------- +(define_expand "<optab><mode>2" + [(set (match_operand:VI 0 "register_operand") + (any_int_unop:VI + (match_operand:VI 1 "register_operand")))] + "TARGET_VECTOR" +{ + riscv_vector::emit_len_op (code_for_pred (<CODE>, <MODE>mode), + operands[0], operands[1], NULL_RTX, <VM>mode); + DONE; +}) + +;; ------------------------------------------------------------------------------- +;; - ABS expansion to vmslt and vneg +;; ------------------------------------------------------------------------------- + +(define_expand "abs<mode>2" + [(set (match_operand:VI 0 "register_operand") + (match_operand:VI 1 "register_operand"))] + "TARGET_VECTOR" +{ + // Create a zero constant. + rtx zero = gen_const_vec_duplicate (<MODE>mode, GEN_INT (0)); + + // Compare the source vector against it. + rtx ltcmp = gen_rtx_LT (<VM>mode, operands[1], zero); + + // Mask out all non-negative elements. + rtx mask = gen_reg_rtx (<VM>mode); + riscv_vector::emit_len_cmp (code_for_pred_ltge (<MODE>mode), + mask, ltcmp, operands[1], zero, + NULL_RTX, <VM>mode); + + // Emit a masked vneg, negating only the negative elements. + riscv_vector::emit_masked_len_op (code_for_pred (NEG, <MODE>mode), + mask, operands[0], operands[1], + NULL_RTX, <VM>mode); + DONE; +}) diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h index 12634d0ac1a..7c588086fa0 100644 --- a/gcc/config/riscv/riscv-protos.h +++ b/gcc/config/riscv/riscv-protos.h @@ -171,6 +171,8 @@ void emit_vlmax_reg_op (unsigned, rtx, rtx, rtx, machine_mode); void emit_len_op (unsigned, rtx, rtx, rtx, machine_mode); void emit_len_binop (unsigned, rtx, rtx, rtx, rtx, machine_mode, machine_mode = VOIDmode); +void emit_masked_len_op (unsigned, rtx, rtx, rtx, rtx, machine_mode); +void emit_len_cmp (unsigned, rtx, rtx, rtx, rtx, rtx, machine_mode); enum vlmul_type get_vlmul (machine_mode); unsigned int get_ratio (machine_mode); unsigned int get_nf (machine_mode); @@ -181,6 +183,7 @@ int get_avl_type (rtx); unsigned int calculate_ratio (unsigned int, enum vlmul_type); enum tail_policy { + TAIL_UNDEFINED = -1, TAIL_UNDISTURBED = 0, TAIL_AGNOSTIC = 1, TAIL_ANY = 2, @@ -188,12 +191,13 @@ enum tail_policy enum mask_policy { + MASK_UNDEFINED = -1, MASK_UNDISTURBED = 0, MASK_AGNOSTIC = 1, MASK_ANY = 2, }; -enum tail_policy get_prefer_tail_policy (); -enum mask_policy get_prefer_mask_policy (); +enum tail_policy get_preferred_tail_policy (); +enum mask_policy get_preferred_mask_policy (); rtx get_avl_type_rtx (enum avl_type); opt_machine_mode get_vector_mode (scalar_mode, poly_uint64); opt_machine_mode get_tuple_mode (machine_mode, unsigned int); diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc index d65e7300303..64ad3970267 100644 --- a/gcc/config/riscv/riscv-v.cc +++ b/gcc/config/riscv/riscv-v.cc @@ -54,11 +54,11 @@ namespace riscv_vector { static bool const_vlmax_p (machine_mode mode) { - poly_uint64 nuints = GET_MODE_NUNITS (mode); + poly_uint64 nunits = GET_MODE_NUNITS (mode); - return nuints.is_constant () + return nunits.is_constant () /* The vsetivli can only hold register 0~31. */ - ? (IN_RANGE (nuints.to_constant (), 0, 31)) + ? (IN_RANGE (nunits.to_constant (), 0, 31)) /* Only allowed in VLS-VLMAX mode. */ : false; } @@ -66,38 +66,68 @@ const_vlmax_p (machine_mode mode) template <int MAX_OPERANDS> class insn_expander { public: - insn_expander () : m_opno (0), has_dest(false) {} + 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); gcc_assert (m_opno <= MAX_OPERANDS); } + + void add_source_operand (rtx x, machine_mode mode) + { + add_src (x); + add_input_operand (x, mode); + } + void add_input_operand (rtx x, machine_mode mode) { create_input_operand (&m_ops[m_opno++], x, mode); gcc_assert (m_opno <= MAX_OPERANDS); } + void add_all_one_mask_operand (machine_mode mode) { add_input_operand (CONSTM1_RTX (mode), mode); } + void add_vundef_operand (machine_mode mode) { add_input_operand (RVV_VUNDEF (mode), mode); } - void add_policy_operand (enum tail_policy vta, enum mask_policy vma) + + void add_policy_operands (enum tail_policy vta = TAIL_UNDEFINED, + enum mask_policy vma = MASK_UNDEFINED) { - rtx tail_policy_rtx = gen_int_mode (vta, Pmode); - rtx mask_policy_rtx = gen_int_mode (vma, Pmode); - add_input_operand (tail_policy_rtx, Pmode); - add_input_operand (mask_policy_rtx, Pmode); + /* If no policies were specified, use the default ones. */ + if (vta == TAIL_UNDEFINED) + vta = get_preferred_tail_policy (); + if (vma == MASK_UNDEFINED) + vma = get_preferred_mask_policy (); + + /* RVV Spec 3.4.3. + Mask destination tail elements are always treated as tail-agnostic, + regardless of the setting of vta. */ + if (!is_mask_destination_instruction ()) + { + rtx tail_policy_rtx = gen_int_mode (vta, Pmode); + add_input_operand (tail_policy_rtx, Pmode); + } + + /* RVV Spec 15.1. + Vector mask logical instructions are always unmasked. */ + if (!is_mask_logical_instruction ()) + { + rtx mask_policy_rtx = gen_int_mode (vma, Pmode); + add_input_operand (mask_policy_rtx, Pmode); + } } void add_avl_type_operand (avl_type type) { add_input_operand (gen_int_mode (type, Pmode), Pmode); } - void set_dest_and_mask (rtx mask, rtx dest, machine_mode mask_mode) + void set_dest_and_mask (rtx dest, rtx mask, machine_mode mask_mode) { dest_mode = GET_MODE (dest); has_dest = true; @@ -133,8 +163,7 @@ public: add_input_operand (len, Pmode); - if (GET_MODE_CLASS (dest_mode) != MODE_VECTOR_BOOL) - add_policy_operand (get_prefer_tail_policy (), get_prefer_mask_policy ()); + add_policy_operands (); add_avl_type_operand (vlmax_p ? avl_type::VLMAX : avl_type::NONVLMAX); } @@ -150,9 +179,36 @@ public: expand_insn (icode, m_opno, m_ops); } + bool is_mask_destination_instruction () + { + gcc_assert (has_dest); + return (GET_MODE_CLASS (dest_mode) == MODE_VECTOR_BOOL); + } + + bool is_mask_logical_instruction () + { + if (!is_mask_destination_instruction ()) + return false; + + if (!srcs.length ()) + return false; + + for (rtx src : srcs) + if (GET_MODE_CLASS (GET_MODE (src)) != MODE_VECTOR_BOOL) + return false; + + return true; + } + + void add_src (rtx src) + { + srcs.quick_push (src); + } + private: int m_opno; bool has_dest; + auto_vec<rtx, 3> srcs; machine_mode dest_mode; expand_operand m_ops[MAX_OPERANDS]; }; @@ -252,9 +308,9 @@ emit_pred_op (unsigned icode, rtx mask, rtx dest, rtx src, rtx len, machine_mode mask_mode, bool force_vlmax = false) { insn_expander<8> e; - e.set_dest_and_mask (mask, dest, mask_mode); + e.set_dest_and_mask (dest, mask, mask_mode); - e.add_input_operand (src, GET_MODE (src)); + e.add_source_operand (src, GET_MODE (src)); e.set_len_and_policy (len, force_vlmax); @@ -269,20 +325,40 @@ emit_pred_binop (unsigned icode, rtx mask, rtx dest, rtx src1, rtx src2, machine_mode scalar_mode = VOIDmode) { insn_expander<9> e; - e.set_dest_and_mask (mask, dest, mask_mode); + e.set_dest_and_mask (dest, mask, mask_mode); gcc_assert (VECTOR_MODE_P (GET_MODE (src1)) || VECTOR_MODE_P (GET_MODE (src2))); if (VECTOR_MODE_P (GET_MODE (src1))) - e.add_input_operand (src1, GET_MODE (src1)); + e.add_source_operand (src1, GET_MODE (src1)); else - e.add_input_operand (src1, scalar_mode); + e.add_source_operand (src1, scalar_mode); if (VECTOR_MODE_P (GET_MODE (src2))) - e.add_input_operand (src2, GET_MODE (src2)); + e.add_source_operand (src2, GET_MODE (src2)); else - e.add_input_operand (src2, scalar_mode); + e.add_source_operand (src2, scalar_mode); + + e.set_len_and_policy (len); + + e.expand ((enum insn_code) icode, MEM_P (dest) || MEM_P (src1) || MEM_P (src2)); +} + +/* Emit an RVV comparison. */ +static void +emit_pred_cmp (unsigned icode, rtx mask, rtx dest, rtx cmp, + rtx src1, rtx src2, + rtx len, machine_mode mask_mode) +{ + insn_expander<9> e; + + e.set_dest_and_mask (dest, mask, mask_mode); + + e.add_input_operand (cmp, GET_MODE (cmp)); + + e.add_source_operand (src1, GET_MODE (src1)); + e.add_source_operand (src2, GET_MODE (src2)); e.set_len_and_policy (len); @@ -332,6 +408,8 @@ emit_vlmax_reg_op (unsigned icode, rtx dest, rtx src, rtx len, /* Force VLMAX */ true); } +/* Emit a binary operation with sources SRC1 and SRC2 and a given length + LEN. */ void emit_len_binop (unsigned icode, rtx dest, rtx src1, rtx src2, rtx len, machine_mode mask_mode, machine_mode scalar_mode) @@ -340,13 +418,29 @@ emit_len_binop (unsigned icode, rtx dest, rtx src1, rtx src2, rtx len, mask_mode, scalar_mode); } +/* Emit a masked operation with a given length LEN. */ +void +emit_masked_len_op (unsigned icode, rtx mask, rtx dest, rtx src, rtx len, + machine_mode mask_mode) +{ + emit_pred_op (icode, mask, dest, src, len, mask_mode); +} + +/* Emit an unmasked comparison whose result is stored in the mask DEST. */ +void +emit_len_cmp (unsigned icode, rtx dest, rtx op, rtx src1, rtx src2, + rtx len, machine_mode mask_mode) +{ + emit_pred_cmp (icode, NULL_RTX, dest, op, src1, src2, len, mask_mode); +} + /* Emit vid.v instruction. */ static void emit_index_op (rtx dest, machine_mode mask_mode) { insn_expander<7> e; - e.set_dest_and_mask (NULL, dest, mask_mode); + e.set_dest_and_mask (dest, NULL, mask_mode); e.set_len_and_policy (NULL, true); @@ -621,9 +715,9 @@ get_ma (rtx ma) return INTVAL (ma); } -/* Get prefer tail policy. */ +/* Get preferred tail policy. */ enum tail_policy -get_prefer_tail_policy () +get_preferred_tail_policy () { /* TODO: By default, we choose to use TAIL_ANY which allows compiler pick up either agnostic or undisturbed. Maybe we @@ -632,9 +726,9 @@ get_prefer_tail_policy () return TAIL_ANY; } -/* Get prefer mask policy. */ +/* Get preferred mask policy. */ enum mask_policy -get_prefer_mask_policy () +get_preferred_mask_policy () { /* TODO: By default, we choose to use MASK_ANY which allows compiler pick up either agnostic or undisturbed. Maybe we @@ -935,8 +1029,8 @@ slide1_sew64_helper (int unspec, machine_mode mode, machine_mode demote_mode, } rtx temp = gen_reg_rtx (demote_mode); - rtx ta = gen_int_mode (get_prefer_tail_policy (), Pmode); - rtx ma = gen_int_mode (get_prefer_mask_policy (), Pmode); + rtx ta = gen_int_mode (get_preferred_tail_policy (), Pmode); + rtx ma = gen_int_mode (get_preferred_mask_policy (), Pmode); rtx merge = RVV_VUNDEF (demote_mode); /* Handle vslide1<ud>_tu. */ if (register_operand (ops[2], mode) diff --git a/gcc/config/riscv/riscv-vector-builtins.cc b/gcc/config/riscv/riscv-vector-builtins.cc index dd714bfcee2..0487827e65e 100644 --- a/gcc/config/riscv/riscv-vector-builtins.cc +++ b/gcc/config/riscv/riscv-vector-builtins.cc @@ -2743,7 +2743,7 @@ get_tail_policy_for_pred (enum predication_type_index pred) { if (pred == PRED_TYPE_tu || pred == PRED_TYPE_tum || pred == PRED_TYPE_tumu) return gen_int_mode (TAIL_UNDISTURBED, Pmode); - return gen_int_mode (get_prefer_tail_policy (), Pmode); + return gen_int_mode (get_preferred_tail_policy (), Pmode); } /* Get MASK policy for predication. If predication indicates MU, return the MU. @@ -2753,7 +2753,7 @@ get_mask_policy_for_pred (enum predication_type_index pred) { if (pred == PRED_TYPE_tumu || pred == PRED_TYPE_mu) return gen_int_mode (MASK_UNDISTURBED, Pmode); - return gen_int_mode (get_prefer_mask_policy (), Pmode); + return gen_int_mode (get_preferred_mask_policy (), Pmode); } tree diff --git a/gcc/config/riscv/riscv-vsetvl.cc b/gcc/config/riscv/riscv-vsetvl.cc index 9847d649d1d..0ecd0bfa2ea 100644 --- a/gcc/config/riscv/riscv-vsetvl.cc +++ b/gcc/config/riscv/riscv-vsetvl.cc @@ -566,8 +566,8 @@ get_default_ta () { /* For the instruction that doesn't require TA, we still need a default value to emit vsetvl. We pick up the default value according to prefer policy. */ - return (bool) (get_prefer_tail_policy () & 0x1 - || (get_prefer_tail_policy () >> 1 & 0x1)); + return (bool) (get_preferred_tail_policy () & 0x1 + || (get_preferred_tail_policy () >> 1 & 0x1)); } /* Get default mask policy. */ @@ -576,8 +576,8 @@ get_default_ma () { /* For the instruction that doesn't require MA, we still need a default value to emit vsetvl. We pick up the default value according to prefer policy. */ - return (bool) (get_prefer_mask_policy () & 0x1 - || (get_prefer_mask_policy () >> 1 & 0x1)); + return (bool) (get_preferred_mask_policy () & 0x1 + || (get_preferred_mask_policy () >> 1 & 0x1)); } /* Helper function to get TA operand. */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-run.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-run.c new file mode 100644 index 00000000000..d6aaa785055 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-run.c @@ -0,0 +1,29 @@ +/* { dg-do run { target { riscv_vector } } } */ +/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=fixed-vlmax" } */ + +#include "abs-template.h" + +#include <assert.h> + +#define SZ 255 + +#define RUN(TYPE) \ + TYPE a##TYPE[SZ]; \ + for (int i = 0; i < SZ; i++) \ + { \ + a##TYPE[i] = i - 127; \ + } \ + vabs_##TYPE (a##TYPE, a##TYPE, SZ); \ + for (int i = 0; i < SZ; i++) \ + assert (a##TYPE[i] == abs (i - 127)); \ + +#define RUN_ALL() \ + RUN(int8_t) \ + RUN(int16_t) \ + RUN(int32_t) \ + RUN(int64_t) + +int main () +{ + RUN_ALL() +} diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-rv32gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-rv32gcv.c new file mode 100644 index 00000000000..cbe0ba0b0ba --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-rv32gcv.c @@ -0,0 +1,7 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv32gcv -mabi=ilp32d --param=riscv-autovec-preference=fixed-vlmax" } */ + +#include "abs-template.h" + +/* { dg-final { scan-assembler-times {\tvmslt\.vi} 4 } } */ +/* { dg-final { scan-assembler-times {\tvneg\.v} 4 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-rv64gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-rv64gcv.c new file mode 100644 index 00000000000..c0c52176a42 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-rv64gcv.c @@ -0,0 +1,7 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv64gcv -mabi=lp64d --param=riscv-autovec-preference=fixed-vlmax" } */ + +#include "abs-template.h" + +/* { dg-final { scan-assembler-times {\tvmslt\.vi} 4 } } */ +/* { dg-final { scan-assembler-times {\tvneg\.v} 4 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-template.h b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-template.h new file mode 100644 index 00000000000..a54238c8ff2 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-template.h @@ -0,0 +1,26 @@ +#include <stdlib.h> +#include <stdint-gcc.h> + +#define TEST_TYPE(TYPE) \ + __attribute__((noipa)) \ + void vabs_##TYPE (TYPE *dst, TYPE *a, int n) \ + { \ + for (int i = 0; i < n; i++) \ + dst[i] = abs (a[i]); \ + } + +#define TEST_TYPE2(TYPE) \ + __attribute__((noipa)) \ + void vabs_##TYPE (TYPE *dst, TYPE *a, int n) \ + { \ + for (int i = 0; i < n; i++) \ + dst[i] = llabs (a[i]); \ + } + +#define TEST_ALL() \ + TEST_TYPE(int8_t) \ + TEST_TYPE(int16_t) \ + TEST_TYPE(int32_t) \ + TEST_TYPE2(int64_t) + +TEST_ALL() diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-run.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-run.c new file mode 100644 index 00000000000..abeb50f21ea --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-run.c @@ -0,0 +1,29 @@ +/* { dg-do run { target { riscv_vector } } } */ +/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=fixed-vlmax" } */ + +#include "vneg-template.h" + +#include <assert.h> + +#define SZ 255 + +#define RUN(TYPE) \ + TYPE a##TYPE[SZ]; \ + for (int i = 0; i < SZ; i++) \ + { \ + a##TYPE[i] = i - 127; \ + } \ + vneg_##TYPE (a##TYPE, a##TYPE, SZ); \ + for (int i = 0; i < SZ; i++) \ + assert (a##TYPE[i] == -(i - 127)); + +#define RUN_ALL() \ + RUN(int8_t) \ + RUN(int16_t) \ + RUN(int32_t) \ + RUN(int64_t) + +int main () +{ + RUN_ALL() +} diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-rv32gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-rv32gcv.c new file mode 100644 index 00000000000..69d9ebb0953 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-rv32gcv.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv32gcv -mabi=ilp32d --param=riscv-autovec-preference=fixed-vlmax" } */ + +#include "vneg-template.h" + +/* { dg-final { scan-assembler-times {\tvneg\.v} 4 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-rv64gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-rv64gcv.c new file mode 100644 index 00000000000..d2c2e17c13e --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-rv64gcv.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv64gcv -mabi=lp64d --param=riscv-autovec-preference=fixed-vlmax" } */ + +#include "vneg-template.h" + +/* { dg-final { scan-assembler-times {\tvneg\.v} 4 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-template.h b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-template.h new file mode 100644 index 00000000000..72701fceb8c --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-template.h @@ -0,0 +1,17 @@ +#include <stdint-gcc.h> + +#define TEST_TYPE(TYPE) \ + __attribute__((noipa)) \ + void vneg_##TYPE (TYPE *dst, TYPE *a, int n) \ + { \ + for (int i = 0; i < n; i++) \ + dst[i] = -a[i]; \ + } + +#define TEST_ALL() \ + TEST_TYPE(int8_t) \ + TEST_TYPE(int16_t) \ + TEST_TYPE(int32_t) \ + TEST_TYPE(int64_t) + +TEST_ALL() diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-run.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-run.c new file mode 100644 index 00000000000..1c6836742cf --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-run.c @@ -0,0 +1,33 @@ +/* { dg-do run { target { riscv_vector } } } */ +/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=fixed-vlmax" } */ + +#include "vnot-template.h" + +#include <assert.h> + +#define SZ 255 + +#define RUN(TYPE) \ + TYPE a##TYPE[SZ]; \ + for (int i = 0; i < SZ; i++) \ + { \ + a##TYPE[i] = i - 127; \ + } \ + vnot_##TYPE (a##TYPE, a##TYPE, SZ); \ + for (int i = 0; i < SZ; i++) \ + assert (a##TYPE[i] == (TYPE)~(i - 127)); + +#define RUN_ALL() \ + RUN(int8_t) \ + RUN(int16_t) \ + RUN(int32_t) \ + RUN(int64_t) \ + RUN(uint8_t) \ + RUN(uint16_t) \ + RUN(uint32_t) \ + RUN(uint64_t) + +int main () +{ + RUN_ALL() +} diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-rv32gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-rv32gcv.c new file mode 100644 index 00000000000..ecc4316bd4f --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-rv32gcv.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv32gcv -mabi=ilp32d --param=riscv-autovec-preference=fixed-vlmax" } */ + +#include "vnot-template.h" + +/* { dg-final { scan-assembler-times {\tvnot\.v} 8 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-rv64gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-rv64gcv.c new file mode 100644 index 00000000000..67e28af2cd8 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-rv64gcv.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv64gcv -mabi=lp64d --param=riscv-autovec-preference=fixed-vlmax" } */ + +#include "vnot-template.h" + +/* { dg-final { scan-assembler-times {\tvnot\.v} 8 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-template.h b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-template.h new file mode 100644 index 00000000000..19c78d6e49b --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-template.h @@ -0,0 +1,21 @@ +#include <stdint-gcc.h> + +#define TEST_TYPE(TYPE) \ + __attribute__((noipa)) \ + void vnot_##TYPE (TYPE *dst, TYPE *a, int n) \ + { \ + for (int i = 0; i < n; i++) \ + dst[i] = ~a[i]; \ + } + +#define TEST_ALL() \ + TEST_TYPE(int8_t) \ + TEST_TYPE(uint8_t) \ + TEST_TYPE(int16_t) \ + TEST_TYPE(uint16_t) \ + TEST_TYPE(int32_t) \ + TEST_TYPE(uint32_t) \ + TEST_TYPE(int64_t) \ + TEST_TYPE(uint64_t) + +TEST_ALL() diff --git a/gcc/testsuite/gcc.target/riscv/rvv/rvv.exp b/gcc/testsuite/gcc.target/riscv/rvv/rvv.exp index bc99cc0c3cf..54e35cb6c62 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/rvv.exp +++ b/gcc/testsuite/gcc.target/riscv/rvv/rvv.exp @@ -63,6 +63,8 @@ foreach op $AUTOVEC_TEST_OPTS { "" "$op" dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/autovec/binop/*.\[cS\]]] \ "" "$op" + dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/autovec/unop/*.\[cS\]]] \ + "" "$op" } # VLS-VLMAX tests
>>> + TAIL_UNDEFINED = -1, >>> + MASK_UNDEFINED = -1, > Why you add this ? > >>> + void add_policy_operands (enum tail_policy vta = TAIL_UNDEFINED, >>> + enum mask_policy vma = MASK_UNDEFINED) > No, you should just specify this as TAIL_ANY or MASK_ANY as default value. That's the value I intended for "unspecified" i.e. the caller didn't specify and then set it to the default. _ANY can work as well I guess. > >>>const_vlmax_p (machine_mode mode) >>>{ >>>- poly_uint64 nuints = GET_MODE_NUNITS (mode); >>>+ poly_uint64 nunits = GET_MODE_NUNITS (mode); >>>- return nuints.is_constant () >>>+ return nunits.is_constant () >>> /* The vsetivli can only hold register 0~31. */ >>>- ? (IN_RANGE (nuints.to_constant (), 0, 31)) >>>+ ? (IN_RANGE (nunits.to_constant (), 0, 31)) >>> /* Only allowed in VLS-VLMAX mode. */ >>> : false; >>>} > Meaningless change ? Typo. > >>> /* For the instruction that doesn't require TA, we still need a default value >>> to emit vsetvl. We pick up the default value according to prefer policy. */ >>> - return (bool) (get_prefer_tail_policy () & 0x1 >>> - || (get_prefer_tail_policy () >> 1 & 0x1)); >>> + return (bool) (get_preferred_tail_policy () & 0x1 >>> + || (get_preferred_tail_policy () >> 1 & 0x1)); >>> } >>> /* Get default mask policy. */ >>> @@ -576,8 +576,8 @@ get_default_ma () >>> { >>> /* For the instruction that doesn't require MA, we still need a default value >>> to emit vsetvl. We pick up the default value according to prefer policy. */ >>> - return (bool) (get_prefer_mask_policy () & 0x1 >>> - || (get_prefer_mask_policy () >> 1 & 0x1)); >>> + return (bool) (get_preferred_mask_policy () & 0x1 >>> + || (get_preferred_mask_policy () >> 1 & 0x1)); > Why you change it ? Typo/grammar imho. What about the rest of the changes? It's not all typos but I tried to unify the mask/policy handling a bit. > You are using comparison helper which I added one in my downstream > when I am working on comparison autovec patterns: > > I think you can normalize my code with yours: I wasn't aware that I'm only using one of several helpers, just refactored what iss upstream. Yes your code looks reasonable and it surely works with the patch without much rework. > I am almost done all comparison autovec patterns, soon will send them after testing. Good, looking forward to it. Regards Robin
>> What about the rest of the changes? It's not all typos but I tried >> to unify the mask/policy handling a bit. Oh, I see. You rename get_prefer into get_preferred. This makes perfect sense to me. juzhe.zhong@rivai.ai From: Robin Dapp Date: 2023-05-19 20:07 To: 钟居哲; gcc-patches; kito.cheng; palmer; Michael Collison; Jeff Law CC: rdapp.gcc Subject: Re: [PATCH] RISC-V: Implement autovec abs, vneg, vnot. >>> + TAIL_UNDEFINED = -1, >>> + MASK_UNDEFINED = -1, > Why you add this ? > >>> + void add_policy_operands (enum tail_policy vta = TAIL_UNDEFINED, >>> + enum mask_policy vma = MASK_UNDEFINED) > No, you should just specify this as TAIL_ANY or MASK_ANY as default value. That's the value I intended for "unspecified" i.e. the caller didn't specify and then set it to the default. _ANY can work as well I guess. > >>>const_vlmax_p (machine_mode mode) >>>{ >>>- poly_uint64 nuints = GET_MODE_NUNITS (mode); >>>+ poly_uint64 nunits = GET_MODE_NUNITS (mode); >>>- return nuints.is_constant () >>>+ return nunits.is_constant () >>> /* The vsetivli can only hold register 0~31. */ >>>- ? (IN_RANGE (nuints.to_constant (), 0, 31)) >>>+ ? (IN_RANGE (nunits.to_constant (), 0, 31)) >>> /* Only allowed in VLS-VLMAX mode. */ >>> : false; >>>} > Meaningless change ? Typo. > >>> /* For the instruction that doesn't require TA, we still need a default value >>> to emit vsetvl. We pick up the default value according to prefer policy. */ >>> - return (bool) (get_prefer_tail_policy () & 0x1 >>> - || (get_prefer_tail_policy () >> 1 & 0x1)); >>> + return (bool) (get_preferred_tail_policy () & 0x1 >>> + || (get_preferred_tail_policy () >> 1 & 0x1)); >>> } >>> /* Get default mask policy. */ >>> @@ -576,8 +576,8 @@ get_default_ma () >>> { >>> /* For the instruction that doesn't require MA, we still need a default value >>> to emit vsetvl. We pick up the default value according to prefer policy. */ >>> - return (bool) (get_prefer_mask_policy () & 0x1 >>> - || (get_prefer_mask_policy () >> 1 & 0x1)); >>> + return (bool) (get_preferred_mask_policy () & 0x1 >>> + || (get_preferred_mask_policy () >> 1 & 0x1)); > Why you change it ? Typo/grammar imho. What about the rest of the changes? It's not all typos but I tried to unify the mask/policy handling a bit. > You are using comparison helper which I added one in my downstream > when I am working on comparison autovec patterns: > > I think you can normalize my code with yours: I wasn't aware that I'm only using one of several helpers, just refactored what iss upstream. Yes your code looks reasonable and it surely works with the patch without much rework. > I am almost done all comparison autovec patterns, soon will send them after testing. Good, looking forward to it. Regards Robin
As discussed with Juzhe off-list, I will rebase this patch against Juzhe's vec_cmp/vcond patch once that hits the trunk. Regards Robin
So I expect you will also apply those refactor on Juzhe's new changes? If so I would like to have a separated NFC refactor patch if possible. e.g. Juzhe's vec_cmp/vcond -> NFC refactor patch -> abs, vneg, vnot On Mon, May 22, 2023 at 4:59 PM Robin Dapp <rdapp.gcc@gmail.com> wrote: > > As discussed with Juzhe off-list, I will rebase this patch against > Juzhe's vec_cmp/vcond patch once that hits the trunk. > > Regards > Robin
Yeah, I agree wit kito. For example, I see you have rename "get_prefer_***" into "get_preferred_**" I think this NFC patch should be separated patch. Thanks. juzhe.zhong@rivai.ai From: Kito Cheng Date: 2023-05-22 17:05 To: Robin Dapp CC: 钟居哲; gcc-patches; palmer; Michael Collison; Jeff Law Subject: Re: [PATCH] RISC-V: Implement autovec abs, vneg, vnot. So I expect you will also apply those refactor on Juzhe's new changes? If so I would like to have a separated NFC refactor patch if possible. e.g. Juzhe's vec_cmp/vcond -> NFC refactor patch -> abs, vneg, vnot On Mon, May 22, 2023 at 4:59 PM Robin Dapp <rdapp.gcc@gmail.com> wrote: > > As discussed with Juzhe off-list, I will rebase this patch against > Juzhe's vec_cmp/vcond patch once that hits the trunk. > > Regards > Robin
> So I expect you will also apply those refactor on Juzhe's new changes? > If so I would like to have a separated NFC refactor patch if possible. What's NFC? :) Do you mean to just have the refactor part as a separate patch? If yes, I agree. > e.g. > Juzhe's vec_cmp/vcond -> NFC refactor patch -> abs, vneg, vnot
> > So I expect you will also apply those refactor on Juzhe's new changes? > > If so I would like to have a separated NFC refactor patch if possible. > > What's NFC? :) Do you mean to just have the refactor part as a separate > patch? If yes, I agree. NFC: non-functional-change, that's a term used in LLVM, I just forgot that's kind of rare term used here,
diff --git a/gcc/config/riscv/autovec.md b/gcc/config/riscv/autovec.md index ce0b46537ad..8060a5cdf90 100644 --- a/gcc/config/riscv/autovec.md +++ b/gcc/config/riscv/autovec.md @@ -161,7 +161,7 @@ (define_expand "<optab><mode>3" }) ;; ------------------------------------------------------------------------- -;; ---- [INT] Binary shifts by scalar. +;; ---- [INT] Binary shifts by vector. ;; ------------------------------------------------------------------------- ;; Includes: ;; - vsll.vv/vsra.vv/vsrl.vv @@ -180,3 +180,52 @@ (define_expand "v<optab><mode>3" NULL_RTX, <VM>mode); DONE; }) + +;; ========================================================================= +;; == Unary arithmetic +;; ========================================================================= + +;; ------------------------------------------------------------------------------- +;; ---- [INT] Unary operations +;; ------------------------------------------------------------------------------- +;; Includes: +;; - vneg.v/vnot.v +;; ------------------------------------------------------------------------------- +(define_expand "<optab><mode>2" + [(set (match_operand:VI 0 "register_operand") + (any_int_unop:VI + (match_operand:VI 1 "register_operand")))] + "TARGET_VECTOR" +{ + riscv_vector::emit_len_op (code_for_pred (<CODE>, <MODE>mode), + operands[0], operands[1], NULL_RTX, <VM>mode); + DONE; +}) + +;; ------------------------------------------------------------------------------- +;; - ABS expansion to vmslt and vneg +;; ------------------------------------------------------------------------------- + +(define_expand "abs<mode>2" + [(set (match_operand:VI 0 "register_operand") + (match_operand:VI 1 "register_operand"))] + "TARGET_VECTOR" +{ + // Create a zero constant. + rtx zero = gen_const_vec_duplicate (<MODE>mode, GEN_INT (0)); + + // Compare the source vector against it. + rtx ltcmp = gen_rtx_LT (<VM>mode, operands[1], zero); + + // Mask out all non-negative elements. + rtx mask = gen_reg_rtx (<VM>mode); + riscv_vector::emit_len_cmp (code_for_pred_ltge (<MODE>mode), + mask, ltcmp, operands[1], zero, + NULL_RTX, <VM>mode); + + // Emit a masked vneg, negating only the negative elements. + riscv_vector::emit_masked_len_op (code_for_pred (NEG, <MODE>mode), + mask, operands[0], operands[1], + NULL_RTX, <VM>mode); + DONE; +}) diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h index 12634d0ac1a..7c588086fa0 100644 --- a/gcc/config/riscv/riscv-protos.h +++ b/gcc/config/riscv/riscv-protos.h @@ -171,6 +171,8 @@ void emit_vlmax_reg_op (unsigned, rtx, rtx, rtx, machine_mode); void emit_len_op (unsigned, rtx, rtx, rtx, machine_mode); void emit_len_binop (unsigned, rtx, rtx, rtx, rtx, machine_mode, machine_mode = VOIDmode); +void emit_masked_len_op (unsigned, rtx, rtx, rtx, rtx, machine_mode); +void emit_len_cmp (unsigned, rtx, rtx, rtx, rtx, rtx, machine_mode); enum vlmul_type get_vlmul (machine_mode); unsigned int get_ratio (machine_mode); unsigned int get_nf (machine_mode); @@ -181,6 +183,7 @@ int get_avl_type (rtx); unsigned int calculate_ratio (unsigned int, enum vlmul_type); enum tail_policy { + TAIL_UNDEFINED = -1, TAIL_UNDISTURBED = 0, TAIL_AGNOSTIC = 1, TAIL_ANY = 2, @@ -188,12 +191,13 @@ enum tail_policy enum mask_policy { + MASK_UNDEFINED = -1, MASK_UNDISTURBED = 0, MASK_AGNOSTIC = 1, MASK_ANY = 2, }; -enum tail_policy get_prefer_tail_policy (); -enum mask_policy get_prefer_mask_policy (); +enum tail_policy get_preferred_tail_policy (); +enum mask_policy get_preferred_mask_policy (); rtx get_avl_type_rtx (enum avl_type); opt_machine_mode get_vector_mode (scalar_mode, poly_uint64); opt_machine_mode get_tuple_mode (machine_mode, unsigned int); diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc index d65e7300303..64ad3970267 100644 --- a/gcc/config/riscv/riscv-v.cc +++ b/gcc/config/riscv/riscv-v.cc @@ -54,11 +54,11 @@ namespace riscv_vector { static bool const_vlmax_p (machine_mode mode) { - poly_uint64 nuints = GET_MODE_NUNITS (mode); + poly_uint64 nunits = GET_MODE_NUNITS (mode); - return nuints.is_constant () + return nunits.is_constant () /* The vsetivli can only hold register 0~31. */ - ? (IN_RANGE (nuints.to_constant (), 0, 31)) + ? (IN_RANGE (nunits.to_constant (), 0, 31)) /* Only allowed in VLS-VLMAX mode. */ : false; } @@ -66,38 +66,68 @@ const_vlmax_p (machine_mode mode) template <int MAX_OPERANDS> class insn_expander { public: - insn_expander () : m_opno (0), has_dest(false) {} + 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); gcc_assert (m_opno <= MAX_OPERANDS); } + + void add_source_operand (rtx x, machine_mode mode) + { + add_src (x); + add_input_operand (x, mode); + } + void add_input_operand (rtx x, machine_mode mode) { create_input_operand (&m_ops[m_opno++], x, mode); gcc_assert (m_opno <= MAX_OPERANDS); } + void add_all_one_mask_operand (machine_mode mode) { add_input_operand (CONSTM1_RTX (mode), mode); } + void add_vundef_operand (machine_mode mode) { add_input_operand (RVV_VUNDEF (mode), mode); } - void add_policy_operand (enum tail_policy vta, enum mask_policy vma) + + void add_policy_operands (enum tail_policy vta = TAIL_UNDEFINED, + enum mask_policy vma = MASK_UNDEFINED) { - rtx tail_policy_rtx = gen_int_mode (vta, Pmode); - rtx mask_policy_rtx = gen_int_mode (vma, Pmode); - add_input_operand (tail_policy_rtx, Pmode); - add_input_operand (mask_policy_rtx, Pmode); + /* If no policies were specified, use the default ones. */ + if (vta == TAIL_UNDEFINED) + vta = get_preferred_tail_policy (); + if (vma == MASK_UNDEFINED) + vma = get_preferred_mask_policy (); + + /* RVV Spec 3.4.3. + Mask destination tail elements are always treated as tail-agnostic, + regardless of the setting of vta. */ + if (!is_mask_destination_instruction ()) + { + rtx tail_policy_rtx = gen_int_mode (vta, Pmode); + add_input_operand (tail_policy_rtx, Pmode); + } + + /* RVV Spec 15.1. + Vector mask logical instructions are always unmasked. */ + if (!is_mask_logical_instruction ()) + { + rtx mask_policy_rtx = gen_int_mode (vma, Pmode); + add_input_operand (mask_policy_rtx, Pmode); + } } void add_avl_type_operand (avl_type type) { add_input_operand (gen_int_mode (type, Pmode), Pmode); } - void set_dest_and_mask (rtx mask, rtx dest, machine_mode mask_mode) + void set_dest_and_mask (rtx dest, rtx mask, machine_mode mask_mode) { dest_mode = GET_MODE (dest); has_dest = true; @@ -133,8 +163,7 @@ public: add_input_operand (len, Pmode); - if (GET_MODE_CLASS (dest_mode) != MODE_VECTOR_BOOL) - add_policy_operand (get_prefer_tail_policy (), get_prefer_mask_policy ()); + add_policy_operands (); add_avl_type_operand (vlmax_p ? avl_type::VLMAX : avl_type::NONVLMAX); } @@ -150,9 +179,36 @@ public: expand_insn (icode, m_opno, m_ops); } + bool is_mask_destination_instruction () + { + gcc_assert (has_dest); + return (GET_MODE_CLASS (dest_mode) == MODE_VECTOR_BOOL); + } + + bool is_mask_logical_instruction () + { + if (!is_mask_destination_instruction ()) + return false; + + if (!srcs.length ()) + return false; + + for (rtx src : srcs) + if (GET_MODE_CLASS (GET_MODE (src)) != MODE_VECTOR_BOOL) + return false; + + return true; + } + + void add_src (rtx src) + { + srcs.quick_push (src); + } + private: int m_opno; bool has_dest; + auto_vec<rtx, 3> srcs; machine_mode dest_mode; expand_operand m_ops[MAX_OPERANDS]; }; @@ -252,9 +308,9 @@ emit_pred_op (unsigned icode, rtx mask, rtx dest, rtx src, rtx len, machine_mode mask_mode, bool force_vlmax = false) { insn_expander<8> e; - e.set_dest_and_mask (mask, dest, mask_mode); + e.set_dest_and_mask (dest, mask, mask_mode); - e.add_input_operand (src, GET_MODE (src)); + e.add_source_operand (src, GET_MODE (src)); e.set_len_and_policy (len, force_vlmax); @@ -269,20 +325,40 @@ emit_pred_binop (unsigned icode, rtx mask, rtx dest, rtx src1, rtx src2, machine_mode scalar_mode = VOIDmode) { insn_expander<9> e; - e.set_dest_and_mask (mask, dest, mask_mode); + e.set_dest_and_mask (dest, mask, mask_mode); gcc_assert (VECTOR_MODE_P (GET_MODE (src1)) || VECTOR_MODE_P (GET_MODE (src2))); if (VECTOR_MODE_P (GET_MODE (src1))) - e.add_input_operand (src1, GET_MODE (src1)); + e.add_source_operand (src1, GET_MODE (src1)); else - e.add_input_operand (src1, scalar_mode); + e.add_source_operand (src1, scalar_mode); if (VECTOR_MODE_P (GET_MODE (src2))) - e.add_input_operand (src2, GET_MODE (src2)); + e.add_source_operand (src2, GET_MODE (src2)); else - e.add_input_operand (src2, scalar_mode); + e.add_source_operand (src2, scalar_mode); + + e.set_len_and_policy (len); + + e.expand ((enum insn_code) icode, MEM_P (dest) || MEM_P (src1) || MEM_P (src2)); +} + +/* Emit an RVV comparison. */ +static void +emit_pred_cmp (unsigned icode, rtx mask, rtx dest, rtx cmp, + rtx src1, rtx src2, + rtx len, machine_mode mask_mode) +{ + insn_expander<9> e; + + e.set_dest_and_mask (dest, mask, mask_mode); + + e.add_input_operand (cmp, GET_MODE (cmp)); + + e.add_source_operand (src1, GET_MODE (src1)); + e.add_source_operand (src2, GET_MODE (src2)); e.set_len_and_policy (len); @@ -332,6 +408,8 @@ emit_vlmax_reg_op (unsigned icode, rtx dest, rtx src, rtx len, /* Force VLMAX */ true); } +/* Emit a binary operation with sources SRC1 and SRC2 and a given length + LEN. */ void emit_len_binop (unsigned icode, rtx dest, rtx src1, rtx src2, rtx len, machine_mode mask_mode, machine_mode scalar_mode) @@ -340,13 +418,29 @@ emit_len_binop (unsigned icode, rtx dest, rtx src1, rtx src2, rtx len, mask_mode, scalar_mode); } +/* Emit a masked operation with a given length LEN. */ +void +emit_masked_len_op (unsigned icode, rtx mask, rtx dest, rtx src, rtx len, + machine_mode mask_mode) +{ + emit_pred_op (icode, mask, dest, src, len, mask_mode); +} + +/* Emit an unmasked comparison whose result is stored in the mask DEST. */ +void +emit_len_cmp (unsigned icode, rtx dest, rtx op, rtx src1, rtx src2, + rtx len, machine_mode mask_mode) +{ + emit_pred_cmp (icode, NULL_RTX, dest, op, src1, src2, len, mask_mode); +} + /* Emit vid.v instruction. */ static void emit_index_op (rtx dest, machine_mode mask_mode) { insn_expander<7> e; - e.set_dest_and_mask (NULL, dest, mask_mode); + e.set_dest_and_mask (dest, NULL, mask_mode); e.set_len_and_policy (NULL, true); @@ -621,9 +715,9 @@ get_ma (rtx ma) return INTVAL (ma); } -/* Get prefer tail policy. */ +/* Get preferred tail policy. */ enum tail_policy -get_prefer_tail_policy () +get_preferred_tail_policy () { /* TODO: By default, we choose to use TAIL_ANY which allows compiler pick up either agnostic or undisturbed. Maybe we @@ -632,9 +726,9 @@ get_prefer_tail_policy () return TAIL_ANY; } -/* Get prefer mask policy. */ +/* Get preferred mask policy. */ enum mask_policy -get_prefer_mask_policy () +get_preferred_mask_policy () { /* TODO: By default, we choose to use MASK_ANY which allows compiler pick up either agnostic or undisturbed. Maybe we @@ -935,8 +1029,8 @@ slide1_sew64_helper (int unspec, machine_mode mode, machine_mode demote_mode, } rtx temp = gen_reg_rtx (demote_mode); - rtx ta = gen_int_mode (get_prefer_tail_policy (), Pmode); - rtx ma = gen_int_mode (get_prefer_mask_policy (), Pmode); + rtx ta = gen_int_mode (get_preferred_tail_policy (), Pmode); + rtx ma = gen_int_mode (get_preferred_mask_policy (), Pmode); rtx merge = RVV_VUNDEF (demote_mode); /* Handle vslide1<ud>_tu. */ if (register_operand (ops[2], mode) diff --git a/gcc/config/riscv/riscv-vector-builtins.cc b/gcc/config/riscv/riscv-vector-builtins.cc index dd714bfcee2..0487827e65e 100644 --- a/gcc/config/riscv/riscv-vector-builtins.cc +++ b/gcc/config/riscv/riscv-vector-builtins.cc @@ -2743,7 +2743,7 @@ get_tail_policy_for_pred (enum predication_type_index pred) { if (pred == PRED_TYPE_tu || pred == PRED_TYPE_tum || pred == PRED_TYPE_tumu) return gen_int_mode (TAIL_UNDISTURBED, Pmode); - return gen_int_mode (get_prefer_tail_policy (), Pmode); + return gen_int_mode (get_preferred_tail_policy (), Pmode); } /* Get MASK policy for predication. If predication indicates MU, return the MU. @@ -2753,7 +2753,7 @@ get_mask_policy_for_pred (enum predication_type_index pred) { if (pred == PRED_TYPE_tumu || pred == PRED_TYPE_mu) return gen_int_mode (MASK_UNDISTURBED, Pmode); - return gen_int_mode (get_prefer_mask_policy (), Pmode); + return gen_int_mode (get_preferred_mask_policy (), Pmode); } tree diff --git a/gcc/config/riscv/riscv-vsetvl.cc b/gcc/config/riscv/riscv-vsetvl.cc index 9847d649d1d..0ecd0bfa2ea 100644 --- a/gcc/config/riscv/riscv-vsetvl.cc +++ b/gcc/config/riscv/riscv-vsetvl.cc @@ -566,8 +566,8 @@ get_default_ta () { /* For the instruction that doesn't require TA, we still need a default value to emit vsetvl. We pick up the default value according to prefer policy. */ - return (bool) (get_prefer_tail_policy () & 0x1 - || (get_prefer_tail_policy () >> 1 & 0x1)); + return (bool) (get_preferred_tail_policy () & 0x1 + || (get_preferred_tail_policy () >> 1 & 0x1)); } /* Get default mask policy. */ @@ -576,8 +576,8 @@ get_default_ma () { /* For the instruction that doesn't require MA, we still need a default value to emit vsetvl. We pick up the default value according to prefer policy. */ - return (bool) (get_prefer_mask_policy () & 0x1 - || (get_prefer_mask_policy () >> 1 & 0x1)); + return (bool) (get_preferred_mask_policy () & 0x1 + || (get_preferred_mask_policy () >> 1 & 0x1)); } /* Helper function to get TA operand. */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-run.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-run.c new file mode 100644 index 00000000000..d6aaa785055 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-run.c @@ -0,0 +1,29 @@ +/* { dg-do run { target { riscv_vector } } } */ +/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=fixed-vlmax" } */ + +#include "abs-template.h" + +#include <assert.h> + +#define SZ 255 + +#define RUN(TYPE) \ + TYPE a##TYPE[SZ]; \ + for (int i = 0; i < SZ; i++) \ + { \ + a##TYPE[i] = i - 127; \ + } \ + vabs_##TYPE (a##TYPE, a##TYPE, SZ); \ + for (int i = 0; i < SZ; i++) \ + assert (a##TYPE[i] == abs (i - 127)); \ + +#define RUN_ALL() \ + RUN(int8_t) \ + RUN(int16_t) \ + RUN(int32_t) \ + RUN(int64_t) + +int main () +{ + RUN_ALL() +} diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-rv32gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-rv32gcv.c new file mode 100644 index 00000000000..cbe0ba0b0ba --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-rv32gcv.c @@ -0,0 +1,7 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv32gcv -mabi=ilp32d --param=riscv-autovec-preference=fixed-vlmax" } */ + +#include "abs-template.h" + +/* { dg-final { scan-assembler-times {\tvmslt\.vi} 4 } } */ +/* { dg-final { scan-assembler-times {\tvneg\.v} 4 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-rv64gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-rv64gcv.c new file mode 100644 index 00000000000..c0c52176a42 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-rv64gcv.c @@ -0,0 +1,7 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv64gcv -mabi=lp64d --param=riscv-autovec-preference=fixed-vlmax" } */ + +#include "abs-template.h" + +/* { dg-final { scan-assembler-times {\tvmslt\.vi} 4 } } */ +/* { dg-final { scan-assembler-times {\tvneg\.v} 4 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-template.h b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-template.h new file mode 100644 index 00000000000..a54238c8ff2 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-template.h @@ -0,0 +1,26 @@ +#include <stdlib.h> +#include <stdint-gcc.h> + +#define TEST_TYPE(TYPE) \ + __attribute__((noipa)) \ + void vabs_##TYPE (TYPE *dst, TYPE *a, int n) \ + { \ + for (int i = 0; i < n; i++) \ + dst[i] = abs (a[i]); \ + } + +#define TEST_TYPE2(TYPE) \ + __attribute__((noipa)) \ + void vabs_##TYPE (TYPE *dst, TYPE *a, int n) \ + { \ + for (int i = 0; i < n; i++) \ + dst[i] = llabs (a[i]); \ + } + +#define TEST_ALL() \ + TEST_TYPE(int8_t) \ + TEST_TYPE(int16_t) \ + TEST_TYPE(int32_t) \ + TEST_TYPE2(int64_t) + +TEST_ALL() diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-run.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-run.c new file mode 100644 index 00000000000..abeb50f21ea --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-run.c @@ -0,0 +1,29 @@ +/* { dg-do run { target { riscv_vector } } } */ +/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=fixed-vlmax" } */ + +#include "vneg-template.h" + +#include <assert.h> + +#define SZ 255 + +#define RUN(TYPE) \ + TYPE a##TYPE[SZ]; \ + for (int i = 0; i < SZ; i++) \ + { \ + a##TYPE[i] = i - 127; \ + } \ + vneg_##TYPE (a##TYPE, a##TYPE, SZ); \ + for (int i = 0; i < SZ; i++) \ + assert (a##TYPE[i] == -(i - 127)); + +#define RUN_ALL() \ + RUN(int8_t) \ + RUN(int16_t) \ + RUN(int32_t) \ + RUN(int64_t) + +int main () +{ + RUN_ALL() +} diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-rv32gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-rv32gcv.c new file mode 100644 index 00000000000..69d9ebb0953 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-rv32gcv.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv32gcv -mabi=ilp32d --param=riscv-autovec-preference=fixed-vlmax" } */ + +#include "vneg-template.h" + +/* { dg-final { scan-assembler-times {\tvneg\.v} 4 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-rv64gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-rv64gcv.c new file mode 100644 index 00000000000..d2c2e17c13e --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-rv64gcv.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv64gcv -mabi=lp64d --param=riscv-autovec-preference=fixed-vlmax" } */ + +#include "vneg-template.h" + +/* { dg-final { scan-assembler-times {\tvneg\.v} 4 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-template.h b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-template.h new file mode 100644 index 00000000000..72701fceb8c --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-template.h @@ -0,0 +1,17 @@ +#include <stdint-gcc.h> + +#define TEST_TYPE(TYPE) \ + __attribute__((noipa)) \ + void vneg_##TYPE (TYPE *dst, TYPE *a, int n) \ + { \ + for (int i = 0; i < n; i++) \ + dst[i] = -a[i]; \ + } + +#define TEST_ALL() \ + TEST_TYPE(int8_t) \ + TEST_TYPE(int16_t) \ + TEST_TYPE(int32_t) \ + TEST_TYPE(int64_t) + +TEST_ALL() diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-run.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-run.c new file mode 100644 index 00000000000..1c6836742cf --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-run.c @@ -0,0 +1,33 @@ +/* { dg-do run { target { riscv_vector } } } */ +/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=fixed-vlmax" } */ + +#include "vnot-template.h" + +#include <assert.h> + +#define SZ 255 + +#define RUN(TYPE) \ + TYPE a##TYPE[SZ]; \ + for (int i = 0; i < SZ; i++) \ + { \ + a##TYPE[i] = i - 127; \ + } \ + vnot_##TYPE (a##TYPE, a##TYPE, SZ); \ + for (int i = 0; i < SZ; i++) \ + assert (a##TYPE[i] == (TYPE)~(i - 127)); + +#define RUN_ALL() \ + RUN(int8_t) \ + RUN(int16_t) \ + RUN(int32_t) \ + RUN(int64_t) \ + RUN(uint8_t) \ + RUN(uint16_t) \ + RUN(uint32_t) \ + RUN(uint64_t) + +int main () +{ + RUN_ALL() +} diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-rv32gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-rv32gcv.c new file mode 100644 index 00000000000..ecc4316bd4f --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-rv32gcv.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv32gcv -mabi=ilp32d --param=riscv-autovec-preference=fixed-vlmax" } */ + +#include "vnot-template.h" + +/* { dg-final { scan-assembler-times {\tvnot\.v} 8 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-rv64gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-rv64gcv.c new file mode 100644 index 00000000000..67e28af2cd8 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-rv64gcv.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv64gcv -mabi=lp64d --param=riscv-autovec-preference=fixed-vlmax" } */ + +#include "vnot-template.h" + +/* { dg-final { scan-assembler-times {\tvnot\.v} 8 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-template.h b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-template.h new file mode 100644 index 00000000000..19c78d6e49b --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-template.h @@ -0,0 +1,21 @@ +#include <stdint-gcc.h> + +#define TEST_TYPE(TYPE) \ + __attribute__((noipa)) \ + void vnot_##TYPE (TYPE *dst, TYPE *a, int n) \ + { \ + for (int i = 0; i < n; i++) \ + dst[i] = ~a[i]; \ + } + +#define TEST_ALL() \ + TEST_TYPE(int8_t) \ + TEST_TYPE(uint8_t) \ + TEST_TYPE(int16_t) \ + TEST_TYPE(uint16_t) \ + TEST_TYPE(int32_t) \ + TEST_TYPE(uint32_t) \ + TEST_TYPE(int64_t) \ + TEST_TYPE(uint64_t) + +TEST_ALL() diff --git a/gcc/testsuite/gcc.target/riscv/rvv/rvv.exp b/gcc/testsuite/gcc.target/riscv/rvv/rvv.exp index bc99cc0c3cf..54e35cb6c62 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/rvv.exp +++ b/gcc/testsuite/gcc.target/riscv/rvv/rvv.exp @@ -63,6 +63,8 @@ foreach op $AUTOVEC_TEST_OPTS { "" "$op" dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/autovec/binop/*.\[cS\]]] \ "" "$op" + dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/autovec/unop/*.\[cS\]]] \ + "" "$op" } # VLS-VLMAX tests