This patch adds support for the RISC-V Zvabd (Vector Absolute Difference) extension, based on Zvabd Draft Spec. https://github.com/riscv/integer-vector-absolute-difference/pull/1
Zvabd is now in the 'Specification in Freeze' state. https://riscv.atlassian.net/browse/RVS-3896 It adds patterns for: - vabs - vabd/vabdu - vwabdacc/vwabdaccu Note: - The abd expand condition remains gated because PR119224 is still open. - check_GNU_style.sh false positive on riscv-ext.opt, gcc/ChangeLog: * config/riscv/autovec.md: Add auto-vectorization patterns for Zvabd instructions. * config/riscv/riscv-ext.def: Add Zvabd extension entry. * config/riscv/riscv-ext.opt: Add Zvabd option. * config/riscv/vector-iterators.md: Update for Zvabd. * config/riscv/vector.md: Add Zvabd patterns. * doc/riscv-ext.texi: Document zvabd extension. gcc/testsuite/ChangeLog: * gcc.target/riscv/rvv/autovec/zvabd-1.c: New tests for Zvabd. Co-authored-by: Yuke Tang <[email protected]> Signed-off-by: Zhongyao Chen <[email protected]> --- gcc/config/riscv/autovec.md | 129 ++++++++++++++---- gcc/config/riscv/riscv-ext.def | 14 ++ gcc/config/riscv/riscv-ext.opt | 6 +- gcc/config/riscv/vector-iterators.md | 33 +++++ gcc/config/riscv/vector.md | 84 ++++++++++++ gcc/doc/riscv-ext.texi | 4 + .../gcc.target/riscv/rvv/autovec/zvabd-1.c | 61 +++++++++ 7 files changed, 304 insertions(+), 27 deletions(-) create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/zvabd-1.c diff --git a/gcc/config/riscv/autovec.md b/gcc/config/riscv/autovec.md index fc5a31c9396..3cdf03fd9b5 100644 --- a/gcc/config/riscv/autovec.md +++ b/gcc/config/riscv/autovec.md @@ -1120,12 +1120,25 @@ (define_expand "abs<mode>2" [(set (match_operand:V_VLSI 0 "register_operand") - (smax:V_VLSI - (match_dup 0) - (neg:V_VLSI - (match_operand:V_VLSI 1 "register_operand"))))] + (abs:V_VLSI + (match_operand:V_VLSI 1 "register_operand")))] "TARGET_VECTOR" { + if (TARGET_ZVABD) + { + riscv_vector::emit_vlmax_insn (CODE_FOR_pred_abs<mode>, + riscv_vector::UNARY_OP, operands); + DONE; + } + + rtx neg = gen_reg_rtx (<MODE>mode); + rtx ops1[] = {neg, operands[1]}; + riscv_vector::emit_vlmax_insn (CODE_FOR_pred_neg<mode>, + riscv_vector::UNARY_OP, ops1); + + rtx ops2[] = {operands[0], operands[1], neg}; + riscv_vector::emit_vlmax_insn (CODE_FOR_pred_smax<mode>, + riscv_vector::BINARY_OP, ops2); DONE; }) @@ -3143,26 +3156,90 @@ ; ======== ; == Absolute difference (not including sum) ; ======== -(define_expand "uabd<mode>3" - [(match_operand:V_VLSI 0 "register_operand") - (match_operand:V_VLSI 1 "register_operand") - (match_operand:V_VLSI 2 "register_operand")] - ;; Disabled until PR119224 is resolved - "TARGET_VECTOR && 0" - { - rtx max = gen_reg_rtx (<MODE>mode); - insn_code icode = code_for_pred (UMAX, <MODE>mode); - rtx ops1[] = {max, operands[1], operands[2]}; - riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, ops1); - - rtx min = gen_reg_rtx (<MODE>mode); - icode = code_for_pred (UMIN, <MODE>mode); - rtx ops2[] = {min, operands[1], operands[2]}; - riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, ops2); - - icode = code_for_pred (MINUS, <MODE>mode); - rtx ops3[] = {operands[0], max, min}; - riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, ops3); +(define_expand "<su>abd<mode>3" + [(set (match_operand:V_VLSI 0 "register_operand") + (unspec:V_VLSI + [(match_operand:V_VLSI 1 "register_operand") + (match_operand:V_VLSI 2 "register_operand")] + UNSPEC_VABD))] +;; Disabled when zvabd not enabled until PR119224 is resolved. + "TARGET_VECTOR && TARGET_ZVABD") + +(define_insn_and_split "*abd<su><mode>3" + [(set (match_operand:V_VLSI 0 "register_operand" "=vr") + (unspec:V_VLSI + [(match_operand:V_VLSI 1 "register_operand" "vr") + (match_operand:V_VLSI 2 "register_operand" "vr")] + UNSPEC_VABD))] + "TARGET_VECTOR && (TARGET_ZVABD || can_create_pseudo_p ())" + "#" + "&& 1" + [(const_int 0)] +{ + if (TARGET_ZVABD) + riscv_vector::emit_vlmax_insn (CODE_FOR_pred_vabd<su><mode>, + riscv_vector::BINARY_OP, operands); + else + { + rtx max = gen_reg_rtx (<MODE>mode); + insn_code icode = code_for_pred (<ABD_MAX>, <MODE>mode); + rtx ops1[] = {max, operands[1], operands[2]}; + riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, ops1); + + rtx min = gen_reg_rtx (<MODE>mode); + icode = code_for_pred (<ABD_MIN>, <MODE>mode); + rtx ops2[] = {min, operands[1], operands[2]}; + riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, ops2); + + icode = code_for_pred (MINUS, <MODE>mode); + rtx ops3[] = {operands[0], max, min}; + riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, ops3); + } + DONE; +} +[(set_attr "type" "vialu")]) - DONE; - }); +; ======== +; == Widening absolute difference and accumulate +; ======== +(define_insn_and_split "*vwabdacc<su><mode>4" + [(set (match_operand:VWEXTI 0 "register_operand" "+&vr") + (plus:VWEXTI + (zero_extend:VWEXTI + (unspec:<V_DOUBLE_TRUNC> + [(match_operand:<V_DOUBLE_TRUNC> 1 "register_operand" "vr") + (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand" "vr")] + UNSPEC_VABD)) + (match_operand:VWEXTI 3 "register_operand" "0")))] + "TARGET_VECTOR && TARGET_ZVABD" + "#" + "&& 1" + [(const_int 0)] +{ + rtx ops[] = {operands[0], operands[1], operands[2]}; + riscv_vector::emit_vlmax_insn (CODE_FOR_pred_vwabdacc<su><mode>, + riscv_vector::BINARY_OP, ops); + DONE; +} +[(set_attr "type" "viwalu")]) + +(define_insn_and_split "*vwabdacc_right<su><mode>4" + [(set (match_operand:VWEXTI 0 "register_operand" "+&vr") + (plus:VWEXTI + (match_operand:VWEXTI 1 "register_operand" "0") + (zero_extend:VWEXTI + (unspec:<V_DOUBLE_TRUNC> + [(match_operand:<V_DOUBLE_TRUNC> 2 "register_operand" "vr") + (match_operand:<V_DOUBLE_TRUNC> 3 "register_operand" "vr")] + UNSPEC_VABD))))] + "TARGET_VECTOR && TARGET_ZVABD" + "#" + "&& 1" + [(const_int 0)] +{ + rtx ops[] = {operands[0], operands[2], operands[3]}; + riscv_vector::emit_vlmax_insn (CODE_FOR_pred_vwabdacc<su><mode>, + riscv_vector::BINARY_OP, ops); + DONE; +} +[(set_attr "type" "viwalu")]) diff --git a/gcc/config/riscv/riscv-ext.def b/gcc/config/riscv/riscv-ext.def index 1993e899148..f963f06d0a1 100644 --- a/gcc/config/riscv/riscv-ext.def +++ b/gcc/config/riscv/riscv-ext.def @@ -1572,6 +1572,19 @@ DEFINE_RISCV_EXT( /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED, /* EXTRA_EXTENSION_FLAGS */ 0) +DEFINE_RISCV_EXT ( + /* NAME. */ zvabd, + /* UPPERCASE_NAME. */ ZVABD, + /* FULL_NAME. */ "Vector absolute difference extension.", + /* DESC. */ "", + /* URL. */ , + /* DEP_EXTS. */ ({"v"}), + /* SUPPORTED_VERSIONS. */ ({{0, 5}}), + /* FLAG_GROUP. */ zvabd, + /* BITMASK_GROUP_ID. */ BITMASK_NOT_YET_ALLOCATED, + /* BITMASK_BIT_POSITION. */ BITMASK_NOT_YET_ALLOCATED, + /* EXTRA_EXTENSION_FLAGS. */ 0) + DEFINE_RISCV_EXT( /* NAME */ sdtrig, /* UPPERCASE_NAME */ SDTRIG, @@ -2095,6 +2108,7 @@ DEFINE_RISCV_EXT( /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED, /* EXTRA_EXTENSION_FLAGS */ 0) + #include "riscv-ext-corev.def" #include "riscv-ext-sifive.def" #include "riscv-ext-thead.def" diff --git a/gcc/config/riscv/riscv-ext.opt b/gcc/config/riscv/riscv-ext.opt index 7bf3d4effc6..00c0953192d 100644 --- a/gcc/config/riscv/riscv-ext.opt +++ b/gcc/config/riscv/riscv-ext.opt @@ -106,6 +106,9 @@ int riscv_zvk_subext TargetVariable int riscv_zvl_subext +TargetVariable +int riscv_zvabd_subext + Mask(RVE) Var(riscv_base_subext) Mask(RVI) Var(riscv_base_subext) @@ -328,6 +331,8 @@ Mask(ZHINX) Var(riscv_zinx_subext) Mask(ZHINXMIN) Var(riscv_zinx_subext) +Mask(ZVABD) Var(riscv_zvabd_subext) + Mask(SDTRIG) Var(riscv_sd_subext) Mask(SHA) Var(riscv_sh_subext) @@ -473,4 +478,3 @@ Mask(XANDESVPACKFPH) Var(riscv_xandes_subext) Mask(XANDESVDOT) Var(riscv_xandes_subext) Mask(XSMTVDOT) Var(riscv_xsmt_subext) - diff --git a/gcc/config/riscv/vector-iterators.md b/gcc/config/riscv/vector-iterators.md index b2383de8549..ceebe35f798 100644 --- a/gcc/config/riscv/vector-iterators.md +++ b/gcc/config/riscv/vector-iterators.md @@ -126,6 +126,13 @@ ;; Vector conditional branch optabs UNSPEC_COND_LEN_CMP_ALL UNSPEC_COND_LEN_CMP_ANY + + ;; abd + UNSPEC_VSABD + UNSPEC_VUABD + ;; abdacc + UNSPEC_VSABDACC + UNSPEC_VUABDACC ]) (define_c_enum "unspecv" [ @@ -6538,3 +6545,29 @@ (UNSPEC_COND_LEN_CMP_ALL "cond_len_vec_cbranch_all") (UNSPEC_COND_LEN_CMP_ANY "cond_len_vec_cbranch_any") ]) + +(define_int_iterator UNSPEC_VABD[ + UNSPEC_VSABD UNSPEC_VUABD +]) + +(define_int_iterator UNSPEC_VABDACC[ + UNSPEC_VSABDACC UNSPEC_VUABDACC +]) + +(define_int_attr su[ + (UNSPEC_VSABD "s") (UNSPEC_VUABD "u") + (UNSPEC_VSABDACC "s") (UNSPEC_VUABDACC "u") +]) + +(define_int_attr u[ + (UNSPEC_VSABD "") (UNSPEC_VUABD "u") + (UNSPEC_VSABDACC "") (UNSPEC_VUABDACC "u") +]) + +(define_int_attr ABD_MAX[ + (UNSPEC_VSABD "SMAX") (UNSPEC_VUABD "UMAX") +]) + +(define_int_attr ABD_MIN[ + (UNSPEC_VSABD "SMIN") (UNSPEC_VUABD "UMIN") +]) diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md index 136ecdc787e..086ed87210d 100644 --- a/gcc/config/riscv/vector.md +++ b/gcc/config/riscv/vector.md @@ -9200,6 +9200,90 @@ riscv_vector::prepare_ternary_operands (operands); }) +;; ------------------------------------ +;; ---- Vector absolute difference extension +;; ---------------------------------------------------------------- +;; Includes: +;; - vabs: Vector Single-Width Signed Integer Absolute +;; - vabd/vabdu: Vector Single-Width Signed Integer Absolute Difference +;; - vwabdacc/vwabdaccu: Vector Widening Signed Integer Absolute +;; Difference and Accumulate +;; ------------------------------------ + +(define_insn "@pred_abs<mode>" + [(set (match_operand:V_VLSI 0 "register_operand" "=vd, vd, vr, vr") + (if_then_else:V_VLSI + (unspec:<VM> + [(match_operand:<VM> 1 "vector_mask_operand" " vm, vm, Wc1, Wc1") + (match_operand 4 "vector_length_operand" " rK, rK, rK, rK") + (match_operand 5 "const_int_operand" " i, i, i, i") + (match_operand 6 "const_int_operand" " i, i, i, i") + (match_operand 7 "const_int_operand" " i, i, i, i") + (reg:SI VL_REGNUM) + (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE) + (abs:V_VLSI + (match_operand:V_VLSI 3 "register_operand" " vr, vr, vr, vr")) + (match_operand:V_VLSI 2 "vector_merge_operand" "vu, 0, vu, 0")))] + "TARGET_VECTOR && TARGET_ZVABD" + "vabs.v\t%0,%3%p1" + [(set_attr "type" "vialu") + (set_attr "mode" "<MODE>") + (set_attr "vl_op_idx" "4") + (set (attr "ta") (symbol_ref "riscv_vector::get_ta (operands[5])")) + (set (attr "ma") (symbol_ref "riscv_vector::get_ma (operands[6])")) + (set (attr "avl_type_idx") (const_int 7))]) + +(define_insn "@pred_vabd<su><mode>" + [(set (match_operand:V_VLSI 0 "register_operand" "=vd, vd, vr, vr") + (if_then_else:V_VLSI + (unspec:<VM> + [(match_operand:<VM> 1 "vector_mask_operand" " vm, vm, Wc1, Wc1") + (match_operand 5 "vector_length_operand" " rK, rK, rK, rK") + (match_operand 6 "const_int_operand" " i, i, i, i") + (match_operand 7 "const_int_operand" " i, i, i, i") + (match_operand 8 "const_int_operand" " i, i, i, i") + (reg:SI VL_REGNUM) + (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE) + (unspec:V_VLSI + [(match_operand:V_VLSI 3 "register_operand" "vr,vr,vr,vr") + (match_operand:V_VLSI 4 "register_operand" "vr,vr,vr,vr")] + UNSPEC_VABD) + (match_operand:V_VLSI 2 "vector_merge_operand" "vu, 0, vu, 0")))] + "TARGET_VECTOR && TARGET_ZVABD" + "vabd<u>.vv\t%0,%3,%4%p1" + [(set_attr "type" "vialu") + (set_attr "mode" "<MODE>") + (set_attr "vl_op_idx" "5") + (set (attr "ta") (symbol_ref "riscv_vector::get_ta (operands[6])")) + (set (attr "ma") (symbol_ref "riscv_vector::get_ma (operands[7])")) + (set (attr "avl_type_idx") (const_int 8))]) + +(define_insn "@pred_vwabdacc<su><mode>" + [(set (match_operand:VWEXTI 0 "register_operand" "+&vd,&vd,&vr,&vr") + (if_then_else:VWEXTI + (unspec:<VM> + [(match_operand:<VM> 1 "vector_mask_operand" "vm,vm,Wc1,Wc1") + (match_operand 5 "vector_length_operand" "rK,rK,rK,rK") + (match_operand 6 "const_int_operand" "i,i,i,i") + (match_operand 7 "const_int_operand" "i,i,i,i") + (match_operand 8 "const_int_operand" "i,i,i,i") + (reg:SI VL_REGNUM) + (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE) + (unspec:VWEXTI + [(match_operand:<V_DOUBLE_TRUNC> 3 "register_operand" "vr,vr,vr,vr") + (match_operand:<V_DOUBLE_TRUNC> 4 "register_operand" "vr,vr,vr,vr") + (match_dup 0)] + UNSPEC_VABDACC) + (match_operand:VWEXTI 2 "vector_merge_operand" "vu,0,vu,0")))] + "TARGET_VECTOR && TARGET_ZVABD" + "vwabdacc<u>.vv\t%0,%3,%4%p1" + [(set_attr "type" "viwalu") + (set_attr "mode" "<V_DOUBLE_TRUNC>") + (set_attr "vl_op_idx" "5") + (set (attr "ta") (symbol_ref "riscv_vector::get_ta (operands[6])")) + (set (attr "ma") (symbol_ref "riscv_vector::get_ma (operands[7])")) + (set (attr "avl_type_idx") (const_int 8))]) + (include "autovec.md") (include "autovec-opt.md") (include "sifive-vector.md") diff --git a/gcc/doc/riscv-ext.texi b/gcc/doc/riscv-ext.texi index bf4f56a6201..92b9514efa9 100644 --- a/gcc/doc/riscv-ext.texi +++ b/gcc/doc/riscv-ext.texi @@ -462,6 +462,10 @@ @tab 1.0 @tab Minimal half-precision floating-point in integer registers extension +@item @samp{zvabd} +@tab 0.5 +@tab Vector absolute difference extension + @item @samp{sdtrig} @tab 1.0 @tab Debug triggers extension diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/zvabd-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zvabd-1.c new file mode 100644 index 00000000000..d28f18f294e --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zvabd-1.c @@ -0,0 +1,61 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv64gcv_zvabd -mabi=lp64d -fno-vect-cost-model" } */ + +#include <stdint-gcc.h> + +static int +abs (int i) +{ + return i < 0 ? -i : i; +} + +#define TEST_VABS(TYPE1, TYPE2) \ + __attribute__((noipa)) void vabs_##TYPE1_##TYPE2 (TYPE1 *__restrict dst, \ + TYPE2 *__restrict a, \ + int n) \ + { \ + int i; \ + for (i = 0; i < n; i++) \ + dst[i] = abs (a[i]); \ + } + +#define TEST_VABD(TYPE1, TYPE2) \ + __attribute__((noipa)) void vabd_##TYPE1_##TYPE2 (TYPE1 *__restrict dst, \ + TYPE2 *__restrict a, \ + TYPE2 *__restrict b, \ + int n) \ + { \ + int i; \ + for (i = 0; i < n; i++) \ + dst[i] = abs (a[i] - b[i]); \ + } + +#define TEST_VWABDACC(TYPE1, TYPE2) \ + __attribute__((noipa)) void \ + vwabdacc_##TYPE1_##TYPE2 (TYPE1 *__restrict dst, TYPE2 *__restrict a, \ + TYPE2 *__restrict b, int n) \ + { \ + int i; \ + for (i = 0; i < n; i++) \ + dst[i] += abs (a[i] - b[i]); \ + } + +#define TEST_ALL() \ + TEST_VABS (int8_t, int8_t) \ + TEST_VABS (int16_t, int16_t) \ + TEST_VABD (int8_t, int8_t) \ + TEST_VABD (uint8_t, uint8_t) \ + TEST_VABD (int16_t, int16_t) \ + TEST_VABD (uint16_t, uint16_t) \ + TEST_VWABDACC (int16_t, int8_t) \ + TEST_VWABDACC (uint16_t, uint8_t)\ + TEST_VWABDACC (int32_t, int16_t) \ + TEST_VWABDACC (uint32_t, uint16_t) + +TEST_ALL() + +/* { dg-final { scan-assembler-times {\tvabs\.v} 2 } } */ +/* { dg-final { scan-assembler-times {\tvabd\.vv} 2 } } */ +/* { dg-final { scan-assembler-times {\tvabdu\.vv} 2 } } */ +/* { dg-final { scan-assembler-times {\tvwabdacc\.vv} 2 } } */ +/* { dg-final { scan-assembler-times {\tvwabdaccu\.vv} 2 } } */ -- 2.43.0
