From: panciyan <[email protected]>
This patch would like to support signed scalar SAT_ADD IMM form 2
Form2:
T __attribute__((noinline)) \
sat_s_add_imm_##T##_fmt_2##_##INDEX (T x) \
{ \
T sum = (T)((UT)x + (UT)IMM); \
return ((x ^ sum) < 0 && (x ^ IMM) >= 0) ? \
(-(T)(x < 0) ^ MAX) : sum; \
}
Take below form1 as example:
DEF_SAT_S_ADD_IMM_FMT_2(0, int8_t, uint8_t, 9, INT8_MIN, INT8_MAX)
Before this patch:
__attribute__((noinline))
int8_t sat_s_add_imm_int8_t_fmt_2_0 (int8_t x)
{
int8_t sum;
unsigned char x.0_1;
unsigned char _2;
signed char _3;
signed char _4;
_Bool _5;
signed char _6;
int8_t _7;
int8_t _10;
signed char _11;
signed char _13;
signed char _14;
<bb 2> [local count: 1073741822]:
x.0_1 = (unsigned char) x_8(D);
_2 = x.0_1 + 9;
sum_9 = (int8_t) _2;
_3 = x_8(D) ^ sum_9;
_4 = x_8(D) ^ 9;
_13 = ~_3;
_14 = _4 | _13;
if (_14 >= 0)
goto <bb 3>; [59.00%]
else
goto <bb 4>; [41.00%]
<bb 3> [local count: 259738146]:
_5 = x_8(D) < 0;
_11 = (signed char) _5;
_6 = -_11;
_10 = _6 ^ 127;
<bb 4> [local count: 1073741824]:
# _7 = PHI <sum_9(2), _10(3)>
return _7;
}
After this patch:
__attribute__((noinline))
int8_t sat_s_add_imm_int8_t_fmt_2_0 (int8_t x)
{
int8_t _7;
<bb 2> [local count: 1073741824]:
_7 = .SAT_ADD (x_8(D), 9); [tail call]
return _7;
}
The below test suites are passed for this patch:
1. The rv64gcv fully regression tests.
2. The x86 bootstrap tests.
3. The x86 fully regression tests.
Signed-off-by: Ciyan Pan <[email protected]>
gcc/ChangeLog:
* match.pd:
gcc/testsuite/ChangeLog:
* gcc.target/riscv/sat/sat_arith.h:
* gcc.target/riscv/sat/sat_s_add_imm-2-i16.c: New test.
* gcc.target/riscv/sat/sat_s_add_imm-2-i32.c: New test.
* gcc.target/riscv/sat/sat_s_add_imm-2-i64.c: New test.
* gcc.target/riscv/sat/sat_s_add_imm-2-i8.c: New test.
* gcc.target/riscv/sat/sat_s_add_imm-run-2-i16.c: New test.
* gcc.target/riscv/sat/sat_s_add_imm-run-2-i32.c: New test.
* gcc.target/riscv/sat/sat_s_add_imm-run-2-i64.c: New test.
* gcc.target/riscv/sat/sat_s_add_imm-run-2-i8.c: New test.
* gcc.target/riscv/sat/sat_s_add_imm_type_check-2-i16.c: New test.
* gcc.target/riscv/sat/sat_s_add_imm_type_check-2-i32.c: New test.
* gcc.target/riscv/sat/sat_s_add_imm_type_check-2-i8.c: New test.
---
gcc/match.pd | 13 ++++-
.../gcc.target/riscv/sat/sat_arith.h | 13 +++++
.../riscv/sat/sat_s_add_imm-2-i16.c | 57 +++++++++++++++++++
.../riscv/sat/sat_s_add_imm-2-i32.c | 54 ++++++++++++++++++
.../riscv/sat/sat_s_add_imm-2-i64.c | 48 ++++++++++++++++
.../gcc.target/riscv/sat/sat_s_add_imm-2-i8.c | 49 ++++++++++++++++
.../riscv/sat/sat_s_add_imm-run-2-i16.c | 48 ++++++++++++++++
.../riscv/sat/sat_s_add_imm-run-2-i32.c | 48 ++++++++++++++++
.../riscv/sat/sat_s_add_imm-run-2-i64.c | 48 ++++++++++++++++
.../riscv/sat/sat_s_add_imm-run-2-i8.c | 48 ++++++++++++++++
.../sat/sat_s_add_imm_type_check-2-i16.c | 9 +++
.../sat/sat_s_add_imm_type_check-2-i32.c | 9 +++
.../riscv/sat/sat_s_add_imm_type_check-2-i8.c | 9 +++
13 files changed, 452 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-2-i16.c
create mode 100644 gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-2-i32.c
create mode 100644 gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-2-i64.c
create mode 100644 gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-2-i8.c
create mode 100644 gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-run-2-i16.c
create mode 100644 gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-run-2-i32.c
create mode 100644 gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-run-2-i64.c
create mode 100644 gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-run-2-i8.c
create mode 100644
gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm_type_check-2-i16.c
create mode 100644
gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm_type_check-2-i32.c
create mode 100644
gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm_type_check-2-i8.c
diff --git a/gcc/match.pd b/gcc/match.pd
index 0f53c162fce..2e92813e026 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -3500,7 +3500,18 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
wide_int c2 = wi::to_wide (@2);
wide_int sum = wi::add (c1, c2);
}
- (if (wi::eq_p (sum, wi::max_value (precision, SIGNED)))))))
+ (if (wi::eq_p (sum, wi::max_value (precision, SIGNED))))))
+
+(match (signed_integer_sat_add @0 @1)
+ /* T SUM = (T)((UT)X + (UT)IMM)
+ SAT_S_ADD = (X ^ SUM) < 0 && (X ^ IMM) >= 0 ? (-(T)(X < 0) ^ MAX) : SUM
*/
+ (cond^ (ge (bit_ior:c (bit_xor:c @0 INTEGER_CST@1)
+ (bit_not (bit_xor:c @0 (nop_convert@2 (plus
(nop_convert @0)
+ INTEGER_CST@3)))))
+ integer_zerop)
+ (signed_integer_sat_val @0)
+ @2)
+ (if (wi::eq_p (wi::to_wide (@1), wi::to_wide (@3))))))
/* Saturation sub for signed integer. */
(if (INTEGRAL_TYPE_P (type) && !TYPE_UNSIGNED (type))
diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_arith.h
b/gcc/testsuite/gcc.target/riscv/sat/sat_arith.h
index 6e97cae96e6..2f825eb6459 100644
--- a/gcc/testsuite/gcc.target/riscv/sat/sat_arith.h
+++ b/gcc/testsuite/gcc.target/riscv/sat/sat_arith.h
@@ -227,6 +227,19 @@ sat_s_add_imm_##T##_fmt_1##_##INDEX (T x) \
#define RUN_SAT_S_ADD_IMM_FMT_1(INDEX, T, x, expect) \
if (sat_s_add_imm##_##T##_fmt_1##_##INDEX(x) != expect) __builtin_abort ()
+#define DEF_SAT_S_ADD_IMM_FMT_2(INDEX, T, UT, IMM, MIN, MAX) \
+T __attribute__((noinline)) \
+sat_s_add_imm_##T##_fmt_2##_##INDEX (T x) \
+{ \
+ T sum = (T)((UT)x + (UT)IMM); \
+ return ((x ^ sum) < 0 && (x ^ IMM) >= 0) ? \
+ (-(T)(x < 0) ^ MAX) : sum; \
+}
+
+#define RUN_SAT_S_ADD_IMM_FMT_2(INDEX, T, x, expect) \
+ if (sat_s_add_imm##_##T##_fmt_2##_##INDEX(x) != expect) __builtin_abort ()
+
+
/******************************************************************************/
/* Saturation Sub (Unsigned and Signed)
*/
/******************************************************************************/
diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-2-i16.c
b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-2-i16.c
new file mode 100644
index 00000000000..14c5d511aab
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-2-i16.c
@@ -0,0 +1,57 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -fdump-tree-optimized
-fno-schedule-insns -fno-schedule-insns2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "sat_arith.h"
+
+/*
+** sat_s_add_imm_int16_t_fmt_2_0:
+** addi\s+[atx][0-9]+,\s*a0,\s*-7
+** xori\s+[atx][0-9]+,\s*a0,\s*-7
+** xor\s+[atx][0-9]+,\s*a0,\s*[atx][0-9]+
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*15
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*15
+** xori\s+[atx][0-9]+,\s*[atx][0-9]+,\s*1
+** and\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
+** andi\s+[atx][0-9]+,\s*[atx][0-9]+,\s*1
+** srai\s+a0,\s*a0,\s*63
+** li\s+[atx][0-9]+,\s*32768
+** addi\s+[atx][0-9]+,\s*[atx][0-9]+,\s*-1
+** xor\s+[atx][0-9]+,\s*[atx][0-9]+,\s*a0
+** neg\s+a0,\s*[atx][0-9]+
+** and\s+[atx][0-9]+,\s*[atx][0-9]+,\s*a0
+** addi\s+[atx][0-9]+,\s*[atx][0-9]+,\s*-1
+** and\s+a0,\s*[atx][0-9]+,\s*[atx][0-9]+
+** or\s+a0,\s*a0,\s*[atx][0-9]+
+** slliw\s+a0,\s*a0,\s*16
+** sraiw\s+a0,\s*a0,\s*16
+** ret
+*/
+DEF_SAT_S_ADD_IMM_FMT_2(0, int16_t, uint16_t, -7, INT16_MIN, INT16_MAX)
+
+/*
+** sat_s_add_imm_int16_t_fmt_2_1:
+** addi\s+[atx][0-9]+,\s*a0,\s*-1
+** not\s+[atx][0-9]+,\s*a0
+** xor\s+[atx][0-9]+,\s*a0,\s*[atx][0-9]+
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*15
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*15
+** xori\s+[atx][0-9]+,\s*[atx][0-9]+,\s*1
+** and\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
+** andi\s+[atx][0-9]+,\s*[atx][0-9]+,\s*1
+** srai\s+a0,\s*a0,\s*63
+** li\s+[atx][0-9]+,\s*32768
+** addi\s+[atx][0-9]+,\s*[atx][0-9]+,\s*-1
+** xor\s+[atx][0-9]+,\s*[atx][0-9]+,\s*a0
+** neg\s+a0,\s*[atx][0-9]+
+** and\s+[atx][0-9]+,\s*[atx][0-9]+,\s*a0
+** addi\s+[atx][0-9]+,\s*[atx][0-9]+,\s*-1
+** and\s+a0,\s*[atx][0-9]+,\s*[atx][0-9]+
+** or\s+a0,\s*a0,\s*[atx][0-9]+
+** slliw\s+a0,\s*a0,\s*16
+** sraiw\s+a0,\s*a0,\s*16
+** ret
+*/
+DEF_SAT_S_ADD_IMM_FMT_2(1, int16_t, uint16_t, -1, INT16_MIN, INT16_MAX)
+
+/* { dg-final { scan-tree-dump-times ".SAT_ADD " 2 "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-2-i32.c
b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-2-i32.c
new file mode 100644
index 00000000000..ecd757d903f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-2-i32.c
@@ -0,0 +1,54 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -fdump-tree-optimized
-fno-schedule-insns -fno-schedule-insns2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "sat_arith.h"
+
+/*
+** sat_s_add_imm_int32_t_fmt_2_0:
+** addi\s+[atx][0-9]+,\s*a0,\s*10
+** xor\s+[atx][0-9]+,\s*a0,\s*[atx][0-9]+
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*31
+** srli\s+[atx][0-9]+,\s*a0,\s*31
+** xori\s+[atx][0-9]+,\s*[atx][0-9]+,\s*1
+** and\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
+** andi\s+[atx][0-9]+,\s*[atx][0-9]+,\s*1
+** srai\s+a0,\s*a0,\s*63
+** li\s+[atx][0-9]+,\s*-2147483648
+** xori\s+[atx][0-9]+,\s*[atx][0-9]+,\s*-1
+** xor\s+[atx][0-9]+,\s*[atx][0-9]+,\s*a0
+** neg\s+a0,\s*[atx][0-9]+
+** and\s+[atx][0-9]+,\s*[atx][0-9]+,\s*a0
+** addi\s+[atx][0-9]+,\s*[atx][0-9]+,\s*-1
+** and\s+a0,\s*[atx][0-9]+,\s*[atx][0-9]+
+** or\s+a0,a0,\s*[atx][0-9]+
+** sext.w\s+a0,\s*a0
+** ret
+*/
+DEF_SAT_S_ADD_IMM_FMT_2(0, int32_t, uint32_t, 10, INT32_MIN, INT32_MAX)
+
+/*
+** sat_s_add_imm_int32_t_fmt_2_1:
+** addi\s+[atx][0-9]+,\s*a0,\s*-1
+** not\s+[atx][0-9]+,\s*a0
+** xor\s+[atx][0-9]+,\s*a0,\s*[atx][0-9]+
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*31
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*31
+** xori\s+[atx][0-9]+,\s*[atx][0-9]+,\s*1
+** and\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
+** andi\s+[atx][0-9]+,\s*[atx][0-9]+,\s*1
+** srai\s+a0,\s*a0,\s*63
+** li\s+[atx][0-9]+,\s*-2147483648
+** xori\s+[atx][0-9]+,\s*[atx][0-9]+,\s*-1
+** xor\s+[atx][0-9]+,\s*[atx][0-9]+,\s*a0
+** neg\s+a0,\s*[atx][0-9]+
+** and\s+[atx][0-9]+,\s*[atx][0-9]+,\s*a0
+** addi\s+[atx][0-9]+,\s*[atx][0-9]+,\s*-1
+** and\s+a0,\s*[atx][0-9]+,\s*[atx][0-9]+
+** or\s+a0,\s*a0,\s*[atx][0-9]+
+** sext.w\s+a0,\s*a0
+** ret
+*/
+DEF_SAT_S_ADD_IMM_FMT_2(1, int32_t, uint32_t, -1, INT32_MIN, INT32_MAX)
+
+/* { dg-final { scan-tree-dump-times ".SAT_ADD " 2 "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-2-i64.c
b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-2-i64.c
new file mode 100644
index 00000000000..07d798f7fd0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-2-i64.c
@@ -0,0 +1,48 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -fdump-tree-optimized
-fno-schedule-insns -fno-schedule-insns2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "sat_arith.h"
+
+/*
+** sat_s_add_imm_int64_t_fmt_2_0:
+** addi\s+[atx][0-9]+,\s*a0,\s*10
+** xor\s+[atx][0-9]+,\s*a0,\s*[atx][0-9]+
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*63
+** srli\s+[atx][0-9]+,\s*a0,\s*63
+** xori\s+[atx][0-9]+,\s*[atx][0-9]+,\s*1
+** and\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
+** srai\s+[atx][0-9]+,\s*a0,\s*63
+** li\s+[atx][0-9]+,\s*-1
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*1
+** xor\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
+** neg\s+[atx][0-9]+,\s*[atx][0-9]+
+** and\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
+** addi\s+[atx][0-9]+,\s*[atx][0-9]+,\s*-1
+** and\s+a0,\s*[atx][0-9]+,\s*[atx][0-9]+
+** or\s+a0,\s*a0,\s*[atx][0-9]+
+** ret
+*/
+DEF_SAT_S_ADD_IMM_FMT_2(0, int64_t, uint64_t, 10, INT64_MIN, INT64_MAX)
+
+/*
+** sat_s_add_imm_int64_t_fmt_2_1:
+** addi\s+[atx][0-9]+,\s*a0,\s*-1
+** xor\s+[atx][0-9]+,\s*a0,\s*[atx][0-9]+
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*63
+** slti\s+[atx][0-9]+,\s*a0,\s*0
+** and\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
+** srai\s+[atx][0-9]+,\s*a0,\s*63
+** li\s+[atx][0-9]+,\s*-1
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*1
+** xor\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
+** neg\s+[atx][0-9]+,\s*[atx][0-9]+
+** and\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
+** addi\s+[atx][0-9]+,\s*[atx][0-9]+,\s*-1
+** and\s+a0,\s*[atx][0-9]+,\s*[atx][0-9]+
+** or\s+a0,\s*a0,\s*[atx][0-9]+
+** ret
+*/
+DEF_SAT_S_ADD_IMM_FMT_2(1, int64_t, uint64_t, -1, INT64_MIN, INT64_MAX)
+
+/* { dg-final { scan-tree-dump-times ".SAT_ADD " 2 "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-2-i8.c
b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-2-i8.c
new file mode 100644
index 00000000000..27342119423
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-2-i8.c
@@ -0,0 +1,49 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -fdump-tree-optimized
-fno-schedule-insns -fno-schedule-insns2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "sat_arith.h"
+
+/*
+** sat_s_add_imm_int8_t_fmt_2_0:
+** addi\s+[atx][0-9]+,\s*a0,\s*9
+** xor\s+[atx][0-9]+,\s*a0,\s*[atx][0-9]+
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*7
+** srli\s+[atx][0-9]+,\s*a0,\s*7
+** xori\s+[atx][0-9]+,\s*[atx][0-9]+,\s*1
+** and\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
+** andi\s+[atx][0-9]+,\s*[atx][0-9]+,\s*1
+** srai\s+a0,\s*a0,\s*63
+** xori\s+[atx][0-9]+,\s*a0,\s*127
+** neg\s+a0,\s*[atx][0-9]+
+** and\s+[atx][0-9]+,\s*[atx][0-9]+,\s*a0
+** addi\s+[atx][0-9]+,\s*[atx][0-9]+,\s*-1
+** and\s+a0,\s*[atx][0-9]+,\s*[atx][0-9]+
+** or\s+a0,\s*a0,\s*[atx][0-9]+
+** slliw\s+a0,\s*a0,\s*24
+** sraiw\s+a0,\s*a0,\s*24
+** ret
+*/
+DEF_SAT_S_ADD_IMM_FMT_2(0, int8_t, uint8_t, 9, INT8_MIN, INT8_MAX)
+
+/*
+** sat_s_add_imm_int8_t_fmt_2_1:
+** addi\s+[atx][0-9]+,\s*a0,\s*-1
+** xor\s+[atx][0-9]+,\s*a0,\s*[atx][0-9]+
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*7
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*63
+** and\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
+** srai\s+a0,\s*a0,\s*63
+** xori\s+[atx][0-9]+,\s*a0,\s*127
+** neg\s+a0,\s*a4
+** and\s+[atx][0-9]+,\s*[atx][0-9]+,\s*a0
+** addi\s+[atx][0-9]+,\s*[atx][0-9]+,\s*-1
+** and\s+a0,\s*[atx][0-9]+,\s*[atx][0-9]+
+** or\s+a0,\s*a0,\s*[atx][0-9]+
+** slliw\s+a0,\s*a0,\s*24
+** sraiw\s+a0,\s*a0,\s*24
+** ret
+*/
+DEF_SAT_S_ADD_IMM_FMT_2(1, int8_t, uint8_t, -1, INT8_MIN, INT8_MAX)
+
+/* { dg-final { scan-tree-dump-times ".SAT_ADD " 2 "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-run-2-i16.c
b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-run-2-i16.c
new file mode 100644
index 00000000000..4f24624eb19
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-run-2-i16.c
@@ -0,0 +1,48 @@
+/* { dg-do run } */
+/* { dg-additional-options "-std=c99" } */
+
+#include "sat_arith.h"
+
+DEF_SAT_S_ADD_IMM_FMT_2(0, int16_t, uint16_t, -32768, INT16_MIN, INT16_MAX)
+DEF_SAT_S_ADD_IMM_FMT_2(1, int16_t, uint16_t, 32767, INT16_MIN, INT16_MAX)
+DEF_SAT_S_ADD_IMM_FMT_2(2, int16_t, uint16_t, 100, INT16_MIN, INT16_MAX)
+DEF_SAT_S_ADD_IMM_FMT_2(3, int16_t, uint16_t, -100, INT16_MIN, INT16_MAX)
+DEF_SAT_S_ADD_IMM_FMT_2(4, int16_t, uint16_t, -1, INT16_MIN, INT16_MAX)
+
+#define T int16_t
+#define RUN(INDEX,T, x, expect) RUN_SAT_S_ADD_IMM_FMT_2(INDEX, T, x, expect)
+
+T d[][2] = {
+ /* arg_0, expect */
+ { -1, -32768, },
+ { 2, -32766, },
+ { 1, 32767, },
+ { -10, 32757, },
+ { 32669, 32767, },
+ { -32768, -32668, },
+ { -32768, -32768, },
+ { 0, -100, },
+ { -32768, -32768, },
+ { 0, -1, },
+};
+
+int
+main ()
+{
+ RUN (0, T, d[0][0], d[0][1]);
+ RUN (0, T, d[1][0], d[1][1]);
+
+ RUN (1, T, d[2][0], d[2][1]);
+ RUN (1, T, d[3][0], d[3][1]);
+
+ RUN (2, T, d[4][0], d[4][1]);
+ RUN (2, T, d[5][0], d[5][1]);
+
+ RUN (3, T, d[6][0], d[6][1]);
+ RUN (3, T, d[7][0], d[7][1]);
+
+ RUN (4, T, d[8][0], d[8][1]);
+ RUN (4, T, d[9][0], d[9][1]);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-run-2-i32.c
b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-run-2-i32.c
new file mode 100644
index 00000000000..8d9ddebfa90
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-run-2-i32.c
@@ -0,0 +1,48 @@
+/* { dg-do run } */
+/* { dg-additional-options "-std=c99" } */
+
+#include "sat_arith.h"
+
+DEF_SAT_S_ADD_IMM_FMT_2(0, int32_t, uint32_t, -2147483648, INT32_MIN,
INT32_MAX)
+DEF_SAT_S_ADD_IMM_FMT_2(1, int32_t, uint32_t, 2147483647, INT32_MIN, INT32_MAX)
+DEF_SAT_S_ADD_IMM_FMT_2(2, int32_t, uint32_t, 100, INT32_MIN, INT32_MAX)
+DEF_SAT_S_ADD_IMM_FMT_2(3, int32_t, uint32_t, -100, INT32_MIN, INT32_MAX)
+DEF_SAT_S_ADD_IMM_FMT_2(4, int32_t, uint32_t, -1, INT32_MIN, INT32_MAX)
+
+#define T int32_t
+#define RUN(INDEX,T, x, expect) RUN_SAT_S_ADD_IMM_FMT_2(INDEX, T, x, expect)
+
+T d[][2] = {
+ /* arg_0, expect */
+ { -1, -2147483648, },
+ { 2, -2147483646, },
+ { 1, 2147483647, },
+ { -10, 2147483637, },
+ { 300, 400, },
+ { -300, -200, },
+ { 100, 0, },
+ { 0, -100, },
+ { 100, 99, },
+ { 0, -1, },
+};
+
+int
+main ()
+{
+ RUN (0, T, d[0][0], d[0][1]);
+ RUN (0, T, d[1][0], d[1][1]);
+
+ RUN (1, T, d[2][0], d[2][1]);
+ RUN (1, T, d[3][0], d[3][1]);
+
+ RUN (2, T, d[4][0], d[4][1]);
+ RUN (2, T, d[5][0], d[5][1]);
+
+ RUN (3, T, d[6][0], d[6][1]);
+ RUN (3, T, d[7][0], d[7][1]);
+
+ RUN (4, T, d[8][0], d[8][1]);
+ RUN (4, T, d[9][0], d[9][1]);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-run-2-i64.c
b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-run-2-i64.c
new file mode 100644
index 00000000000..4523f9a8643
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-run-2-i64.c
@@ -0,0 +1,48 @@
+/* { dg-do run } */
+/* { dg-additional-options "-std=c99" } */
+
+#include "sat_arith.h"
+
+DEF_SAT_S_ADD_IMM_FMT_2(0, int64_t, uint64_t, (-9223372036854775807ll - 1),
INT64_MIN, INT64_MAX)
+DEF_SAT_S_ADD_IMM_FMT_2(1, int64_t, uint64_t, 9223372036854775807ll,
INT64_MIN, INT64_MAX)
+DEF_SAT_S_ADD_IMM_FMT_2(2, int64_t, uint64_t, 100, INT64_MIN, INT64_MAX)
+DEF_SAT_S_ADD_IMM_FMT_2(3, int64_t, uint64_t, -100, INT64_MIN, INT64_MAX)
+DEF_SAT_S_ADD_IMM_FMT_2(4, int64_t, uint64_t, -1, INT64_MIN, INT64_MAX)
+
+#define T int64_t
+#define RUN(INDEX,T, x, expect) RUN_SAT_S_ADD_IMM_FMT_2(INDEX, T, x, expect)
+
+T d[][2] = {
+ /* arg_0, expect */
+ { -1, (-9223372036854775807ll - 1), },
+ { 2, -9223372036854775806ll, },
+ { 1, 9223372036854775807ll, },
+ { -7, 9223372036854775800ll, },
+ { 0, 100, },
+ { -1, 99, },
+ { 0, -100, },
+ { 100, 0, },
+ { 0, -1, },
+ { 100, 99, },
+};
+
+int
+main ()
+{
+ RUN (0, T, d[0][0], d[0][1]);
+ RUN (0, T, d[1][0], d[1][1]);
+
+ RUN (1, T, d[2][0], d[2][1]);
+ RUN (1, T, d[3][0], d[3][1]);
+
+ RUN (2, T, d[4][0], d[4][1]);
+ RUN (2, T, d[5][0], d[5][1]);
+
+ RUN (3, T, d[6][0], d[6][1]);
+ RUN (3, T, d[7][0], d[7][1]);
+
+ RUN (4, T, d[8][0], d[8][1]);
+ RUN (4, T, d[9][0], d[9][1]);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-run-2-i8.c
b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-run-2-i8.c
new file mode 100644
index 00000000000..82e9864b1ad
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm-run-2-i8.c
@@ -0,0 +1,48 @@
+/* { dg-do run } */
+/* { dg-additional-options "-std=c99" } */
+
+#include "sat_arith.h"
+
+DEF_SAT_S_ADD_IMM_FMT_2(0, int8_t, uint8_t, -128, INT8_MIN, INT8_MAX)
+DEF_SAT_S_ADD_IMM_FMT_2(1, int8_t, uint8_t, 127, INT8_MIN, INT8_MAX)
+DEF_SAT_S_ADD_IMM_FMT_2(2, int8_t, uint8_t, 6, INT8_MIN, INT8_MAX)
+DEF_SAT_S_ADD_IMM_FMT_2(3, int8_t, uint8_t, -6, INT8_MIN, INT8_MAX)
+DEF_SAT_S_ADD_IMM_FMT_2(4, int8_t, uint8_t, -1, INT8_MIN, INT8_MAX)
+
+#define T int8_t
+#define RUN(INDEX,T, x, expect) RUN_SAT_S_ADD_IMM_FMT_2(INDEX, T, x, expect)
+
+T d[][2] = {
+ /* arg_0, expect */
+ { -1, -128, },
+ { 2, -126, },
+ { 1, 127, },
+ { -10, 117, },
+ { 122, 127, },
+ { -10, -4, },
+ { -128, -128, },
+ { 127, 121, },
+ { -128, -128, },
+ { 1, 0, },
+};
+
+int
+main ()
+{
+ RUN (0, T, d[0][0], d[0][1]);
+ RUN (0, T, d[1][0], d[1][1]);
+
+ RUN (1, T, d[2][0], d[2][1]);
+ RUN (1, T, d[3][0], d[3][1]);
+
+ RUN (2, T, d[4][0], d[4][1]);
+ RUN (2, T, d[5][0], d[5][1]);
+
+ RUN (3, T, d[6][0], d[6][1]);
+ RUN (3, T, d[7][0], d[7][1]);
+
+ RUN (4, T, d[8][0], d[8][1]);
+ RUN (4, T, d[9][0], d[9][1]);
+
+ return 0;
+}
diff --git
a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm_type_check-2-i16.c
b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm_type_check-2-i16.c
new file mode 100644
index 00000000000..a73a77fafd7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm_type_check-2-i16.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -fdump-tree-optimized" } */
+
+#include "sat_arith.h"
+
+DEF_SAT_S_ADD_IMM_FMT_2(0, int16_t, uint16_t, -32769, INT16_MIN, INT16_MAX)
+DEF_SAT_S_ADD_IMM_FMT_2(1, int16_t, uint16_t, 32768, INT16_MIN, INT16_MAX)
+
+/* { dg-final { scan-tree-dump-not ".SAT_ADD " "optimized" } } */
diff --git
a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm_type_check-2-i32.c
b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm_type_check-2-i32.c
new file mode 100644
index 00000000000..9dae4254d31
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm_type_check-2-i32.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -fdump-tree-optimized" } */
+
+#include "sat_arith.h"
+
+DEF_SAT_S_ADD_IMM_FMT_1(0, int32_t, uint32_t, -2147483649, INT32_MIN,
INT32_MAX)
+DEF_SAT_S_ADD_IMM_FMT_1(1, int32_t, uint32_t, 2147483648, INT32_MIN, INT32_MAX)
+
+/* { dg-final { scan-tree-dump-not ".SAT_ADD " "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm_type_check-2-i8.c
b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm_type_check-2-i8.c
new file mode 100644
index 00000000000..a9cd4b9cd20
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add_imm_type_check-2-i8.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -fdump-tree-optimized" } */
+
+#include "sat_arith.h"
+
+DEF_SAT_S_ADD_IMM_FMT_2(0, int8_t, uint8_t, -129, INT8_MIN, INT8_MAX)
+DEF_SAT_S_ADD_IMM_FMT_2(1, int8_t, uint8_t, 128, INT8_MIN, INT8_MAX)
+
+/* { dg-final { scan-tree-dump-not ".SAT_ADD " "optimized" } } */
--
2.43.0