Thanks Ciyan.

Suggest to break this patch into a series with 2 PATCH(es),
the middle-end(aka gcc/match.pd) and the risc-v backend,
then Richard could locate the middle-end part easily, and
leave the risc-v parts to the risc-v ports.

Pan

-----Original Message-----
From: Ciyan Pan <panci...@eswincomputing.com> 
Sent: Monday, June 23, 2025 2:27 PM
To: gcc-patches@gcc.gnu.org
Cc: kito.ch...@gmail.com; richard.guent...@gmail.com; tamar.christ...@arm.com; 
juzhe.zh...@rivai.ai; Li, Pan2 <pan2...@intel.com>; jeffreya...@gmail.com; 
rdapp....@gmail.com; panciyan <panci...@eswincomputing.com>
Subject: [PATCH] Match:Support for signed scalar SAT_ADD IMM form 2

From: panciyan <panci...@eswincomputing.com>

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 <panci...@eswincomputing.com>
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

Reply via email to