aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPan Li <pan2.li@intel.com>2024-09-12 10:43:46 +0800
committerPan Li <pan2.li@intel.com>2024-09-18 09:25:39 +0800
commita82896ed7bbdb5f64ae741433bba4c1db2f2a562 (patch)
tree5dd766b4eb3c8b51e3ce516b10a5af87e515c0ef /gcc
parent9a07ac151327f61963b092062eb8566dd0c6f0cd (diff)
downloadgcc-a82896ed7bbdb5f64ae741433bba4c1db2f2a562.zip
gcc-a82896ed7bbdb5f64ae741433bba4c1db2f2a562.tar.gz
gcc-a82896ed7bbdb5f64ae741433bba4c1db2f2a562.tar.bz2
RISC-V: Implement SAT_ADD for signed integer vector
This patch would like to implement the ssadd for vector integer. Aka form 1 of ssadd vector. Form 1: #define DEF_VEC_SAT_S_ADD_FMT_1(T, UT, MIN, MAX) \ void __attribute__((noinline)) \ vec_sat_s_add_##T##_fmt_1 (T *out, T *op_1, T *op_2, unsigned limit) \ { \ unsigned i; \ for (i = 0; i < limit; i++) \ { \ T x = op_1[i]; \ T y = op_2[i]; \ T sum = (UT)x + (UT)y; \ out[i] = (x ^ y) < 0 \ ? sum \ : (sum ^ x) >= 0 \ ? sum \ : x < 0 ? MIN : MAX; \ } \ } DEF_VEC_SAT_S_ADD_FMT_1(int64_t, uint64_t, INT64_MIN, INT64_MAX) Before this patch: vec_sat_s_add_int64_t_fmt_1: ... vsetvli t1,zero,e64,m1,ta,mu vadd.vv v3,v1,v2 vxor.vv v0,v1,v3 vmslt.vi v0,v0,0 vxor.vv v2,v1,v2 vmsge.vi v2,v2,0 vmand.mm v0,v0,v2 vsra.vx v1,v1,t3 vxor.vv v3,v1,v4,v0.t ... After this patch: vec_sat_s_add_int64_t_fmt_1: ... vsetvli a6,zero,e64,m1,ta,ma vsadd.vv v1,v1,v2 ... The below test suites are passed for this patch. * The rv64gcv fully regression test. gcc/ChangeLog: * config/riscv/autovec.md (ssadd<mode>3): Add new pattern for signed integer vector SAT_ADD. * config/riscv/riscv-protos.h (expand_vec_ssadd): Add new func decl for vector ssadd expanding. * config/riscv/riscv-v.cc (expand_vec_ssadd): Add new func impl to expand vector ssadd pattern. gcc/testsuite/ChangeLog: * gcc.target/riscv/rvv/autovec/binop/vec_sat_data.h: Add test data for vector ssadd. * gcc.target/riscv/rvv/autovec/vec_sat_arith.h: Add test helper macros. * gcc.target/riscv/rvv/autovec/binop/vec_sat_s_add-1.c: New test. * gcc.target/riscv/rvv/autovec/binop/vec_sat_s_add-2.c: New test. * gcc.target/riscv/rvv/autovec/binop/vec_sat_s_add-3.c: New test. * gcc.target/riscv/rvv/autovec/binop/vec_sat_s_add-4.c: New test. * gcc.target/riscv/rvv/autovec/binop/vec_sat_s_add-run-1.c: New test. * gcc.target/riscv/rvv/autovec/binop/vec_sat_s_add-run-2.c: New test. * gcc.target/riscv/rvv/autovec/binop/vec_sat_s_add-run-3.c: New test. * gcc.target/riscv/rvv/autovec/binop/vec_sat_s_add-run-4.c: New test. Signed-off-by: Pan Li <pan2.li@intel.com>
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/riscv/autovec.md11
-rw-r--r--gcc/config/riscv/riscv-protos.h1
-rw-r--r--gcc/config/riscv/riscv-v.cc9
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vec_sat_data.h264
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vec_sat_s_add-1.c18
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vec_sat_s_add-2.c18
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vec_sat_s_add-3.c18
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vec_sat_s_add-4.c18
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vec_sat_s_add-run-1.c17
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vec_sat_s_add-run-2.c17
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vec_sat_s_add-run-3.c17
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vec_sat_s_add-run-4.c17
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vec_sat_arith.h25
13 files changed, 450 insertions, 0 deletions
diff --git a/gcc/config/riscv/autovec.md b/gcc/config/riscv/autovec.md
index a4e1082..a53c446 100644
--- a/gcc/config/riscv/autovec.md
+++ b/gcc/config/riscv/autovec.md
@@ -2684,6 +2684,17 @@
}
)
+(define_expand "ssadd<mode>3"
+ [(match_operand:V_VLSI 0 "register_operand")
+ (match_operand:V_VLSI 1 "register_operand")
+ (match_operand:V_VLSI 2 "register_operand")]
+ "TARGET_VECTOR"
+ {
+ riscv_vector::expand_vec_ssadd (operands[0], operands[1], operands[2], <MODE>mode);
+ DONE;
+ }
+)
+
(define_expand "ussub<mode>3"
[(match_operand:V_VLSI 0 "register_operand")
(match_operand:V_VLSI 1 "register_operand")
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index 3358e38..07a4d42 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -645,6 +645,7 @@ void expand_vec_lround (rtx, rtx, machine_mode, machine_mode, machine_mode);
void expand_vec_lceil (rtx, rtx, machine_mode, machine_mode);
void expand_vec_lfloor (rtx, rtx, machine_mode, machine_mode);
void expand_vec_usadd (rtx, rtx, rtx, machine_mode);
+void expand_vec_ssadd (rtx, rtx, rtx, machine_mode);
void expand_vec_ussub (rtx, rtx, rtx, machine_mode);
void expand_vec_double_ustrunc (rtx, rtx, machine_mode);
void expand_vec_quad_ustrunc (rtx, rtx, machine_mode, machine_mode);
diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index 9b6c3a2..ca3a80c 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -4884,6 +4884,15 @@ expand_vec_usadd (rtx op_0, rtx op_1, rtx op_2, machine_mode vec_mode)
emit_vec_binary_alu (op_0, op_1, op_2, US_PLUS, vec_mode);
}
+/* Expand the standard name ssadd<mode>3 for vector mode, we can leverage
+ the vector fixed point vector single-width saturating add directly. */
+
+void
+expand_vec_ssadd (rtx op_0, rtx op_1, rtx op_2, machine_mode vec_mode)
+{
+ emit_vec_binary_alu (op_0, op_1, op_2, SS_PLUS, vec_mode);
+}
+
/* Expand the standard name usadd<mode>3 for vector mode, we can leverage
the vector fixed point vector single-width saturating add directly. */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vec_sat_data.h b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vec_sat_data.h
index 1db0f17..99d6181 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vec_sat_data.h
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vec_sat_data.h
@@ -334,4 +334,268 @@ TEST_ZIP_STRUCT_DECL(uint16_t, uint32_t) \
},
};
+int8_t TEST_BINARY_DATA_NAME(int8_t, int8_t, ssadd)[][3][N] =
+{
+ {
+ {
+ 0, 0, 0, 0,
+ 2, 2, 2, 2,
+ 126, 126, 126, 126,
+ 127, 127, 127, 127,
+ },
+ {
+ 0, 0, 0, 0,
+ 2, 2, 2, 2,
+ 1, 1, 1, 1,
+ 1, 1, 1, 1,
+ },
+ {
+ 0, 0, 0, 0,
+ 4, 4, 4, 4,
+ 127, 127, 127, 127,
+ 127, 127, 127, 127,
+ },
+ },
+
+ {
+ {
+ -7, -7, -7, -7,
+ -128, -128, -128, -128,
+ -127, -127, -127, -127,
+ -128, -128, -128, -128,
+ },
+ {
+ -4, -4, -4, -4,
+ -1, -1, -1, -1,
+ -1, -1, -1, -1,
+ -128, -128, -128, -128,
+ },
+ {
+ -11, -11, -11, -11,
+ -128, -128, -128, -128,
+ -128, -128, -128, -128,
+ -128, -128, -128, -128,
+ },
+ },
+
+ {
+ {
+ -128, -128, -128, -128,
+ -127, -127, -127, -127,
+ -122, -122, -122, -122,
+ -122, -122, -122, -122,
+ },
+ {
+ 127, 127, 127, 127,
+ 127, 127, 127, 127,
+ 105, 105, 105, 105,
+ 125, 125, 125, 125,
+ },
+ {
+ -1, -1, -1, -1,
+ 0, 0, 0, 0,
+ -17, -17, -17, -17,
+ 3, 3, 3, 3,
+ },
+ },
+};
+
+int16_t TEST_BINARY_DATA_NAME(int16_t, int16_t, ssadd)[][3][N] =
+{
+ {
+ {
+ 0, 0, 0, 0,
+ 2, 2, 2, 2,
+ 32766, 32766, 32766, 32766,
+ 32767, 32767, 32767, 32767,
+ },
+ {
+ 0, 0, 0, 0,
+ 2, 2, 2, 2,
+ 1, 1, 1, 1,
+ 1, 1, 1, 1,
+ },
+ {
+ 0, 0, 0, 0,
+ 4, 4, 4, 4,
+ 32767, 32767, 32767, 32767,
+ 32767, 32767, 32767, 32767,
+ },
+ },
+
+ {
+ {
+ -7, -7, -7, -7,
+ -32768, -32768, -32768, -32768,
+ -32767, -32767, -32767, -32767,
+ -32768, -32768, -32768, -32768,
+ },
+ {
+ -4, -4, -4, -4,
+ -1, -1, -1, -1,
+ -1, -1, -1, -1,
+ -32768, -32768, -32768, -32768,
+ },
+ {
+ -11, -11, -11, -11,
+ -32768, -32768, -32768, -32768,
+ -32768, -32768, -32768, -32768,
+ -32768, -32768, -32768, -32768,
+ },
+ },
+
+ {
+ {
+ -32768, -32768, -32768, -32768,
+ -32767, -32767, -32767, -32767,
+ -32762, -32762, -32762, -32762,
+ -32762, -32762, -32762, -32762,
+ },
+ {
+ 32767, 32767, 32767, 32767,
+ 32767, 32767, 32767, 32767,
+ 32745, 32745, 32745, 32745,
+ 32765, 32765, 32765, 32765,
+ },
+ {
+ -1, -1, -1, -1,
+ 0, 0, 0, 0,
+ -17, -17, -17, -17,
+ 3, 3, 3, 3,
+ },
+ },
+};
+
+int32_t TEST_BINARY_DATA_NAME(int32_t, int32_t, ssadd)[][3][N] =
+{
+ {
+ {
+ 0, 0, 0, 0,
+ 2, 2, 2, 2,
+ 2147483646, 2147483646, 2147483646, 2147483646,
+ 2147483647, 2147483647, 2147483647, 2147483647,
+ },
+ {
+ 0, 0, 0, 0,
+ 2, 2, 2, 2,
+ 1, 1, 1, 1,
+ 1, 1, 1, 1,
+ },
+ {
+ 0, 0, 0, 0,
+ 4, 4, 4, 4,
+ 2147483647, 2147483647, 2147483647, 2147483647,
+ 2147483647, 2147483647, 2147483647, 2147483647,
+ },
+ },
+
+ {
+ {
+ -7, -7, -7, -7,
+ -2147483648, -2147483648, -2147483648, -2147483648,
+ -2147483647, -2147483647, -2147483647, -2147483647,
+ -2147483648, -2147483648, -2147483648, -2147483648,
+ },
+ {
+ -4, -4, -4, -4,
+ -1, -1, -1, -1,
+ -1, -1, -1, -1,
+ -2147483648, -2147483648, -2147483648, -2147483648,
+ },
+ {
+ -11, -11, -11, -11,
+ -2147483648, -2147483648, -2147483648, -2147483648,
+ -2147483648, -2147483648, -2147483648, -2147483648,
+ -2147483648, -2147483648, -2147483648, -2147483648,
+ },
+ },
+
+ {
+ {
+ -2147483648, -2147483648, -2147483648, -2147483648,
+ -2147483647, -2147483647, -2147483647, -2147483647,
+ -2147483642, -2147483642, -2147483642, -2147483642,
+ -2147483642, -2147483642, -2147483642, -2147483642,
+ },
+ {
+ 2147483647, 2147483647, 2147483647, 2147483647,
+ 2147483647, 2147483647, 2147483647, 2147483647,
+ 2147483625, 2147483625, 2147483625, 2147483625,
+ 2147483645, 2147483645, 2147483645, 2147483645,
+ },
+ {
+ -1, -1, -1, -1,
+ 0, 0, 0, 0,
+ -17, -17, -17, -17,
+ 3, 3, 3, 3,
+ },
+ },
+};
+
+int64_t TEST_BINARY_DATA_NAME(int64_t, int64_t, ssadd)[][3][N] =
+{
+ {
+ {
+ 0, 0, 0, 0,
+ 2, 2, 2, 2,
+ 9223372036854775806ll, 9223372036854775806ll, 9223372036854775806ll, 9223372036854775806ll,
+ 9223372036854775807ll, 9223372036854775807ll, 9223372036854775807ll, 9223372036854775807ll,
+ },
+ {
+ 0, 0, 0, 0,
+ 2, 2, 2, 2,
+ 1, 1, 1, 1,
+ 1, 1, 1, 1,
+ },
+ {
+ 0, 0, 0, 0,
+ 4, 4, 4, 4,
+ 9223372036854775807ll, 9223372036854775807ll, 9223372036854775807ll, 9223372036854775807ll,
+ 9223372036854775807ll, 9223372036854775807ll, 9223372036854775807ll, 9223372036854775807ll,
+ },
+ },
+
+ {
+ {
+ -7, -7, -7, -7,
+ -9223372036854775808ull, -9223372036854775808ull, -9223372036854775808ull, -9223372036854775808ull,
+ -9223372036854775807ll, -9223372036854775807ll, -9223372036854775807ll, -9223372036854775807ll,
+ -9223372036854775808ull, -9223372036854775808ull, -9223372036854775808ull, -9223372036854775808ull,
+ },
+ {
+ -4, -4, -4, -4,
+ -1, -1, -1, -1,
+ -1, -1, -1, -1,
+ -9223372036854775808ull, -9223372036854775808ull, -9223372036854775808ull, -9223372036854775808ull,
+ },
+ {
+ -11, -11, -11, -11,
+ -9223372036854775808ull, -9223372036854775808ull, -9223372036854775808ull, -9223372036854775808ull,
+ -9223372036854775808ull, -9223372036854775808ull, -9223372036854775808ull, -9223372036854775808ull,
+ -9223372036854775808ull, -9223372036854775808ull, -9223372036854775808ull, -9223372036854775808ull,
+ },
+ },
+
+ {
+ {
+ -9223372036854775808ull, -9223372036854775808ull, -9223372036854775808ull, -9223372036854775808ull,
+ -9223372036854775807ll, -9223372036854775807ll, -9223372036854775807ll, -9223372036854775807ll,
+ -9223372036854775802ll, -9223372036854775802ll, -9223372036854775802ll, -9223372036854775802ll,
+ -9223372036854775802ll, -9223372036854775802ll, -9223372036854775802ll, -9223372036854775802ll,
+ },
+ {
+ 9223372036854775807ll, 9223372036854775807ll, 9223372036854775807ll, 9223372036854775807ll,
+ 9223372036854775807ll, 9223372036854775807ll, 9223372036854775807ll, 9223372036854775807ll,
+ 9223372036854775785ll, 9223372036854775785ll, 9223372036854775785ll, 9223372036854775785ll,
+ 9223372036854775805ll, 9223372036854775805ll, 9223372036854775805ll, 9223372036854775805ll,
+ },
+ {
+ -1, -1, -1, -1,
+ 0, 0, 0, 0,
+ -17, -17, -17, -17,
+ 3, 3, 3, 3,
+ },
+ },
+};
+
#endif
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vec_sat_s_add-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vec_sat_s_add-1.c
new file mode 100644
index 0000000..8677353
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vec_sat_s_add-1.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64d -O3 -ftree-vectorize -fdump-rtl-expand-details -fno-schedule-insns -fno-schedule-insns2" } */
+/* { dg-skip-if "" { *-*-* } { "-flto" } } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "../vec_sat_arith.h"
+
+/*
+** vec_sat_s_add_int8_t_fmt_1:
+** ...
+** vsetvli\s+[atx][0-9]+,\s*zero,\s*e8,\s*m1,\s*ta,\s*ma
+** ...
+** vsadd\.vv\s+v[0-9]+,\s*v[0-9]+,\s*v[0-9]+
+** ...
+*/
+DEF_VEC_SAT_S_ADD_FMT_1(int8_t, uint8_t, INT8_MIN, INT8_MAX)
+
+/* { dg-final { scan-rtl-dump-times ".SAT_ADD " 2 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vec_sat_s_add-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vec_sat_s_add-2.c
new file mode 100644
index 0000000..4c6ec43
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vec_sat_s_add-2.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64d -O3 -ftree-vectorize -fdump-rtl-expand-details -fno-schedule-insns -fno-schedule-insns2" } */
+/* { dg-skip-if "" { *-*-* } { "-flto" } } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "../vec_sat_arith.h"
+
+/*
+** vec_sat_s_add_int16_t_fmt_1:
+** ...
+** vsetvli\s+[atx][0-9]+,\s*zero,\s*e16,\s*m1,\s*ta,\s*ma
+** ...
+** vsadd\.vv\s+v[0-9]+,\s*v[0-9]+,\s*v[0-9]+
+** ...
+*/
+DEF_VEC_SAT_S_ADD_FMT_1(int16_t, uint16_t, INT16_MIN, INT16_MAX)
+
+/* { dg-final { scan-rtl-dump-times ".SAT_ADD " 2 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vec_sat_s_add-3.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vec_sat_s_add-3.c
new file mode 100644
index 0000000..6e44eb3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vec_sat_s_add-3.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64d -O3 -ftree-vectorize -fdump-rtl-expand-details -fno-schedule-insns -fno-schedule-insns2" } */
+/* { dg-skip-if "" { *-*-* } { "-flto" } } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "../vec_sat_arith.h"
+
+/*
+** vec_sat_s_add_int32_t_fmt_1:
+** ...
+** vsetvli\s+[atx][0-9]+,\s*zero,\s*e32,\s*m1,\s*ta,\s*ma
+** ...
+** vsadd\.vv\s+v[0-9]+,\s*v[0-9]+,\s*v[0-9]+
+** ...
+*/
+DEF_VEC_SAT_S_ADD_FMT_1(int32_t, uint32_t, INT32_MIN, INT32_MAX)
+
+/* { dg-final { scan-rtl-dump-times ".SAT_ADD " 2 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vec_sat_s_add-4.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vec_sat_s_add-4.c
new file mode 100644
index 0000000..bbf8486
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vec_sat_s_add-4.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64d -O3 -ftree-vectorize -fdump-rtl-expand-details -fno-schedule-insns -fno-schedule-insns2" } */
+/* { dg-skip-if "" { *-*-* } { "-flto" } } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "../vec_sat_arith.h"
+
+/*
+** vec_sat_s_add_int64_t_fmt_1:
+** ...
+** vsetvli\s+[atx][0-9]+,\s*zero,\s*e64,\s*m1,\s*ta,\s*ma
+** ...
+** vsadd\.vv\s+v[0-9]+,\s*v[0-9]+,\s*v[0-9]+
+** ...
+*/
+DEF_VEC_SAT_S_ADD_FMT_1(int64_t, uint64_t, INT64_MIN, INT64_MAX)
+
+/* { dg-final { scan-rtl-dump-times ".SAT_ADD " 2 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vec_sat_s_add-run-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vec_sat_s_add-run-1.c
new file mode 100644
index 0000000..0869df9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vec_sat_s_add-run-1.c
@@ -0,0 +1,17 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99" } */
+
+#include "../vec_sat_arith.h"
+#include "vec_sat_data.h"
+
+#define T int8_t
+#define T1 int8_t
+#define T2 uint8_t
+
+DEF_VEC_SAT_S_ADD_FMT_1_WRAP (T1, T2, INT8_MIN, INT8_MAX)
+
+#define test_data TEST_BINARY_DATA_NAME_WRAP(T, T, ssadd)
+#define RUN_VEC_SAT_BINARY(T, out, op_1, op_2, N) \
+ RUN_VEC_SAT_S_ADD_FMT_1_WRAP(T, out, op_1, op_2, N)
+
+#include "vec_sat_binary_vvv_run.h"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vec_sat_s_add-run-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vec_sat_s_add-run-2.c
new file mode 100644
index 0000000..5b5c9d3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vec_sat_s_add-run-2.c
@@ -0,0 +1,17 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99" } */
+
+#include "../vec_sat_arith.h"
+#include "vec_sat_data.h"
+
+#define T int16_t
+#define T1 int16_t
+#define T2 uint16_t
+
+DEF_VEC_SAT_S_ADD_FMT_1_WRAP (T1, T2, INT16_MIN, INT16_MAX)
+
+#define test_data TEST_BINARY_DATA_NAME_WRAP(T, T, ssadd)
+#define RUN_VEC_SAT_BINARY(T, out, op_1, op_2, N) \
+ RUN_VEC_SAT_S_ADD_FMT_1_WRAP(T, out, op_1, op_2, N)
+
+#include "vec_sat_binary_vvv_run.h"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vec_sat_s_add-run-3.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vec_sat_s_add-run-3.c
new file mode 100644
index 0000000..47d232a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vec_sat_s_add-run-3.c
@@ -0,0 +1,17 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99" } */
+
+#include "../vec_sat_arith.h"
+#include "vec_sat_data.h"
+
+#define T int32_t
+#define T1 int32_t
+#define T2 uint32_t
+
+DEF_VEC_SAT_S_ADD_FMT_1_WRAP (T1, T2, INT32_MIN, INT32_MAX)
+
+#define test_data TEST_BINARY_DATA_NAME_WRAP(T, T, ssadd)
+#define RUN_VEC_SAT_BINARY(T, out, op_1, op_2, N) \
+ RUN_VEC_SAT_S_ADD_FMT_1_WRAP(T, out, op_1, op_2, N)
+
+#include "vec_sat_binary_vvv_run.h"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vec_sat_s_add-run-4.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vec_sat_s_add-run-4.c
new file mode 100644
index 0000000..6ac43a7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vec_sat_s_add-run-4.c
@@ -0,0 +1,17 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99" } */
+
+#include "../vec_sat_arith.h"
+#include "vec_sat_data.h"
+
+#define T int64_t
+#define T1 int64_t
+#define T2 uint64_t
+
+DEF_VEC_SAT_S_ADD_FMT_1_WRAP (T1, T2, INT64_MIN, INT64_MAX)
+
+#define test_data TEST_BINARY_DATA_NAME_WRAP(T, T, ssadd)
+#define RUN_VEC_SAT_BINARY(T, out, op_1, op_2, N) \
+ RUN_VEC_SAT_S_ADD_FMT_1_WRAP(T, out, op_1, op_2, N)
+
+#include "vec_sat_binary_vvv_run.h"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vec_sat_arith.h b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vec_sat_arith.h
index 23edc48..9a16804 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vec_sat_arith.h
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vec_sat_arith.h
@@ -221,6 +221,31 @@ vec_sat_u_add_imm##IMM##_##T##_fmt_4 (T *out, T *in, unsigned limit) \
#define RUN_VEC_SAT_U_ADD_IMM_FMT_4_WRAP(T, out, op_1, expect, IMM, N) \
RUN_VEC_SAT_U_ADD_IMM_FMT_4(T, out, op_1, expect, IMM, N)
+#define DEF_VEC_SAT_S_ADD_FMT_1(T, UT, MIN, MAX) \
+void __attribute__((noinline)) \
+vec_sat_s_add_##T##_fmt_1 (T *out, T *op_1, T *op_2, unsigned limit) \
+{ \
+ unsigned i; \
+ for (i = 0; i < limit; i++) \
+ { \
+ T x = op_1[i]; \
+ T y = op_2[i]; \
+ T sum = (UT)x + (UT)y; \
+ out[i] = (x ^ y) < 0 \
+ ? sum \
+ : (sum ^ x) >= 0 \
+ ? sum \
+ : x < 0 ? MIN : MAX; \
+ } \
+}
+#define DEF_VEC_SAT_S_ADD_FMT_1_WRAP(T, UT, MIN, MAX) \
+ DEF_VEC_SAT_S_ADD_FMT_1(T, UT, MIN, MAX)
+
+#define RUN_VEC_SAT_S_ADD_FMT_1(T, out, op_1, op_2, N) \
+ vec_sat_s_add_##T##_fmt_1(out, op_1, op_2, N)
+#define RUN_VEC_SAT_S_ADD_FMT_1_WRAP(T, out, op_1, op_2, N) \
+ RUN_VEC_SAT_S_ADD_FMT_1(T, out, op_1, op_2, N)
+
/******************************************************************************/
/* Saturation Sub (Unsigned and Signed) */
/******************************************************************************/