aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPan Li <pan2.li@intel.com>2024-06-05 16:42:05 +0800
committerPan Li <pan2.li@intel.com>2024-06-08 16:36:34 +0800
commitab50ac8180beae9001c97cc036ce0df055e25b41 (patch)
tree925905c6ba447f556c8212a633893ee1a9c91c68 /gcc
parente22b7f741ab54ff3a3f8a676ce9e7414fe174958 (diff)
downloadgcc-ab50ac8180beae9001c97cc036ce0df055e25b41.zip
gcc-ab50ac8180beae9001c97cc036ce0df055e25b41.tar.gz
gcc-ab50ac8180beae9001c97cc036ce0df055e25b41.tar.bz2
RISC-V: Implement .SAT_SUB for unsigned scalar int
As the middle support of .SAT_SUB committed, implement the unsigned scalar int of .SAT_SUB for the riscv backend. Consider below example code: T __attribute__((noinline)) \ sat_u_sub_##T##_fmt_1 (T x, T y) \ { \ return (x - y) & (-(T)(x >= y)); \ } T __attribute__((noinline)) \ sat_u_sub_##T##_fmt_2 (T x, T y) \ { \ return (x - y) & (-(T)(x > y)); \ } DEF_SAT_U_SUB_FMT_1(uint64_t); DEF_SAT_U_SUB_FMT_2(uint64_t); Before this patch: sat_u_sub_uint64_t_fmt_1: bltu a0,a1,.L2 sub a0,a0,a1 ret .L2: li a0,0 ret After this patch: sat_u_sub_uint64_t_fmt_1: sltu a5,a0,a1 addi a5,a5,-1 sub a0,a0,a1 and a0,a5,a0 ret ToDo: Only above 2 forms of .SAT_SUB are support for now, we will support more forms of .SAT_SUB in the middle-end in short future. The below test suites are passed for this patch. * The rv64gcv fully regression test. gcc/ChangeLog: * config/riscv/riscv-protos.h (riscv_expand_ussub): Add new func decl for ussub expanding. * config/riscv/riscv.cc (riscv_expand_ussub): Ditto but for impl. * config/riscv/riscv.md (ussub<mode>3): Add new pattern ussub for scalar modes. gcc/testsuite/ChangeLog: * gcc.target/riscv/sat_arith.h: Add test macros and comments. * gcc.target/riscv/sat_u_sub-1.c: New test. * gcc.target/riscv/sat_u_sub-2.c: New test. * gcc.target/riscv/sat_u_sub-3.c: New test. * gcc.target/riscv/sat_u_sub-4.c: New test. * gcc.target/riscv/sat_u_sub-5.c: New test. * gcc.target/riscv/sat_u_sub-6.c: New test. * gcc.target/riscv/sat_u_sub-7.c: New test. * gcc.target/riscv/sat_u_sub-8.c: New test. * gcc.target/riscv/sat_u_sub-run-1.c: New test. * gcc.target/riscv/sat_u_sub-run-2.c: New test. * gcc.target/riscv/sat_u_sub-run-3.c: New test. * gcc.target/riscv/sat_u_sub-run-4.c: New test. * gcc.target/riscv/sat_u_sub-run-5.c: New test. * gcc.target/riscv/sat_u_sub-run-6.c: New test. * gcc.target/riscv/sat_u_sub-run-7.c: New test. * gcc.target/riscv/sat_u_sub-run-8.c: New test. Signed-off-by: Pan Li <pan2.li@intel.com>
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/riscv/riscv-protos.h1
-rw-r--r--gcc/config/riscv/riscv.cc35
-rw-r--r--gcc/config/riscv/riscv.md11
-rw-r--r--gcc/testsuite/gcc.target/riscv/sat_arith.h23
-rw-r--r--gcc/testsuite/gcc.target/riscv/sat_u_sub-1.c18
-rw-r--r--gcc/testsuite/gcc.target/riscv/sat_u_sub-2.c19
-rw-r--r--gcc/testsuite/gcc.target/riscv/sat_u_sub-3.c18
-rw-r--r--gcc/testsuite/gcc.target/riscv/sat_u_sub-4.c17
-rw-r--r--gcc/testsuite/gcc.target/riscv/sat_u_sub-5.c18
-rw-r--r--gcc/testsuite/gcc.target/riscv/sat_u_sub-6.c19
-rw-r--r--gcc/testsuite/gcc.target/riscv/sat_u_sub-7.c18
-rw-r--r--gcc/testsuite/gcc.target/riscv/sat_u_sub-8.c17
-rw-r--r--gcc/testsuite/gcc.target/riscv/sat_u_sub-run-1.c25
-rw-r--r--gcc/testsuite/gcc.target/riscv/sat_u_sub-run-2.c25
-rw-r--r--gcc/testsuite/gcc.target/riscv/sat_u_sub-run-3.c25
-rw-r--r--gcc/testsuite/gcc.target/riscv/sat_u_sub-run-4.c25
-rw-r--r--gcc/testsuite/gcc.target/riscv/sat_u_sub-run-5.c25
-rw-r--r--gcc/testsuite/gcc.target/riscv/sat_u_sub-run-6.c25
-rw-r--r--gcc/testsuite/gcc.target/riscv/sat_u_sub-run-7.c25
-rw-r--r--gcc/testsuite/gcc.target/riscv/sat_u_sub-run-8.c25
20 files changed, 414 insertions, 0 deletions
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index 0704968..09eb3a5 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -134,6 +134,7 @@ extern bool
riscv_zcmp_valid_stack_adj_bytes_p (HOST_WIDE_INT, int);
extern void riscv_legitimize_poly_move (machine_mode, rtx, rtx, rtx);
extern void riscv_expand_usadd (rtx, rtx, rtx);
+extern void riscv_expand_ussub (rtx, rtx, rtx);
#ifdef RTX_CODE
extern void riscv_expand_int_scc (rtx, enum rtx_code, rtx, rtx, bool *invert_ptr = 0);
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 9704ff9..95f3636 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -11612,6 +11612,41 @@ riscv_expand_usadd (rtx dest, rtx x, rtx y)
emit_move_insn (dest, gen_lowpart (mode, xmode_dest));
}
+/* Implements the unsigned saturation sub standard name usadd for int mode.
+
+ z = SAT_SUB(x, y).
+ =>
+ 1. minus = x - y.
+ 2. lt = x < y.
+ 3. lt = lt - 1.
+ 4. z = minus & lt. */
+
+void
+riscv_expand_ussub (rtx dest, rtx x, rtx y)
+{
+ machine_mode mode = GET_MODE (dest);
+ rtx pmode_x = gen_lowpart (Pmode, x);
+ rtx pmode_y = gen_lowpart (Pmode, y);
+ rtx pmode_lt = gen_reg_rtx (Pmode);
+ rtx pmode_minus = gen_reg_rtx (Pmode);
+ rtx pmode_dest = gen_reg_rtx (Pmode);
+
+ /* Step-1: minus = x - y */
+ riscv_emit_binary (MINUS, pmode_minus, pmode_x, pmode_y);
+
+ /* Step-2: lt = x < y */
+ riscv_emit_binary (LTU, pmode_lt, pmode_x, pmode_y);
+
+ /* Step-3: lt = lt - 1 (lt + (-1)) */
+ riscv_emit_binary (PLUS, pmode_lt, pmode_lt, CONSTM1_RTX (Pmode));
+
+ /* Step-4: pmode_dest = minus & lt */
+ riscv_emit_binary (AND, pmode_dest, pmode_lt, pmode_minus);
+
+ /* Step-5: dest = pmode_dest */
+ emit_move_insn (dest, gen_lowpart (mode, pmode_dest));
+}
+
/* Initialize the GCC target structure. */
#undef TARGET_ASM_ALIGNED_HI_OP
#define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index e57bfcf..7a9454d 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -4228,6 +4228,17 @@
}
)
+(define_expand "ussub<mode>3"
+ [(match_operand:ANYI 0 "register_operand")
+ (match_operand:ANYI 1 "register_operand")
+ (match_operand:ANYI 2 "register_operand")]
+ ""
+ {
+ riscv_expand_ussub (operands[0], operands[1], operands[2]);
+ DONE;
+ }
+)
+
;; These are forms of (x << C1) + C2, potentially canonicalized from
;; ((x + C2') << C1. Depending on the cost to load C2 vs C2' we may
;; want to go ahead and recognize this form as C2 may be cheaper to
diff --git a/gcc/testsuite/gcc.target/riscv/sat_arith.h b/gcc/testsuite/gcc.target/riscv/sat_arith.h
index 976ef1c..9c60ac0 100644
--- a/gcc/testsuite/gcc.target/riscv/sat_arith.h
+++ b/gcc/testsuite/gcc.target/riscv/sat_arith.h
@@ -3,6 +3,9 @@
#include <stdint-gcc.h>
+/******************************************************************************/
+/* Saturation Add (unsigned and signed) */
+/******************************************************************************/
#define DEF_SAT_U_ADD_FMT_1(T) \
T __attribute__((noinline)) \
sat_u_add_##T##_fmt_1 (T x, T y) \
@@ -72,4 +75,24 @@ vec_sat_u_add_##T##_fmt_1 (T *out, T *op_1, T *op_2, unsigned limit) \
#define RUN_VEC_SAT_U_ADD_FMT_1(T, out, op_1, op_2, N) \
vec_sat_u_add_##T##_fmt_1(out, op_1, op_2, N)
+/******************************************************************************/
+/* Saturation Sub (Unsigned and Signed) */
+/******************************************************************************/
+#define DEF_SAT_U_SUB_FMT_1(T) \
+T __attribute__((noinline)) \
+sat_u_sub_##T##_fmt_1 (T x, T y) \
+{ \
+ return (x - y) & (-(T)(x >= y)); \
+}
+
+#define DEF_SAT_U_SUB_FMT_2(T) \
+T __attribute__((noinline)) \
+sat_u_sub_##T##_fmt_2 (T x, T y) \
+{ \
+ return (x - y) & (-(T)(x > y)); \
+}
+
+#define RUN_SAT_U_SUB_FMT_1(T, x, y) sat_u_sub_##T##_fmt_1(x, y)
+#define RUN_SAT_U_SUB_FMT_2(T, x, y) sat_u_sub_##T##_fmt_2(x, y)
+
#endif
diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_sub-1.c b/gcc/testsuite/gcc.target/riscv/sat_u_sub-1.c
new file mode 100644
index 0000000..73be7d5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sat_u_sub-1.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -O3 -fdump-rtl-expand-details -fno-schedule-insns -fno-schedule-insns2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "sat_arith.h"
+
+/*
+** sat_u_sub_uint8_t_fmt_1:
+** sub\s+[atx][0-9]+,\s*a0,\s*a1
+** sltu\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*a0,\s*[atx][0-9]+
+** andi\s+a0,\s*a0,\s*0xff
+** ret
+*/
+DEF_SAT_U_SUB_FMT_1(uint8_t)
+
+/* { dg-final { scan-rtl-dump-times ".SAT_SUB " 2 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_sub-2.c b/gcc/testsuite/gcc.target/riscv/sat_u_sub-2.c
new file mode 100644
index 0000000..7bd5efc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sat_u_sub-2.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -O3 -fdump-rtl-expand-details -fno-schedule-insns -fno-schedule-insns2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "sat_arith.h"
+
+/*
+** sat_u_sub_uint16_t_fmt_1:
+** sub\s+[atx][0-9]+,\s*a0,\s*a1
+** sltu\s+[atx][0-9]+,\s*a0,\s*a1
+** addi\s+[atx][0-9]+,\s*[atx][0-9]+,\s*-1
+** and\s+a0,\s*[atx][0-9]+,\s*[atx][0-9]+
+** slli\s+a0,\s*a0,\s*48
+** srli\s+a0,\s*a0,\s*48
+** ret
+*/
+DEF_SAT_U_SUB_FMT_1(uint16_t)
+
+/* { dg-final { scan-rtl-dump-times ".SAT_SUB " 2 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_sub-3.c b/gcc/testsuite/gcc.target/riscv/sat_u_sub-3.c
new file mode 100644
index 0000000..a60fc9b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sat_u_sub-3.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -O3 -fdump-rtl-expand-details -fno-schedule-insns -fno-schedule-insns2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "sat_arith.h"
+
+/*
+** sat_u_sub_uint32_t_fmt_1:
+** sub\s+[atx][0-9]+,\s*a0,\s*a1
+** sltu\s+[atx][0-9]+,\s*a0,\s*a1
+** addi\s+[atx][0-9]+,\s*[atx][0-9]+,\s*-1
+** and\s+a0,\s*[atx][0-9]+,\s*[atx][0-9]+
+** sext.w\s+a0,\s*a0
+** ret
+*/
+DEF_SAT_U_SUB_FMT_1(uint32_t)
+
+/* { dg-final { scan-rtl-dump-times ".SAT_SUB " 2 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_sub-4.c b/gcc/testsuite/gcc.target/riscv/sat_u_sub-4.c
new file mode 100644
index 0000000..bae46a0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sat_u_sub-4.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -O3 -fdump-rtl-expand-details -fno-schedule-insns -fno-schedule-insns2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "sat_arith.h"
+
+/*
+** sat_u_sub_uint64_t_fmt_1:
+** sub\s+[atx][0-9]+,\s*a0,\s*a1
+** sltu\s+[atx][0-9]+,\s*a0,\s*a1
+** addi\s+a0,\s*[atx][0-9]+,\s*-1
+** and\s+a0,\s*[atx][0-9]+,\s*[atx][0-9]+
+** ret
+*/
+DEF_SAT_U_SUB_FMT_1(uint64_t)
+
+/* { dg-final { scan-rtl-dump-times ".SAT_SUB " 2 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_sub-5.c b/gcc/testsuite/gcc.target/riscv/sat_u_sub-5.c
new file mode 100644
index 0000000..e917487
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sat_u_sub-5.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -O3 -fdump-rtl-expand-details -fno-schedule-insns -fno-schedule-insns2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "sat_arith.h"
+
+/*
+** sat_u_sub_uint8_t_fmt_2:
+** sub\s+[atx][0-9]+,\s*a0,\s*a1
+** sltu\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*a0,\s*[atx][0-9]+
+** andi\s+a0,\s*a0,\s*0xff
+** ret
+*/
+DEF_SAT_U_SUB_FMT_2(uint8_t)
+
+/* { dg-final { scan-rtl-dump-times ".SAT_SUB " 2 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_sub-6.c b/gcc/testsuite/gcc.target/riscv/sat_u_sub-6.c
new file mode 100644
index 0000000..4e3c91d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sat_u_sub-6.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -O3 -fdump-rtl-expand-details -fno-schedule-insns -fno-schedule-insns2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "sat_arith.h"
+
+/*
+** sat_u_sub_uint16_t_fmt_2:
+** sub\s+[atx][0-9]+,\s*a0,\s*a1
+** sltu\s+[atx][0-9]+,\s*a0,\s*a1
+** addi\s+[atx][0-9]+,\s*[atx][0-9]+,\s*-1
+** and\s+a0,\s*[atx][0-9]+,\s*[atx][0-9]+
+** slli\s+a0,\s*a0,\s*48
+** srli\s+a0,\s*a0,\s*48
+** ret
+*/
+DEF_SAT_U_SUB_FMT_2(uint16_t)
+
+/* { dg-final { scan-rtl-dump-times ".SAT_SUB " 2 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_sub-7.c b/gcc/testsuite/gcc.target/riscv/sat_u_sub-7.c
new file mode 100644
index 0000000..e1b0eac
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sat_u_sub-7.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -O3 -fdump-rtl-expand-details -fno-schedule-insns -fno-schedule-insns2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "sat_arith.h"
+
+/*
+** sat_u_sub_uint32_t_fmt_2:
+** sub\s+[atx][0-9]+,\s*a0,\s*a1
+** sltu\s+[atx][0-9]+,\s*a0,\s*a1
+** addi\s+[atx][0-9]+,\s*[atx][0-9]+,\s*-1
+** and\s+a0,\s*[atx][0-9]+,\s*[atx][0-9]+
+** sext.w\s+a0,\s*a0
+** ret
+*/
+DEF_SAT_U_SUB_FMT_2(uint32_t)
+
+/* { dg-final { scan-rtl-dump-times ".SAT_SUB " 2 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_sub-8.c b/gcc/testsuite/gcc.target/riscv/sat_u_sub-8.c
new file mode 100644
index 0000000..d73f00f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sat_u_sub-8.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -O3 -fdump-rtl-expand-details -fno-schedule-insns -fno-schedule-insns2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "sat_arith.h"
+
+/*
+** sat_u_sub_uint64_t_fmt_2:
+** sub\s+[atx][0-9]+,\s*a0,\s*a1
+** sltu\s+[atx][0-9]+,\s*a0,\s*a1
+** addi\s+a0,\s*[atx][0-9]+,\s*-1
+** and\s+a0,\s*[atx][0-9]+,\s*[atx][0-9]+
+** ret
+*/
+DEF_SAT_U_SUB_FMT_2(uint64_t)
+
+/* { dg-final { scan-rtl-dump-times ".SAT_SUB " 2 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_sub-run-1.c b/gcc/testsuite/gcc.target/riscv/sat_u_sub-run-1.c
new file mode 100644
index 0000000..931420a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sat_u_sub-run-1.c
@@ -0,0 +1,25 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99" } */
+
+#include "sat_arith.h"
+
+#define T uint8_t
+#define RUN_SAT_BINARY RUN_SAT_U_SUB_FMT_1
+
+DEF_SAT_U_SUB_FMT_1(T)
+
+T test_data[][3] = {
+ /* arg_0, arg_1, expect */
+ { 0, 0, 0, },
+ { 0, 1, 0, },
+ { 1, 1, 0, },
+ { 255, 254, 1, },
+ { 255, 255, 0, },
+ { 254, 255, 0, },
+ { 253, 254, 0, },
+ { 0, 255, 0, },
+ { 1, 255, 0, },
+ { 32, 5, 27, },
+};
+
+#include "scalar_sat_binary.h"
diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_sub-run-2.c b/gcc/testsuite/gcc.target/riscv/sat_u_sub-run-2.c
new file mode 100644
index 0000000..1534cf9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sat_u_sub-run-2.c
@@ -0,0 +1,25 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99" } */
+
+#include "sat_arith.h"
+
+#define T uint16_t
+#define RUN_SAT_BINARY RUN_SAT_U_SUB_FMT_1
+
+DEF_SAT_U_SUB_FMT_1(T)
+
+T test_data[][3] = {
+ /* arg_0, arg_1, expect */
+ { 0, 0, 0, },
+ { 0, 1, 0, },
+ { 1, 1, 0, },
+ { 65535, 65534, 1, },
+ { 65535, 65535, 0, },
+ { 65534, 65535, 0, },
+ { 65533, 65534, 0, },
+ { 0, 65535, 0, },
+ { 1, 65535, 0, },
+ { 35, 5, 30, },
+};
+
+#include "scalar_sat_binary.h"
diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_sub-run-3.c b/gcc/testsuite/gcc.target/riscv/sat_u_sub-run-3.c
new file mode 100644
index 0000000..5c60d28
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sat_u_sub-run-3.c
@@ -0,0 +1,25 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99" } */
+
+#include "sat_arith.h"
+
+#define T uint32_t
+#define RUN_SAT_BINARY RUN_SAT_U_SUB_FMT_1
+
+DEF_SAT_U_SUB_FMT_1(T)
+
+T test_data[][3] = {
+ /* arg_0, arg_1, expect */
+ { 0, 0, 0, },
+ { 0, 1, 0, },
+ { 1, 1, 0, },
+ { 4294967295, 4294967294, 1, },
+ { 4294967295, 4294967295, 0, },
+ { 4294967294, 4294967295, 0, },
+ { 4294967293, 4294967294, 0, },
+ { 1, 4294967295, 0, },
+ { 2, 4294967295, 0, },
+ { 5, 1, 4, },
+};
+
+#include "scalar_sat_binary.h"
diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_sub-run-4.c b/gcc/testsuite/gcc.target/riscv/sat_u_sub-run-4.c
new file mode 100644
index 0000000..403764c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sat_u_sub-run-4.c
@@ -0,0 +1,25 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99" } */
+
+#include "sat_arith.h"
+
+#define T uint64_t
+#define RUN_SAT_BINARY RUN_SAT_U_SUB_FMT_1
+
+DEF_SAT_U_SUB_FMT_1(T)
+
+T test_data[][3] = {
+ /* arg_0, arg_1, expect */
+ { 0, 0, 0, },
+ { 0, 1, 0, },
+ { 1, 1, 0, },
+ { 18446744073709551615u, 18446744073709551614u, 1, },
+ { 18446744073709551615u, 18446744073709551615u, 0, },
+ { 18446744073709551614u, 18446744073709551615u, 0, },
+ { 18446744073709551613u, 18446744073709551614u, 0, },
+ { 0, 18446744073709551615u, 0, },
+ { 1, 18446744073709551615u, 0, },
+ { 43, 11, 32, },
+};
+
+#include "scalar_sat_binary.h"
diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_sub-run-5.c b/gcc/testsuite/gcc.target/riscv/sat_u_sub-run-5.c
new file mode 100644
index 0000000..6fa44ca
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sat_u_sub-run-5.c
@@ -0,0 +1,25 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99" } */
+
+#include "sat_arith.h"
+
+#define T uint8_t
+#define RUN_SAT_BINARY RUN_SAT_U_SUB_FMT_2
+
+DEF_SAT_U_SUB_FMT_2(T)
+
+T test_data[][3] = {
+ /* arg_0, arg_1, expect */
+ { 0, 0, 0, },
+ { 0, 1, 0, },
+ { 1, 1, 0, },
+ { 255, 254, 1, },
+ { 255, 255, 0, },
+ { 254, 255, 0, },
+ { 253, 254, 0, },
+ { 0, 255, 0, },
+ { 1, 255, 0, },
+ { 32, 5, 27, },
+};
+
+#include "scalar_sat_binary.h"
diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_sub-run-6.c b/gcc/testsuite/gcc.target/riscv/sat_u_sub-run-6.c
new file mode 100644
index 0000000..7deaae9a5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sat_u_sub-run-6.c
@@ -0,0 +1,25 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99" } */
+
+#include "sat_arith.h"
+
+#define T uint16_t
+#define RUN_SAT_BINARY RUN_SAT_U_SUB_FMT_2
+
+DEF_SAT_U_SUB_FMT_2(T)
+
+T test_data[][3] = {
+ /* arg_0, arg_1, expect */
+ { 0, 0, 0, },
+ { 0, 1, 0, },
+ { 1, 1, 0, },
+ { 65535, 65534, 1, },
+ { 65535, 65535, 0, },
+ { 65534, 65535, 0, },
+ { 65533, 65534, 0, },
+ { 0, 65535, 0, },
+ { 1, 65535, 0, },
+ { 35, 5, 30, },
+};
+
+#include "scalar_sat_binary.h"
diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_sub-run-7.c b/gcc/testsuite/gcc.target/riscv/sat_u_sub-run-7.c
new file mode 100644
index 0000000..d9b1d5c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sat_u_sub-run-7.c
@@ -0,0 +1,25 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99" } */
+
+#include "sat_arith.h"
+
+#define T uint32_t
+#define RUN_SAT_BINARY RUN_SAT_U_SUB_FMT_2
+
+DEF_SAT_U_SUB_FMT_2(T)
+
+T test_data[][3] = {
+ /* arg_0, arg_1, expect */
+ { 0, 0, 0, },
+ { 0, 1, 0, },
+ { 1, 1, 0, },
+ { 4294967295, 4294967294, 1, },
+ { 4294967295, 4294967295, 0, },
+ { 4294967294, 4294967295, 0, },
+ { 4294967293, 4294967294, 0, },
+ { 1, 4294967295, 0, },
+ { 2, 4294967295, 0, },
+ { 5, 1, 4, },
+};
+
+#include "scalar_sat_binary.h"
diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_sub-run-8.c b/gcc/testsuite/gcc.target/riscv/sat_u_sub-run-8.c
new file mode 100644
index 0000000..2774c23
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sat_u_sub-run-8.c
@@ -0,0 +1,25 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99" } */
+
+#include "sat_arith.h"
+
+#define T uint64_t
+#define RUN_SAT_BINARY RUN_SAT_U_SUB_FMT_2
+
+DEF_SAT_U_SUB_FMT_2(T)
+
+T test_data[][3] = {
+ /* arg_0, arg_1, expect */
+ { 0, 0, 0, },
+ { 0, 1, 0, },
+ { 1, 1, 0, },
+ { 18446744073709551615u, 18446744073709551614u, 1, },
+ { 18446744073709551615u, 18446744073709551615u, 0, },
+ { 18446744073709551614u, 18446744073709551615u, 0, },
+ { 18446744073709551613u, 18446744073709551614u, 0, },
+ { 0, 18446744073709551615u, 0, },
+ { 1, 18446744073709551615u, 0, },
+ { 43, 11, 32, },
+};
+
+#include "scalar_sat_binary.h"