aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPan Li <pan2.li@intel.com>2024-07-05 09:02:47 +0800
committerPan Li <pan2.li@intel.com>2024-07-08 16:43:59 +0800
commitdafd63d7c5cddce1e00803606e742d75927b1a1e (patch)
tree1982efc01336c0c2aea4cc7ec81d8e5a901f9bda
parent7183a8ca18d5889a1f66ec1edbda00200d700c6c (diff)
downloadgcc-dafd63d7c5cddce1e00803606e742d75927b1a1e.zip
gcc-dafd63d7c5cddce1e00803606e742d75927b1a1e.tar.gz
gcc-dafd63d7c5cddce1e00803606e742d75927b1a1e.tar.bz2
RISC-V: Implement .SAT_TRUNC for vector unsigned int
This patch would like to implement the .SAT_TRUNC for the RISC-V backend. With the help of the RVV Vector Narrowing Fixed-Point Clip Instructions. The below SEW(S) are supported: * e64 => e32 * e64 => e16 * e64 => e8 * e32 => e16 * e32 => e8 * e16 => e8 Take below example to see the changes to asm. Form 1: #define DEF_VEC_SAT_U_TRUNC_FMT_1(NT, WT) \ void __attribute__((noinline)) \ vec_sat_u_trunc_##NT##_##WT##_fmt_1 (NT *out, WT *in, unsigned limit) \ { \ unsigned i; \ for (i = 0; i < limit; i++) \ { \ WT x = in[i]; \ bool overflow = x > (WT)(NT)(-1); \ out[i] = ((NT)x) | (NT)-overflow; \ } \ } DEF_VEC_SAT_U_TRUNC_FMT_1 (uint32_t, uint64_t) Before this patch: .L3: vsetvli a5,a2,e64,m1,ta,ma vle64.v v1,0(a1) vmsgtu.vv v0,v1,v2 vsetvli zero,zero,e32,mf2,ta,ma vncvt.x.x.w v1,v1 vmerge.vim v1,v1,-1,v0 vse32.v v1,0(a0) slli a4,a5,3 add a1,a1,a4 slli a4,a5,2 add a0,a0,a4 sub a2,a2,a5 bne a2,zero,.L3 After this patch: .L3: vsetvli a5,a2,e32,mf2,ta,ma vle64.v v1,0(a1) vnclipu.wi v1,v1,0 vse32.v v1,0(a0) slli a4,a5,3 add a1,a1,a4 slli a4,a5,2 add a0,a0,a4 sub a2,a2,a5 bne a2,zero,.L3 Passed the rv64gcv fully regression tests. gcc/ChangeLog: * config/riscv/autovec.md (ustrunc<mode><v_double_trunc>2): Add new pattern for double truncation. (ustrunc<mode><v_quad_trunc>2): Ditto but for quad truncation. (ustrunc<mode><v_oct_trunc>2): Ditto but for oct truncation. * config/riscv/riscv-protos.h (expand_vec_double_ustrunc): Add new func decl to expand double vec ustrunc. (expand_vec_quad_ustrunc): Ditto but for quad. (expand_vec_oct_ustrunc): Ditto but for oct. * config/riscv/riscv-v.cc (expand_vec_double_ustrunc): Add new func impl to expand vector double ustrunc. (expand_vec_quad_ustrunc): Ditto but for quad. (expand_vec_oct_ustrunc): Ditto but for oct. gcc/testsuite/ChangeLog: * gcc.target/riscv/rvv/autovec/binop/vec_sat_arith.h: Add helper test macros. * gcc.target/riscv/rvv/autovec/unop/vec_sat_data.h: New test. * gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-1.c: New test. * gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-2.c: New test. * gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-3.c: New test. * gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-4.c: New test. * gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-5.c: New test. * gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-6.c: New test. * gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-run-1.c: New test. * gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-run-2.c: New test. * gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-run-3.c: New test. * gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-run-4.c: New test. * gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-run-5.c: New test. * gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-run-6.c: New test. * gcc.target/riscv/rvv/autovec/unop/vec_sat_unary_vv_run.h: New test. Signed-off-by: Pan Li <pan2.li@intel.com>
-rw-r--r--gcc/config/riscv/autovec.md35
-rw-r--r--gcc/config/riscv/riscv-protos.h4
-rw-r--r--gcc/config/riscv/riscv-v.cc46
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vec_sat_arith.h22
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_data.h394
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-1.c19
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-2.c21
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-3.c23
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-4.c19
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-5.c21
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-6.c19
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-run-1.c16
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-run-2.c16
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-run-3.c16
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-run-4.c16
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-run-5.c16
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-run-6.c16
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_unary_vv_run.h23
18 files changed, 742 insertions, 0 deletions
diff --git a/gcc/config/riscv/autovec.md b/gcc/config/riscv/autovec.md
index 0fb6316..d5793ac 100644
--- a/gcc/config/riscv/autovec.md
+++ b/gcc/config/riscv/autovec.md
@@ -2646,6 +2646,7 @@
;; Includes:
;; - add
;; - sub
+;; - trunc
;; =========================================================================
(define_expand "usadd<mode>3"
[(match_operand:V_VLSI 0 "register_operand")
@@ -2669,6 +2670,40 @@
}
)
+(define_expand "ustrunc<mode><v_double_trunc>2"
+ [(match_operand:<V_DOUBLE_TRUNC> 0 "register_operand")
+ (match_operand:VWEXTI 1 "register_operand")]
+ "TARGET_VECTOR"
+ {
+ riscv_vector::expand_vec_double_ustrunc (operands[0], operands[1],
+ <MODE>mode);
+ DONE;
+ }
+)
+
+(define_expand "ustrunc<mode><v_quad_trunc>2"
+ [(match_operand:<V_QUAD_TRUNC> 0 "register_operand")
+ (match_operand:VQEXTI 1 "register_operand")]
+ "TARGET_VECTOR"
+ {
+ riscv_vector::expand_vec_quad_ustrunc (operands[0], operands[1], <MODE>mode,
+ <V_DOUBLE_TRUNC>mode);
+ DONE;
+ }
+)
+
+(define_expand "ustrunc<mode><v_oct_trunc>2"
+ [(match_operand:<V_OCT_TRUNC> 0 "register_operand")
+ (match_operand:VOEXTI 1 "register_operand")]
+ "TARGET_VECTOR"
+ {
+ riscv_vector::expand_vec_oct_ustrunc (operands[0], operands[1], <MODE>mode,
+ <V_DOUBLE_TRUNC>mode,
+ <V_QUAD_TRUNC>mode);
+ DONE;
+ }
+)
+
;; =========================================================================
;; == Early break auto-vectorization patterns
;; =========================================================================
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index abf6e34..7c0ea1b 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -643,6 +643,10 @@ 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_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);
+void expand_vec_oct_ustrunc (rtx, rtx, machine_mode, machine_mode,
+ machine_mode);
#endif
bool sew64_scalar_helper (rtx *, rtx *, rtx, machine_mode,
bool, void (*)(rtx *, rtx), enum avl_type);
diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index 5306711..e290675 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -4901,6 +4901,52 @@ expand_vec_ussub (rtx op_0, rtx op_1, rtx op_2, machine_mode vec_mode)
emit_vec_binary_alu (op_0, op_1, op_2, US_MINUS, vec_mode);
}
+/* Expand the standard name ustrunc<m><n>2 for double vector mode, like
+ DI => SI. we can leverage the vector fixed point vector narrowing
+ fixed-point clip directly. */
+
+void
+expand_vec_double_ustrunc (rtx op_0, rtx op_1, machine_mode vec_mode)
+{
+ insn_code icode;
+ rtx zero = CONST0_RTX (Xmode);
+ enum unspec unspec = UNSPEC_VNCLIPU;
+ rtx ops[] = {op_0, op_1, zero};
+
+ icode = code_for_pred_narrow_clip_scalar (unspec, vec_mode);
+ emit_vlmax_insn (icode, BINARY_OP_VXRM_RNU, ops);
+}
+
+/* Expand the standard name ustrunc<m><n>2 for double vector mode, like
+ DI => HI. we can leverage the vector fixed point vector narrowing
+ fixed-point clip directly. */
+
+void
+expand_vec_quad_ustrunc (rtx op_0, rtx op_1, machine_mode vec_mode,
+ machine_mode double_mode)
+{
+ rtx double_rtx = gen_reg_rtx (double_mode);
+
+ expand_vec_double_ustrunc (double_rtx, op_1, vec_mode);
+ expand_vec_double_ustrunc (op_0, double_rtx, double_mode);
+}
+
+/* Expand the standard name ustrunc<m><n>2 for double vector mode, like
+ DI => QI. we can leverage the vector fixed point vector narrowing
+ fixed-point clip directly. */
+
+void
+expand_vec_oct_ustrunc (rtx op_0, rtx op_1, machine_mode vec_mode,
+ machine_mode double_mode, machine_mode quad_mode)
+{
+ rtx double_rtx = gen_reg_rtx (double_mode);
+ rtx quad_rtx = gen_reg_rtx (quad_mode);
+
+ expand_vec_double_ustrunc (double_rtx, op_1, vec_mode);
+ expand_vec_double_ustrunc (quad_rtx, double_rtx, double_mode);
+ expand_vec_double_ustrunc (op_0, quad_rtx, quad_mode);
+}
+
/* Vectorize popcount by the Wilkes-Wheeler-Gill algorithm that libgcc uses as
well. */
void
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vec_sat_arith.h b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vec_sat_arith.h
index a311603..b55a589 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vec_sat_arith.h
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vec_sat_arith.h
@@ -329,4 +329,26 @@ vec_sat_u_sub_trunc_##OUT_T##_fmt_1 (OUT_T *out, IN_T *op_1, IN_T y, \
#define RUN_VEC_SAT_U_SUB_TRUNC_FMT_1(OUT_T, IN_T, out, op_1, y, N) \
vec_sat_u_sub_trunc_##OUT_T##_fmt_1(out, op_1, y, N)
+/******************************************************************************/
+/* Saturation Truncation (Unsigned and Signed) */
+/******************************************************************************/
+#define DEF_VEC_SAT_U_TRUNC_FMT_1(NT, WT) \
+void __attribute__((noinline)) \
+vec_sat_u_trunc_##NT##_##WT##_fmt_1 (NT *out, WT *in, unsigned limit) \
+{ \
+ unsigned i; \
+ for (i = 0; i < limit; i++) \
+ { \
+ WT x = in[i]; \
+ bool overflow = x > (WT)(NT)(-1); \
+ out[i] = ((NT)x) | (NT)-overflow; \
+ } \
+}
+#define DEF_VEC_SAT_U_TRUNC_FMT_1_WRAP(NT, WT) DEF_VEC_SAT_U_TRUNC_FMT_1(NT, WT)
+
+#define RUN_VEC_SAT_U_TRUNC_FMT_1(NT, WT, out, in, N) \
+ vec_sat_u_trunc_##NT##_##WT##_fmt_1 (out, in, N)
+#define RUN_VEC_SAT_U_TRUNC_FMT_1_WRAP(NT, WT, out, in, N) \
+ RUN_VEC_SAT_U_TRUNC_FMT_1(NT, WT, out, in, N)
+
#endif
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_data.h b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_data.h
new file mode 100644
index 0000000..6b23ec8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_data.h
@@ -0,0 +1,394 @@
+#ifndef HAVE_DEFINE_VEC_SAT_DATA_H
+#define HAVE_DEFINE_VEC_SAT_DATA_H
+
+#define N 16
+
+#define TEST_UNARY_STRUCT_NAME(T1, T2) test_##T1##_##T2##_s
+#define TEST_UNARY_STRUCT_DECL(T1, T2) struct TEST_UNARY_STRUCT_NAME(T1, T2)
+#define TEST_UNARY_STRUCT(T1, T2) \
+ struct TEST_UNARY_STRUCT_NAME(T1, T2) \
+ { \
+ T2 in[N]; \
+ T1 expect[N]; \
+ T1 out[N]; \
+ };
+
+#define TEST_UNARY_DATA(T1, T2) test_##T1##_##T2##_data
+#define TEST_UNARY_DATA_WRAP(T1, T2) TEST_UNARY_DATA(T1, T2)
+
+TEST_UNARY_STRUCT(uint8_t, uint16_t)
+TEST_UNARY_STRUCT(uint8_t, uint32_t)
+TEST_UNARY_STRUCT(uint8_t, uint64_t)
+
+TEST_UNARY_STRUCT(uint16_t, uint32_t)
+TEST_UNARY_STRUCT(uint16_t, uint64_t)
+
+TEST_UNARY_STRUCT(uint32_t, uint64_t)
+
+TEST_UNARY_STRUCT_DECL(uint8_t, uint16_t) \
+ TEST_UNARY_DATA(uint8_t, uint16_t)[] =
+{
+ {
+ {
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ },
+ {
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ },
+ },
+ {
+ {
+ 1, 2, 3, 4,
+ 1, 2, 3, 4,
+ 1, 2, 3, 4,
+ 1, 2, 3, 4,
+ },
+ {
+ 1, 2, 3, 4,
+ 1, 2, 3, 4,
+ 1, 2, 3, 4,
+ 1, 2, 3, 4,
+ },
+ },
+ {
+ {
+ 254, 255, 256, 257,
+ 254, 255, 256, 257,
+ 254, 255, 256, 257,
+ 254, 255, 256, 257,
+ },
+ {
+ 254, 255, 255, 255,
+ 254, 255, 255, 255,
+ 254, 255, 255, 255,
+ 254, 255, 255, 255,
+ },
+ },
+ {
+ {
+ 65534, 65535, 650, 24,
+ 65534, 65535, 650, 24,
+ 65534, 65535, 650, 24,
+ 65534, 65535, 650, 24,
+ },
+ {
+ 255, 255, 255, 24,
+ 255, 255, 255, 24,
+ 255, 255, 255, 24,
+ 255, 255, 255, 24,
+ },
+ },
+};
+
+TEST_UNARY_STRUCT_DECL(uint8_t, uint32_t) \
+ TEST_UNARY_DATA(uint8_t, uint32_t)[] =
+{
+ {
+ {
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ },
+ {
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ },
+ },
+ {
+ {
+ 1, 2, 3, 4,
+ 1, 2, 3, 4,
+ 1, 2, 3, 4,
+ 1, 2, 3, 4,
+ },
+ {
+ 1, 2, 3, 4,
+ 1, 2, 3, 4,
+ 1, 2, 3, 4,
+ 1, 2, 3, 4,
+ },
+ },
+ {
+ {
+ 254, 255, 256, 257,
+ 254, 255, 256, 257,
+ 254, 255, 256, 257,
+ 254, 255, 256, 257,
+ },
+ {
+ 254, 255, 255, 255,
+ 254, 255, 255, 255,
+ 254, 255, 255, 255,
+ 254, 255, 255, 255,
+ },
+ },
+ {
+ {
+ 65534, 65535, 65536, 4294967291,
+ 65534, 65535, 65537, 4294967292,
+ 65534, 65535, 65538, 4294967293,
+ 65534, 65535, 65539, 4294967294,
+ },
+ {
+ 255, 255, 255, 255,
+ 255, 255, 255, 255,
+ 255, 255, 255, 255,
+ 255, 255, 255, 255,
+ },
+ },
+};
+
+TEST_UNARY_STRUCT_DECL(uint8_t, uint64_t) \
+ TEST_UNARY_DATA(uint8_t, uint64_t)[] =
+{
+ {
+ {
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ },
+ {
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ },
+ },
+ {
+ {
+ 1, 2, 3, 4,
+ 1, 2, 3, 4,
+ 1, 2, 3, 4,
+ 1, 2, 3, 4,
+ },
+ {
+ 1, 2, 3, 4,
+ 1, 2, 3, 4,
+ 1, 2, 3, 4,
+ 1, 2, 3, 4,
+ },
+ },
+ {
+ {
+ 254, 255, 256, 257,
+ 254, 255, 256, 257,
+ 254, 255, 256, 257,
+ 254, 255, 256, 257,
+ },
+ {
+ 254, 255, 255, 255,
+ 254, 255, 255, 255,
+ 254, 255, 255, 255,
+ 254, 255, 255, 255,
+ },
+ },
+ {
+ {
+ 65534, 65535, 4294967292, 4294967296,
+ 65534, 65536, 4294967293, 18446744073709551613u,
+ 65534, 65537, 4294967294, 18446744073709551614u,
+ 65534, 65538, 4294967295, 18446744073709551615u,
+ },
+ {
+ 255, 255, 255, 255,
+ 255, 255, 255, 255,
+ 255, 255, 255, 255,
+ 255, 255, 255, 255,
+ },
+ },
+};
+
+TEST_UNARY_STRUCT_DECL(uint16_t, uint32_t) \
+ TEST_UNARY_DATA(uint16_t, uint32_t)[] =
+{
+ {
+ {
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ },
+ {
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ },
+ },
+ {
+ {
+ 1, 2, 3, 4,
+ 1, 2, 3, 4,
+ 1, 2, 3, 4,
+ 1, 2, 3, 4,
+ },
+ {
+ 1, 2, 3, 4,
+ 1, 2, 3, 4,
+ 1, 2, 3, 4,
+ 1, 2, 3, 4,
+ },
+ },
+ {
+ {
+ 65534, 65535, 65536, 65537,
+ 65534, 65535, 65536, 65537,
+ 65534, 65535, 65536, 65537,
+ 65534, 65535, 65536, 65537,
+ },
+ {
+ 65534, 65535, 65535, 65535,
+ 65534, 65535, 65535, 65535,
+ 65534, 65535, 65535, 65535,
+ 65534, 65535, 65535, 65535,
+ },
+ },
+ {
+ {
+ 65534, 65535, 4294967295, 4294967291,
+ 65534, 65535, 4294967295, 4294967292,
+ 65534, 65535, 4294967295, 4294967293,
+ 65534, 65535, 4294967295, 4294967294,
+ },
+ {
+ 65534, 65535, 65535, 65535,
+ 65534, 65535, 65535, 65535,
+ 65534, 65535, 65535, 65535,
+ 65534, 65535, 65535, 65535,
+ },
+ },
+};
+
+TEST_UNARY_STRUCT_DECL(uint16_t, uint64_t) \
+ TEST_UNARY_DATA(uint16_t, uint64_t)[] =
+{
+ {
+ {
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ },
+ {
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ },
+ },
+ {
+ {
+ 1, 2, 3, 4,
+ 1, 2, 3, 4,
+ 1, 2, 3, 4,
+ 1, 2, 3, 4,
+ },
+ {
+ 1, 2, 3, 4,
+ 1, 2, 3, 4,
+ 1, 2, 3, 4,
+ 1, 2, 3, 4,
+ },
+ },
+ {
+ {
+ 65534, 65535, 65536, 65537,
+ 65534, 65535, 65536, 65537,
+ 65534, 65535, 65536, 65537,
+ 65534, 65535, 65536, 65537,
+ },
+ {
+ 65534, 65535, 65535, 65535,
+ 65534, 65535, 65535, 65535,
+ 65534, 65535, 65535, 65535,
+ 65534, 65535, 65535, 65535,
+ },
+ },
+ {
+ {
+ 65534, 65535, 4294967294, 4294967298,
+ 65534, 65536, 4294967295, 18446744073709551613u,
+ 65534, 65537, 4294967296, 18446744073709551614u,
+ 65534, 65538, 4294967297, 18446744073709551615u,
+ },
+ {
+ 65534, 65535, 65535, 65535,
+ 65534, 65535, 65535, 65535,
+ 65534, 65535, 65535, 65535,
+ 65534, 65535, 65535, 65535,
+ },
+ },
+};
+
+TEST_UNARY_STRUCT_DECL(uint32_t, uint64_t) \
+ TEST_UNARY_DATA(uint32_t, uint64_t)[] =
+{
+ {
+ {
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ },
+ {
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ },
+ },
+ {
+ {
+ 1, 2, 3, 4,
+ 1, 2, 3, 4,
+ 1, 2, 3, 4,
+ 1, 2, 3, 4,
+ },
+ {
+ 1, 2, 3, 4,
+ 1, 2, 3, 4,
+ 1, 2, 3, 4,
+ 1, 2, 3, 4,
+ },
+ },
+ {
+ {
+ 65534, 65535, 65536, 65537,
+ 65534, 65535, 65536, 65537,
+ 65534, 65535, 65536, 65537,
+ 65534, 65535, 65536, 65537,
+ },
+ {
+ 65534, 65535, 65536, 65537,
+ 65534, 65535, 65536, 65537,
+ 65534, 65535, 65536, 65537,
+ 65534, 65535, 65536, 65537,
+ },
+ },
+ {
+ {
+ 65534, 65535, 4294967294, 4294967298,
+ 65534, 65536, 4294967295, 18446744073709551613u,
+ 65534, 65537, 4294967296, 18446744073709551614u,
+ 65534, 65538, 4294967297, 18446744073709551615u,
+ },
+ {
+ 65534, 65535, 4294967294, 4294967295,
+ 65534, 65536, 4294967295, 4294967295,
+ 65534, 65537, 4294967295, 4294967295,
+ 65534, 65538, 4294967295, 4294967295,
+ },
+ },
+};
+
+#endif
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-1.c
new file mode 100644
index 0000000..dc96539
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-1.c
@@ -0,0 +1,19 @@
+/* { 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 "../binop/vec_sat_arith.h"
+
+/*
+** vec_sat_u_trunc_uint8_t_uint16_t_fmt_1:
+** ...
+** vsetvli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*e8,\s*mf2,\s*ta,\s*ma
+** vle16\.v\s+v[0-9]+,\s*0\([atx][0-9]+\)
+** vnclipu\.wi\s+v[0-9]+,\s*v[0-9]+,\s*0
+** vse8\.v\s+v[0-9]+,\s*0\([atx][0-9]+\)
+** ...
+*/
+DEF_VEC_SAT_U_TRUNC_FMT_1 (uint8_t, uint16_t)
+
+/* { dg-final { scan-rtl-dump-times ".SAT_TRUNC " 2 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-2.c
new file mode 100644
index 0000000..03c1d70
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-2.c
@@ -0,0 +1,21 @@
+/* { 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 "../binop/vec_sat_arith.h"
+
+/*
+** vec_sat_u_trunc_uint8_t_uint32_t_fmt_1:
+** ...
+** vsetvli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*e16,\s*mf2,\s*ta,\s*ma
+** vle32\.v\s+v[0-9]+,\s*0\([atx][0-9]+\)
+** vnclipu\.wi\s+v[0-9]+,\s*v[0-9]+,\s*0
+** vsetvli\s+zero,\s*zero,\s*e8,\s*mf4,\s*ta,\s*ma
+** vnclipu\.wi\s+v[0-9]+,\s*v[0-9]+,\s*0
+** vse8\.v\s+v[0-9]+,\s*0\([atx][0-9]+\)
+** ...
+*/
+DEF_VEC_SAT_U_TRUNC_FMT_1 (uint8_t, uint32_t)
+
+/* { dg-final { scan-rtl-dump-times ".SAT_TRUNC " 2 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-3.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-3.c
new file mode 100644
index 0000000..291dd05
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-3.c
@@ -0,0 +1,23 @@
+/* { 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 "../binop/vec_sat_arith.h"
+
+/*
+** vec_sat_u_trunc_uint8_t_uint64_t_fmt_1:
+** ...
+** vsetvli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*e32,\s*mf2,\s*ta,\s*ma
+** vle64\.v\s+v[0-9]+,\s*0\([atx][0-9]+\)
+** vnclipu\.wi\s+v[0-9]+,\s*v[0-9]+,\s*0
+** vsetvli\s+zero,\s*zero,\s*e16,\s*mf4,\s*ta,\s*ma
+** vnclipu\.wi\s+v[0-9]+,\s*v[0-9]+,\s*0
+** vsetvli\s+zero,\s*zero,\s*e8,\s*mf8,\s*ta,\s*ma
+** vnclipu\.wi\s+v[0-9]+,\s*v[0-9]+,\s*0
+** vse8\.v\s+v[0-9]+,\s*0\([atx][0-9]+\)
+** ...
+*/
+DEF_VEC_SAT_U_TRUNC_FMT_1 (uint8_t, uint64_t)
+
+/* { dg-final { scan-rtl-dump-times ".SAT_TRUNC " 2 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-4.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-4.c
new file mode 100644
index 0000000..a3192bf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-4.c
@@ -0,0 +1,19 @@
+/* { 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 "../binop/vec_sat_arith.h"
+
+/*
+** vec_sat_u_trunc_uint16_t_uint32_t_fmt_1:
+** ...
+** vsetvli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*e16,\s*mf2,\s*ta,\s*ma
+** vle32\.v\s+v[0-9]+,\s*0\([atx][0-9]+\)
+** vnclipu\.wi\s+v[0-9]+,\s*v[0-9]+,\s*0
+** vse16\.v\s+v[0-9]+,\s*0\([atx][0-9]+\)
+** ...
+*/
+DEF_VEC_SAT_U_TRUNC_FMT_1 (uint16_t, uint32_t)
+
+/* { dg-final { scan-rtl-dump-times ".SAT_TRUNC " 2 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-5.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-5.c
new file mode 100644
index 0000000..b852761
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-5.c
@@ -0,0 +1,21 @@
+/* { 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 "../binop/vec_sat_arith.h"
+
+/*
+** vec_sat_u_trunc_uint16_t_uint64_t_fmt_1:
+** ...
+** vsetvli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*e32,\s*mf2,\s*ta,\s*ma
+** vle64\.v\s+v[0-9]+,\s*0\([atx][0-9]+\)
+** vnclipu\.wi\s+v[0-9]+,\s*v[0-9]+,\s*0
+** vsetvli\s+zero,\s*zero,\s*e16,\s*mf4,\s*ta,\s*ma
+** vnclipu\.wi\s+v[0-9]+,\s*v[0-9]+,\s*0
+** vse16\.v\s+v[0-9]+,\s*0\([atx][0-9]+\)
+** ...
+*/
+DEF_VEC_SAT_U_TRUNC_FMT_1 (uint16_t, uint64_t)
+
+/* { dg-final { scan-rtl-dump-times ".SAT_TRUNC " 2 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-6.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-6.c
new file mode 100644
index 0000000..65b5ad3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-6.c
@@ -0,0 +1,19 @@
+/* { 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 "../binop/vec_sat_arith.h"
+
+/*
+** vec_sat_u_trunc_uint32_t_uint64_t_fmt_1:
+** ...
+** vsetvli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*e32,\s*mf2,\s*ta,\s*ma
+** vle64\.v\s+v[0-9]+,\s*0\([atx][0-9]+\)
+** vnclipu\.wi\s+v[0-9]+,\s*v[0-9]+,\s*0
+** vse32\.v\s+v[0-9]+,\s*0\([atx][0-9]+\)
+** ...
+*/
+DEF_VEC_SAT_U_TRUNC_FMT_1 (uint32_t, uint64_t)
+
+/* { dg-final { scan-rtl-dump-times ".SAT_TRUNC " 2 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-run-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-run-1.c
new file mode 100644
index 0000000..cd896e2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-run-1.c
@@ -0,0 +1,16 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99" } */
+
+#include "../binop/vec_sat_arith.h"
+#include "vec_sat_data.h"
+
+#define T1 uint8_t
+#define T2 uint16_t
+
+DEF_VEC_SAT_U_TRUNC_FMT_1_WRAP(T1, T2)
+
+#define T TEST_UNARY_STRUCT_DECL(T1, T2)
+#define DATA TEST_UNARY_DATA_WRAP(T1, T2)
+#define RUN_UNARY(out, in, N) RUN_VEC_SAT_U_TRUNC_FMT_1_WRAP(T1, T2, out, in, N)
+
+#include "vec_sat_unary_vv_run.h"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-run-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-run-2.c
new file mode 100644
index 0000000..96272ca
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-run-2.c
@@ -0,0 +1,16 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99" } */
+
+#include "../binop/vec_sat_arith.h"
+#include "vec_sat_data.h"
+
+#define T1 uint8_t
+#define T2 uint32_t
+
+DEF_VEC_SAT_U_TRUNC_FMT_1_WRAP(T1, T2)
+
+#define T TEST_UNARY_STRUCT_DECL(T1, T2)
+#define DATA TEST_UNARY_DATA_WRAP(T1, T2)
+#define RUN_UNARY(out, in, N) RUN_VEC_SAT_U_TRUNC_FMT_1_WRAP(T1, T2, out, in, N)
+
+#include "vec_sat_unary_vv_run.h"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-run-3.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-run-3.c
new file mode 100644
index 0000000..671bbeb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-run-3.c
@@ -0,0 +1,16 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99" } */
+
+#include "../binop/vec_sat_arith.h"
+#include "vec_sat_data.h"
+
+#define T1 uint8_t
+#define T2 uint64_t
+
+DEF_VEC_SAT_U_TRUNC_FMT_1_WRAP(T1, T2)
+
+#define T TEST_UNARY_STRUCT_DECL(T1, T2)
+#define DATA TEST_UNARY_DATA_WRAP(T1, T2)
+#define RUN_UNARY(out, in, N) RUN_VEC_SAT_U_TRUNC_FMT_1_WRAP(T1, T2, out, in, N)
+
+#include "vec_sat_unary_vv_run.h"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-run-4.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-run-4.c
new file mode 100644
index 0000000..c7df27b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-run-4.c
@@ -0,0 +1,16 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99" } */
+
+#include "../binop/vec_sat_arith.h"
+#include "vec_sat_data.h"
+
+#define T1 uint16_t
+#define T2 uint32_t
+
+DEF_VEC_SAT_U_TRUNC_FMT_1_WRAP(T1, T2)
+
+#define T TEST_UNARY_STRUCT_DECL(T1, T2)
+#define DATA TEST_UNARY_DATA_WRAP(T1, T2)
+#define RUN_UNARY(out, in, N) RUN_VEC_SAT_U_TRUNC_FMT_1_WRAP(T1, T2, out, in, N)
+
+#include "vec_sat_unary_vv_run.h"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-run-5.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-run-5.c
new file mode 100644
index 0000000..c9067a1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-run-5.c
@@ -0,0 +1,16 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99" } */
+
+#include "../binop/vec_sat_arith.h"
+#include "vec_sat_data.h"
+
+#define T1 uint16_t
+#define T2 uint64_t
+
+DEF_VEC_SAT_U_TRUNC_FMT_1_WRAP(T1, T2)
+
+#define T TEST_UNARY_STRUCT_DECL(T1, T2)
+#define DATA TEST_UNARY_DATA_WRAP(T1, T2)
+#define RUN_UNARY(out, in, N) RUN_VEC_SAT_U_TRUNC_FMT_1_WRAP(T1, T2, out, in, N)
+
+#include "vec_sat_unary_vv_run.h"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-run-6.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-run-6.c
new file mode 100644
index 0000000..51d76be
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_u_trunc-run-6.c
@@ -0,0 +1,16 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99" } */
+
+#include "../binop/vec_sat_arith.h"
+#include "vec_sat_data.h"
+
+#define T1 uint32_t
+#define T2 uint64_t
+
+DEF_VEC_SAT_U_TRUNC_FMT_1_WRAP(T1, T2)
+
+#define T TEST_UNARY_STRUCT_DECL(T1, T2)
+#define DATA TEST_UNARY_DATA_WRAP(T1, T2)
+#define RUN_UNARY(out, in, N) RUN_VEC_SAT_U_TRUNC_FMT_1_WRAP(T1, T2, out, in, N)
+
+#include "vec_sat_unary_vv_run.h"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_unary_vv_run.h b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_unary_vv_run.h
new file mode 100644
index 0000000..e731e9f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vec_sat_unary_vv_run.h
@@ -0,0 +1,23 @@
+#ifndef HAVE_DEFINE_VEC_SAT_UNARY_VV_RUN_H
+#define HAVE_DEFINE_VEC_SAT_UNARY_VV_RUN_H
+
+int
+main ()
+{
+ unsigned i, k;
+
+ for (i = 0; i < sizeof (DATA) / sizeof (DATA[0]); i++)
+ {
+ T *data = &DATA[i];
+
+ RUN_UNARY (data->out, data->in, N);
+
+ for (k = 0; k < N; k++)
+ if (data->out[k] != data->expect[k])
+ __builtin_abort ();
+ }
+
+ return 0;
+}
+
+#endif