Changes from v2:
- move widen_abd_plus combine to autovec-opt.md.
- some naming update.
- update conditions: TARGET_ZVABD implies TARGET_VECTOR.
- remove redundant vialu attributes
- PR119224 is resolved, so remove the abd condition block.
BTW: If abs is a define_insn_and_split, pr117722.c still fails
because combine can no longer fold abs(a - b) into the old form.
So I keep it as an expand.
This patch adds support for the RISC-V Zvabd (Vector Absolute Difference)
extension, based on the current draft specification:
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
gcc/ChangeLog:
* config/riscv/autovec.md: Add auto-vectorization patterns for
Zvabd instructions.
* config/riscv/autovec-opt.md: Add widening absolute-difference
accumulate combine patterns.
* 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-opt.md | 43 +++++++++++
gcc/config/riscv/autovec.md | 62 ++++++++-------
gcc/config/riscv/riscv-ext.def | 14 ++++
gcc/config/riscv/riscv-ext.opt | 6 +-
gcc/config/riscv/vector-iterators.md | 25 ++++++
gcc/config/riscv/vector.md | 76 +++++++++++++++++++
gcc/doc/riscv-ext.texi | 4 +
.../gcc.target/riscv/rvv/autovec/zvabd-1.c | 61 +++++++++++++++
8 files changed, 262 insertions(+), 29 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/zvabd-1.c
diff --git a/gcc/config/riscv/autovec-opt.md b/gcc/config/riscv/autovec-opt.md
index c86fb16586d..651461f787c 100644
--- a/gcc/config/riscv/autovec-opt.md
+++ b/gcc/config/riscv/autovec-opt.md
@@ -684,6 +684,49 @@
}
[(set_attr "type" "viwalu")])
+(define_insn_and_split "*vwabdacc<su><mode>"
+ [(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_ZVABD && can_create_pseudo_p ()"
+ "#"
+ "&& 1"
+ [(const_int 0)]
+{
+ rtx ops[] = {operands[0], operands[1], operands[2]};
+ riscv_vector::emit_vlmax_insn (CODE_FOR_pred_widen_abd_plus<su><mode>,
+ riscv_vector::BINARY_OP, ops);
+ DONE;
+}
+[(set_attr "type" "viwalu")])
+
+;; have this since we don't canonicalize the plus in the presence of an unspec.
+(define_insn_and_split "*vwabdacc_right<su><mode>"
+ [(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_ZVABD && can_create_pseudo_p ()"
+ "#"
+ "&& 1"
+ [(const_int 0)]
+{
+ rtx ops[] = {operands[0], operands[2], operands[3]};
+ riscv_vector::emit_vlmax_insn (CODE_FOR_pred_widen_abd_plus<su><mode>,
+ riscv_vector::BINARY_OP, ops);
+ DONE;
+}
+[(set_attr "type" "viwalu")])
+
;; This combine pattern does not correspond to an single instruction,
;; i.e. there is no vwmul.wv instruction. This is a temporary pattern
;; produced by a combine pass and if there is no further combine into
diff --git a/gcc/config/riscv/autovec.md b/gcc/config/riscv/autovec.md
index fc5a31c9396..2d818ad1afb 100644
--- a/gcc/config/riscv/autovec.md
+++ b/gcc/config/riscv/autovec.md
@@ -1115,17 +1115,30 @@
[(set_attr "type" "vialu")])
;;
-------------------------------------------------------------------------------
-;; - [INT] ABS expansion to vneg and vmax.
+;; - [INT] ABS expansion
;;
-------------------------------------------------------------------------------
(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,19 @@
; ========
; == 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);
-
- DONE;
- });
+(define_insn_and_split "<su>abd<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_ZVABD && can_create_pseudo_p ()"
+ "#"
+ "&& 1"
+ [(const_int 0)]
+{
+ riscv_vector::emit_vlmax_insn (CODE_FOR_pred_vabd<su><mode>,
+ riscv_vector::BINARY_OP, operands);
+ DONE;
+}
+[(set_attr "type" "vialu")])
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..80d258762c4 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,21 @@
(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")
+])
diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md
index 136ecdc787e..2966d89c8c3 100644
--- a/gcc/config/riscv/vector.md
+++ b/gcc/config/riscv/vector.md
@@ -9200,6 +9200,82 @@
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_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_ZVABD"
+ "vabd<u>.vv\t%0,%3,%4%p1"
+ [(set_attr "type" "vialu")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "@pred_widen_abd_plus<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_ZVABD"
+ "vwabdacc<u>.vv\t%0,%3,%4%p1"
+ [(set_attr "type" "viwalu")
+ (set_attr "mode" "<V_DOUBLE_TRUNC>")])
+
(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