diff mbox series

RISC-V: Split vwadd.wx and vwsub.wx and add helpers.

Message ID 99adaa97-97e5-4ddb-bc56-af0d19088278@gmail.com
State New
Headers show
Series RISC-V: Split vwadd.wx and vwsub.wx and add helpers. | expand

Commit Message

Robin Dapp May 17, 2024, 3:24 p.m. UTC
Hi,

vwadd.wx and vwsub.wx have the same problem vfwadd.wf had.  This patch
splits the insn pattern in the same way vfwadd.wf was split.

It also adds two patterns to recognize extended scalars.  In practice
those do not provide a lot of improvement over what we already have but
in some instances we can get rid of redundant extensions.  If somebody
considers the patterns excessive, I'd be open to not add them.

Regtested on rv64gcv_zvfh_zvbb.

Regards
 Robin

gcc/ChangeLog:

	* config/riscv/vector.md: Split vwadd.wx/vwsub.wx pattern and
	add extended_scalar patterns.

gcc/testsuite/ChangeLog:

	* gcc.target/riscv/rvv/base/pr115068.c: Add vwadd.wx/vwsub.wx
	tests.
	* gcc.target/riscv/rvv/base/pr115068-run.c: Include pr115068.c.
	* gcc.target/riscv/rvv/base/vwaddsub-1.c: New test.
---
 gcc/config/riscv/vector.md                    | 62 ++++++++++++++++---
 .../gcc.target/riscv/rvv/base/pr115068-run.c  | 24 +------
 .../gcc.target/riscv/rvv/base/pr115068.c      | 26 ++++++++
 .../gcc.target/riscv/rvv/base/vwaddsub-1.c    | 47 ++++++++++++++
 4 files changed, 127 insertions(+), 32 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/vwaddsub-1.c

Comments

juzhe.zhong@rivai.ai May 17, 2024, 10:26 p.m. UTC | #1
LGTM.



juzhe.zhong@rivai.ai
 
From: Robin Dapp
Date: 2024-05-17 23:24
To: gcc-patches
CC: palmer; Kito Cheng; juzhe.zhong@rivai.ai; jeffreyalaw; rdapp.gcc
Subject: [PATCH] RISC-V: Split vwadd.wx and vwsub.wx and add helpers.
Hi,
 
vwadd.wx and vwsub.wx have the same problem vfwadd.wf had.  This patch
splits the insn pattern in the same way vfwadd.wf was split.
 
It also adds two patterns to recognize extended scalars.  In practice
those do not provide a lot of improvement over what we already have but
in some instances we can get rid of redundant extensions.  If somebody
considers the patterns excessive, I'd be open to not add them.
 
Regtested on rv64gcv_zvfh_zvbb.
 
Regards
Robin
 
gcc/ChangeLog:
 
* config/riscv/vector.md: Split vwadd.wx/vwsub.wx pattern and
add extended_scalar patterns.
 
gcc/testsuite/ChangeLog:
 
* gcc.target/riscv/rvv/base/pr115068.c: Add vwadd.wx/vwsub.wx
tests.
* gcc.target/riscv/rvv/base/pr115068-run.c: Include pr115068.c.
* gcc.target/riscv/rvv/base/vwaddsub-1.c: New test.
---
gcc/config/riscv/vector.md                    | 62 ++++++++++++++++---
.../gcc.target/riscv/rvv/base/pr115068-run.c  | 24 +------
.../gcc.target/riscv/rvv/base/pr115068.c      | 26 ++++++++
.../gcc.target/riscv/rvv/base/vwaddsub-1.c    | 47 ++++++++++++++
4 files changed, 127 insertions(+), 32 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/vwaddsub-1.c
 
diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md
index 107914afa3a..248461302dd 100644
--- a/gcc/config/riscv/vector.md
+++ b/gcc/config/riscv/vector.md
@@ -3900,27 +3900,71 @@ (define_insn "@pred_single_widen_add<any_extend:su><mode>"
    (set_attr "mode" "<V_DOUBLE_TRUNC>")])
(define_insn "@pred_single_widen_<plus_minus:optab><any_extend:su><mode>_scalar"
-  [(set (match_operand:VWEXTI 0 "register_operand"                   "=vr,   vr")
+  [(set (match_operand:VWEXTI 0 "register_operand"                 "=vd,vd, vr, vr")
(if_then_else:VWEXTI
  (unspec:<VM>
-     [(match_operand:<VM> 1 "vector_mask_operand"           "vmWc1,vmWc1")
-      (match_operand 5 "vector_length_operand"              "   rK,   rK")
-      (match_operand 6 "const_int_operand"                  "    i,    i")
-      (match_operand 7 "const_int_operand"                  "    i,    i")
-      (match_operand 8 "const_int_operand"                  "    i,    i")
+     [(match_operand:<VM> 1 "vector_mask_operand"    " vm,vm,Wc1,Wc1")
+      (match_operand 5 "vector_length_operand"              " rK,rK, rK, rK")
+      (match_operand 6 "const_int_operand"                  "  i, i,  i,  i")
+      (match_operand 7 "const_int_operand"                  "  i, i,  i,  i")
+      (match_operand 8 "const_int_operand"                  "  i, i,  i,  i")
     (reg:SI VL_REGNUM)
     (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
  (plus_minus:VWEXTI
-     (match_operand:VWEXTI 3 "register_operand"             "   vr,   vr")
+     (match_operand:VWEXTI 3 "register_operand"             " vr,vr, vr, vr")
    (any_extend:VWEXTI
      (vec_duplicate:<V_DOUBLE_TRUNC>
- (match_operand:<VSUBEL> 4 "reg_or_0_operand"       "   rJ,   rJ"))))
-   (match_operand:VWEXTI 2 "vector_merge_operand"           "   vu,    0")))]
+ (match_operand:<VSUBEL> 4 "reg_or_0_operand"       " rJ,rJ, rJ, rJ"))))
+   (match_operand:VWEXTI 2 "vector_merge_operand"           " vu, 0, vu,  0")))]
   "TARGET_VECTOR"
   "vw<plus_minus:insn><any_extend:u>.wx\t%0,%3,%z4%p1"
   [(set_attr "type" "vi<widen_binop_insn_type>")
    (set_attr "mode" "<V_DOUBLE_TRUNC>")])
+(define_insn "@pred_single_widen_add<any_extend:su><mode>_extended_scalar"
+  [(set (match_operand:VWEXTI 0 "register_operand"                 "=vd,vd, vr, vr")
+ (if_then_else:VWEXTI
+   (unspec:<VM>
+     [(match_operand:<VM> 1 "vector_mask_operand"    " vm,vm,Wc1,Wc1")
+      (match_operand 5 "vector_length_operand"              " rK,rK, rK, rK")
+      (match_operand 6 "const_int_operand"                  "  i, i,  i,  i")
+      (match_operand 7 "const_int_operand"                  "  i, i,  i,  i")
+      (match_operand 8 "const_int_operand"                  "  i, i,  i,  i")
+      (reg:SI VL_REGNUM)
+      (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
+   (plus:VWEXTI
+     (vec_duplicate:VWEXTI
+       (any_extend:<VEL>
+ (match_operand:<VSUBEL> 4 "reg_or_0_operand"       " rJ,rJ, rJ, rJ")))
+     (match_operand:VWEXTI 3 "register_operand"             " vr,vr, vr, vr"))
+   (match_operand:VWEXTI 2 "vector_merge_operand"           " vu, 0, vu,  0")))]
+  "TARGET_VECTOR"
+  "vwadd<any_extend:u>.wx\t%0,%3,%z4%p1"
+  [(set_attr "type" "viwalu")
+   (set_attr "mode" "<V_DOUBLE_TRUNC>")])
+
+(define_insn "@pred_single_widen_sub<any_extend:su><mode>_extended_scalar"
+  [(set (match_operand:VWEXTI 0 "register_operand"                 "=vd,vd, vr, vr")
+ (if_then_else:VWEXTI
+   (unspec:<VM>
+     [(match_operand:<VM> 1 "vector_mask_operand"    " vm,vm,Wc1,Wc1")
+      (match_operand 5 "vector_length_operand"              " rK,rK, rK, rK")
+      (match_operand 6 "const_int_operand"                  "  i, i,  i,  i")
+      (match_operand 7 "const_int_operand"                  "  i, i,  i,  i")
+      (match_operand 8 "const_int_operand"                  "  i, i,  i,  i")
+      (reg:SI VL_REGNUM)
+      (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
+   (minus:VWEXTI
+     (match_operand:VWEXTI 3 "register_operand"             " vr,vr, vr, vr")
+     (vec_duplicate:VWEXTI
+       (any_extend:<VEL>
+ (match_operand:<VSUBEL> 4 "reg_or_0_operand"       " rJ,rJ, rJ, rJ"))))
+   (match_operand:VWEXTI 2 "vector_merge_operand"           " vu, 0, vu,  0")))]
+  "TARGET_VECTOR"
+  "vwsub<any_extend:u>.wx\t%0,%3,%z4%p1"
+  [(set_attr "type" "viwalu")
+   (set_attr "mode" "<V_DOUBLE_TRUNC>")])
+
(define_insn "@pred_widen_mulsu<mode>"
   [(set (match_operand:VWEXTI 0 "register_operand"                  "=&vr,&vr")
(if_then_else:VWEXTI
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/pr115068-run.c b/gcc/testsuite/gcc.target/riscv/rvv/base/pr115068-run.c
index 95ec8e06021..d552eb568f6 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/base/pr115068-run.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/pr115068-run.c
@@ -3,26 +3,4 @@
/* { dg-add-options riscv_v } */
/* { dg-additional-options "-std=gnu99" } */
-#include <stdint.h>
-#include <riscv_vector.h>
-
-vfloat64m8_t
-test_vfwadd_wf_f64m8_m (vbool8_t vm, vfloat64m8_t vs2, float rs1, size_t vl)
-{
-  return __riscv_vfwadd_wf_f64m8_m (vm, vs2, rs1, vl);
-}
-
-char global_memory[1024];
-void *fake_memory = (void *) global_memory;
-
-int
-main ()
-{
-  asm volatile ("fence" ::: "memory");
-  vfloat64m8_t vfwadd_wf_f64m8_m_vd = test_vfwadd_wf_f64m8_m (
-    __riscv_vreinterpret_v_i8m1_b8 (__riscv_vundefined_i8m1 ()),
-    __riscv_vundefined_f64m8 (), 1.0, __riscv_vsetvlmax_e64m8 ());
-  asm volatile ("" ::"vr"(vfwadd_wf_f64m8_m_vd) : "memory");
-
-  return 0;
-}
+#include "pr115068.c"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/pr115068.c b/gcc/testsuite/gcc.target/riscv/rvv/base/pr115068.c
index 6d680037aa1..8359e81629d 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/base/pr115068.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/pr115068.c
@@ -11,6 +11,18 @@ test_vfwadd_wf_f64m8_m (vbool8_t vm, vfloat64m8_t vs2, float rs1, size_t vl)
   return __riscv_vfwadd_wf_f64m8_m (vm, vs2, rs1, vl);
}
+vint64m8_t
+test_vwadd_wx_i64m8_m (vbool8_t vm, vint64m8_t vs2, int32_t rs1, size_t vl)
+{
+  return __riscv_vwadd_wx_i64m8_m (vm, vs2, rs1, vl);
+}
+
+vint64m8_t
+test_vwsub_wx_i64m8_m (vbool8_t vm, vint64m8_t vs2, int32_t rs1, size_t vl)
+{
+  return __riscv_vwsub_wx_i64m8_m (vm, vs2, rs1, vl);
+}
+
char global_memory[1024];
void *fake_memory = (void *) global_memory;
@@ -23,7 +35,21 @@ main ()
     __riscv_vundefined_f64m8 (), 1.0, __riscv_vsetvlmax_e64m8 ());
   asm volatile ("" ::"vr"(vfwadd_wf_f64m8_m_vd) : "memory");
+  asm volatile ("fence" ::: "memory");
+  vint64m8_t vwadd_wx_i64m8_m_vd = test_vwadd_wx_i64m8_m (
+    __riscv_vreinterpret_v_i8m1_b8 (__riscv_vundefined_i8m1 ()),
+    __riscv_vundefined_i64m8 (), 1.0, __riscv_vsetvlmax_e64m8 ());
+  asm volatile ("" ::"vr"(vwadd_wx_i64m8_m_vd) : "memory");
+
+  asm volatile ("fence" ::: "memory");
+  vint64m8_t vwsub_wx_i64m8_m_vd = test_vwsub_wx_i64m8_m (
+    __riscv_vreinterpret_v_i8m1_b8 (__riscv_vundefined_i8m1 ()),
+    __riscv_vundefined_i64m8 (), 1.0, __riscv_vsetvlmax_e64m8 ());
+  asm volatile ("" ::"vr"(vwsub_wx_i64m8_m_vd) : "memory");
+
   return 0;
}
/* { dg-final { scan-assembler-not "vfwadd.wf\tv0.*v0" } } */
+/* { dg-final { scan-assembler-not "vwadd.wx\tv0.*v0" } } */
+/* { dg-final { scan-assembler-not "vwsub.wx\tv0.*v0" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/vwaddsub-1.c b/gcc/testsuite/gcc.target/riscv/rvv/base/vwaddsub-1.c
new file mode 100644
index 00000000000..1ee45823b48
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/vwaddsub-1.c
@@ -0,0 +1,47 @@
+/* { dg-do compile } */
+/* { dg-add-options riscv_v } */
+/* { dg-additional-options "-std=gnu99 -O3 -fno-schedule-insns -fno-schedule-insns2" } */
+
+#include <stdint.h>
+#include <riscv_vector.h>
+
+extern int8_t bla;
+
+/*
+** vwadd_wx_i64m8_m:
+**    vsetvli\s+zero,[a-x0-9]+,\s*e32,\s*m4,\s*t[au],\s*m[au]
+**    vwadd\.wx\tv8,v8,a0,v0.t
+**    ret
+*/
+vint64m8_t
+vwadd_wx_i64m8_m (vbool8_t vm, vint64m8_t vs2, int64_t rs1, size_t vl)
+{
+  return __riscv_vwadd_wx_i64m8_m (vm, vs2, rs1, vl);
+}
+
+/*
+** vwsub_wx_i64m8_m:
+**    vsetvli\s+zero,[a-x0-9]+,\s*e32,\s*m4,\s*t[au],\s*m[au]
+**    vwsub\.wx\tv8,v8,a0,v0.t
+**    ret
+*/
+vint64m8_t
+vwsub_wx_i64m8_m (vbool8_t vm, vint64m8_t vs2, int64_t rs1, size_t vl)
+{
+  return __riscv_vwsub_wx_i64m8_m (vm, vs2, rs1, vl);
+}
+
+/*
+** vwsub_wx_i32m8_m:
+**    vsetvli\s+zero,[a-x0-9]+,\s*e16,\s*m4,\s*t[au],\s*m[au]
+**    ..
+**    vwadd\.wx\tv8,v8,a5,v0.t
+**    ret
+*/
+vint32m8_t
+vwadd_wx_i32m8_m (vbool4_t vm, vint32m8_t vs2, int16_t rs1, size_t vl)
+{
+  return __riscv_vwadd_wx_i32m8_m (vm, vs2, bla, vl);
+}
+
+/* { dg-final { check-function-bodies "**" "" } } */
juzhe.zhong@rivai.ai May 17, 2024, 10:37 p.m. UTC | #2
I think it should be backport to GCC-14 since it is a bug.



juzhe.zhong@rivai.ai
 
From: Robin Dapp
Date: 2024-05-17 23:24
To: gcc-patches
CC: palmer; Kito Cheng; juzhe.zhong@rivai.ai; jeffreyalaw; rdapp.gcc
Subject: [PATCH] RISC-V: Split vwadd.wx and vwsub.wx and add helpers.
Hi,
 
vwadd.wx and vwsub.wx have the same problem vfwadd.wf had.  This patch
splits the insn pattern in the same way vfwadd.wf was split.
 
It also adds two patterns to recognize extended scalars.  In practice
those do not provide a lot of improvement over what we already have but
in some instances we can get rid of redundant extensions.  If somebody
considers the patterns excessive, I'd be open to not add them.
 
Regtested on rv64gcv_zvfh_zvbb.
 
Regards
Robin
 
gcc/ChangeLog:
 
* config/riscv/vector.md: Split vwadd.wx/vwsub.wx pattern and
add extended_scalar patterns.
 
gcc/testsuite/ChangeLog:
 
* gcc.target/riscv/rvv/base/pr115068.c: Add vwadd.wx/vwsub.wx
tests.
* gcc.target/riscv/rvv/base/pr115068-run.c: Include pr115068.c.
* gcc.target/riscv/rvv/base/vwaddsub-1.c: New test.
---
gcc/config/riscv/vector.md                    | 62 ++++++++++++++++---
.../gcc.target/riscv/rvv/base/pr115068-run.c  | 24 +------
.../gcc.target/riscv/rvv/base/pr115068.c      | 26 ++++++++
.../gcc.target/riscv/rvv/base/vwaddsub-1.c    | 47 ++++++++++++++
4 files changed, 127 insertions(+), 32 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/vwaddsub-1.c
 
diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md
index 107914afa3a..248461302dd 100644
--- a/gcc/config/riscv/vector.md
+++ b/gcc/config/riscv/vector.md
@@ -3900,27 +3900,71 @@ (define_insn "@pred_single_widen_add<any_extend:su><mode>"
    (set_attr "mode" "<V_DOUBLE_TRUNC>")])
(define_insn "@pred_single_widen_<plus_minus:optab><any_extend:su><mode>_scalar"
-  [(set (match_operand:VWEXTI 0 "register_operand"                   "=vr,   vr")
+  [(set (match_operand:VWEXTI 0 "register_operand"                 "=vd,vd, vr, vr")
(if_then_else:VWEXTI
  (unspec:<VM>
-     [(match_operand:<VM> 1 "vector_mask_operand"           "vmWc1,vmWc1")
-      (match_operand 5 "vector_length_operand"              "   rK,   rK")
-      (match_operand 6 "const_int_operand"                  "    i,    i")
-      (match_operand 7 "const_int_operand"                  "    i,    i")
-      (match_operand 8 "const_int_operand"                  "    i,    i")
+     [(match_operand:<VM> 1 "vector_mask_operand"    " vm,vm,Wc1,Wc1")
+      (match_operand 5 "vector_length_operand"              " rK,rK, rK, rK")
+      (match_operand 6 "const_int_operand"                  "  i, i,  i,  i")
+      (match_operand 7 "const_int_operand"                  "  i, i,  i,  i")
+      (match_operand 8 "const_int_operand"                  "  i, i,  i,  i")
     (reg:SI VL_REGNUM)
     (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
  (plus_minus:VWEXTI
-     (match_operand:VWEXTI 3 "register_operand"             "   vr,   vr")
+     (match_operand:VWEXTI 3 "register_operand"             " vr,vr, vr, vr")
    (any_extend:VWEXTI
      (vec_duplicate:<V_DOUBLE_TRUNC>
- (match_operand:<VSUBEL> 4 "reg_or_0_operand"       "   rJ,   rJ"))))
-   (match_operand:VWEXTI 2 "vector_merge_operand"           "   vu,    0")))]
+ (match_operand:<VSUBEL> 4 "reg_or_0_operand"       " rJ,rJ, rJ, rJ"))))
+   (match_operand:VWEXTI 2 "vector_merge_operand"           " vu, 0, vu,  0")))]
   "TARGET_VECTOR"
   "vw<plus_minus:insn><any_extend:u>.wx\t%0,%3,%z4%p1"
   [(set_attr "type" "vi<widen_binop_insn_type>")
    (set_attr "mode" "<V_DOUBLE_TRUNC>")])
+(define_insn "@pred_single_widen_add<any_extend:su><mode>_extended_scalar"
+  [(set (match_operand:VWEXTI 0 "register_operand"                 "=vd,vd, vr, vr")
+ (if_then_else:VWEXTI
+   (unspec:<VM>
+     [(match_operand:<VM> 1 "vector_mask_operand"    " vm,vm,Wc1,Wc1")
+      (match_operand 5 "vector_length_operand"              " rK,rK, rK, rK")
+      (match_operand 6 "const_int_operand"                  "  i, i,  i,  i")
+      (match_operand 7 "const_int_operand"                  "  i, i,  i,  i")
+      (match_operand 8 "const_int_operand"                  "  i, i,  i,  i")
+      (reg:SI VL_REGNUM)
+      (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
+   (plus:VWEXTI
+     (vec_duplicate:VWEXTI
+       (any_extend:<VEL>
+ (match_operand:<VSUBEL> 4 "reg_or_0_operand"       " rJ,rJ, rJ, rJ")))
+     (match_operand:VWEXTI 3 "register_operand"             " vr,vr, vr, vr"))
+   (match_operand:VWEXTI 2 "vector_merge_operand"           " vu, 0, vu,  0")))]
+  "TARGET_VECTOR"
+  "vwadd<any_extend:u>.wx\t%0,%3,%z4%p1"
+  [(set_attr "type" "viwalu")
+   (set_attr "mode" "<V_DOUBLE_TRUNC>")])
+
+(define_insn "@pred_single_widen_sub<any_extend:su><mode>_extended_scalar"
+  [(set (match_operand:VWEXTI 0 "register_operand"                 "=vd,vd, vr, vr")
+ (if_then_else:VWEXTI
+   (unspec:<VM>
+     [(match_operand:<VM> 1 "vector_mask_operand"    " vm,vm,Wc1,Wc1")
+      (match_operand 5 "vector_length_operand"              " rK,rK, rK, rK")
+      (match_operand 6 "const_int_operand"                  "  i, i,  i,  i")
+      (match_operand 7 "const_int_operand"                  "  i, i,  i,  i")
+      (match_operand 8 "const_int_operand"                  "  i, i,  i,  i")
+      (reg:SI VL_REGNUM)
+      (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
+   (minus:VWEXTI
+     (match_operand:VWEXTI 3 "register_operand"             " vr,vr, vr, vr")
+     (vec_duplicate:VWEXTI
+       (any_extend:<VEL>
+ (match_operand:<VSUBEL> 4 "reg_or_0_operand"       " rJ,rJ, rJ, rJ"))))
+   (match_operand:VWEXTI 2 "vector_merge_operand"           " vu, 0, vu,  0")))]
+  "TARGET_VECTOR"
+  "vwsub<any_extend:u>.wx\t%0,%3,%z4%p1"
+  [(set_attr "type" "viwalu")
+   (set_attr "mode" "<V_DOUBLE_TRUNC>")])
+
(define_insn "@pred_widen_mulsu<mode>"
   [(set (match_operand:VWEXTI 0 "register_operand"                  "=&vr,&vr")
(if_then_else:VWEXTI
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/pr115068-run.c b/gcc/testsuite/gcc.target/riscv/rvv/base/pr115068-run.c
index 95ec8e06021..d552eb568f6 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/base/pr115068-run.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/pr115068-run.c
@@ -3,26 +3,4 @@
/* { dg-add-options riscv_v } */
/* { dg-additional-options "-std=gnu99" } */
-#include <stdint.h>
-#include <riscv_vector.h>
-
-vfloat64m8_t
-test_vfwadd_wf_f64m8_m (vbool8_t vm, vfloat64m8_t vs2, float rs1, size_t vl)
-{
-  return __riscv_vfwadd_wf_f64m8_m (vm, vs2, rs1, vl);
-}
-
-char global_memory[1024];
-void *fake_memory = (void *) global_memory;
-
-int
-main ()
-{
-  asm volatile ("fence" ::: "memory");
-  vfloat64m8_t vfwadd_wf_f64m8_m_vd = test_vfwadd_wf_f64m8_m (
-    __riscv_vreinterpret_v_i8m1_b8 (__riscv_vundefined_i8m1 ()),
-    __riscv_vundefined_f64m8 (), 1.0, __riscv_vsetvlmax_e64m8 ());
-  asm volatile ("" ::"vr"(vfwadd_wf_f64m8_m_vd) : "memory");
-
-  return 0;
-}
+#include "pr115068.c"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/pr115068.c b/gcc/testsuite/gcc.target/riscv/rvv/base/pr115068.c
index 6d680037aa1..8359e81629d 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/base/pr115068.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/pr115068.c
@@ -11,6 +11,18 @@ test_vfwadd_wf_f64m8_m (vbool8_t vm, vfloat64m8_t vs2, float rs1, size_t vl)
   return __riscv_vfwadd_wf_f64m8_m (vm, vs2, rs1, vl);
}
+vint64m8_t
+test_vwadd_wx_i64m8_m (vbool8_t vm, vint64m8_t vs2, int32_t rs1, size_t vl)
+{
+  return __riscv_vwadd_wx_i64m8_m (vm, vs2, rs1, vl);
+}
+
+vint64m8_t
+test_vwsub_wx_i64m8_m (vbool8_t vm, vint64m8_t vs2, int32_t rs1, size_t vl)
+{
+  return __riscv_vwsub_wx_i64m8_m (vm, vs2, rs1, vl);
+}
+
char global_memory[1024];
void *fake_memory = (void *) global_memory;
@@ -23,7 +35,21 @@ main ()
     __riscv_vundefined_f64m8 (), 1.0, __riscv_vsetvlmax_e64m8 ());
   asm volatile ("" ::"vr"(vfwadd_wf_f64m8_m_vd) : "memory");
+  asm volatile ("fence" ::: "memory");
+  vint64m8_t vwadd_wx_i64m8_m_vd = test_vwadd_wx_i64m8_m (
+    __riscv_vreinterpret_v_i8m1_b8 (__riscv_vundefined_i8m1 ()),
+    __riscv_vundefined_i64m8 (), 1.0, __riscv_vsetvlmax_e64m8 ());
+  asm volatile ("" ::"vr"(vwadd_wx_i64m8_m_vd) : "memory");
+
+  asm volatile ("fence" ::: "memory");
+  vint64m8_t vwsub_wx_i64m8_m_vd = test_vwsub_wx_i64m8_m (
+    __riscv_vreinterpret_v_i8m1_b8 (__riscv_vundefined_i8m1 ()),
+    __riscv_vundefined_i64m8 (), 1.0, __riscv_vsetvlmax_e64m8 ());
+  asm volatile ("" ::"vr"(vwsub_wx_i64m8_m_vd) : "memory");
+
   return 0;
}
/* { dg-final { scan-assembler-not "vfwadd.wf\tv0.*v0" } } */
+/* { dg-final { scan-assembler-not "vwadd.wx\tv0.*v0" } } */
+/* { dg-final { scan-assembler-not "vwsub.wx\tv0.*v0" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/vwaddsub-1.c b/gcc/testsuite/gcc.target/riscv/rvv/base/vwaddsub-1.c
new file mode 100644
index 00000000000..1ee45823b48
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/vwaddsub-1.c
@@ -0,0 +1,47 @@
+/* { dg-do compile } */
+/* { dg-add-options riscv_v } */
+/* { dg-additional-options "-std=gnu99 -O3 -fno-schedule-insns -fno-schedule-insns2" } */
+
+#include <stdint.h>
+#include <riscv_vector.h>
+
+extern int8_t bla;
+
+/*
+** vwadd_wx_i64m8_m:
+**    vsetvli\s+zero,[a-x0-9]+,\s*e32,\s*m4,\s*t[au],\s*m[au]
+**    vwadd\.wx\tv8,v8,a0,v0.t
+**    ret
+*/
+vint64m8_t
+vwadd_wx_i64m8_m (vbool8_t vm, vint64m8_t vs2, int64_t rs1, size_t vl)
+{
+  return __riscv_vwadd_wx_i64m8_m (vm, vs2, rs1, vl);
+}
+
+/*
+** vwsub_wx_i64m8_m:
+**    vsetvli\s+zero,[a-x0-9]+,\s*e32,\s*m4,\s*t[au],\s*m[au]
+**    vwsub\.wx\tv8,v8,a0,v0.t
+**    ret
+*/
+vint64m8_t
+vwsub_wx_i64m8_m (vbool8_t vm, vint64m8_t vs2, int64_t rs1, size_t vl)
+{
+  return __riscv_vwsub_wx_i64m8_m (vm, vs2, rs1, vl);
+}
+
+/*
+** vwsub_wx_i32m8_m:
+**    vsetvli\s+zero,[a-x0-9]+,\s*e16,\s*m4,\s*t[au],\s*m[au]
+**    ..
+**    vwadd\.wx\tv8,v8,a5,v0.t
+**    ret
+*/
+vint32m8_t
+vwadd_wx_i32m8_m (vbool4_t vm, vint32m8_t vs2, int16_t rs1, size_t vl)
+{
+  return __riscv_vwadd_wx_i32m8_m (vm, vs2, bla, vl);
+}
+
+/* { dg-final { check-function-bodies "**" "" } } */
Palmer Dabbelt May 17, 2024, 10:45 p.m. UTC | #3
On Fri, 17 May 2024 15:37:43 PDT (-0700), juzhe.zhong@rivai.ai wrote:
> I think it should be backport to GCC-14 since it is a bug.

Seems reasonable to me -- I guess in theory those extended scalar 
patterns aren't bug fixes and we should split them out, but I don't 
think it's all that big of a deal.  We'd likely just backport them to 
the performance branch anyway, so it's essentially the same on my end.

> 
> 
> 
> juzhe.zhong@rivai.ai
>  
> From: Robin Dapp
> Date: 2024-05-17 23:24
> To: gcc-patches
> CC: palmer; Kito Cheng; juzhe.zhong@rivai.ai; jeffreyalaw; rdapp.gcc
> Subject: [PATCH] RISC-V: Split vwadd.wx and vwsub.wx and add helpers.
> Hi,
>  
> vwadd.wx and vwsub.wx have the same problem vfwadd.wf had.  This patch
> splits the insn pattern in the same way vfwadd.wf was split.
>  
> It also adds two patterns to recognize extended scalars.  In practice
> those do not provide a lot of improvement over what we already have but
> in some instances we can get rid of redundant extensions.  If somebody
> considers the patterns excessive, I'd be open to not add them.
>  
> Regtested on rv64gcv_zvfh_zvbb.
>  
> Regards
> Robin
>  
> gcc/ChangeLog:
>  
> * config/riscv/vector.md: Split vwadd.wx/vwsub.wx pattern and
> add extended_scalar patterns.
>  
> gcc/testsuite/ChangeLog:
>  
> * gcc.target/riscv/rvv/base/pr115068.c: Add vwadd.wx/vwsub.wx
> tests.
> * gcc.target/riscv/rvv/base/pr115068-run.c: Include pr115068.c.
> * gcc.target/riscv/rvv/base/vwaddsub-1.c: New test.
> ---
> gcc/config/riscv/vector.md                    | 62 ++++++++++++++++---
> .../gcc.target/riscv/rvv/base/pr115068-run.c  | 24 +------
> .../gcc.target/riscv/rvv/base/pr115068.c      | 26 ++++++++
> .../gcc.target/riscv/rvv/base/vwaddsub-1.c    | 47 ++++++++++++++
> 4 files changed, 127 insertions(+), 32 deletions(-)
> create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/vwaddsub-1.c
>  
> diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md
> index 107914afa3a..248461302dd 100644
> --- a/gcc/config/riscv/vector.md
> +++ b/gcc/config/riscv/vector.md
> @@ -3900,27 +3900,71 @@ (define_insn "@pred_single_widen_add<any_extend:su><mode>"
>     (set_attr "mode" "<V_DOUBLE_TRUNC>")])
> (define_insn "@pred_single_widen_<plus_minus:optab><any_extend:su><mode>_scalar"
> -  [(set (match_operand:VWEXTI 0 "register_operand"                   "=vr,   vr")
> +  [(set (match_operand:VWEXTI 0 "register_operand"                 "=vd,vd, vr, vr")
> (if_then_else:VWEXTI
>   (unspec:<VM>
> -     [(match_operand:<VM> 1 "vector_mask_operand"           "vmWc1,vmWc1")
> -      (match_operand 5 "vector_length_operand"              "   rK,   rK")
> -      (match_operand 6 "const_int_operand"                  "    i,    i")
> -      (match_operand 7 "const_int_operand"                  "    i,    i")
> -      (match_operand 8 "const_int_operand"                  "    i,    i")
> +     [(match_operand:<VM> 1 "vector_mask_operand"    " vm,vm,Wc1,Wc1")
> +      (match_operand 5 "vector_length_operand"              " rK,rK, rK, rK")
> +      (match_operand 6 "const_int_operand"                  "  i, i,  i,  i")
> +      (match_operand 7 "const_int_operand"                  "  i, i,  i,  i")
> +      (match_operand 8 "const_int_operand"                  "  i, i,  i,  i")
>      (reg:SI VL_REGNUM)
>      (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
>   (plus_minus:VWEXTI
> -     (match_operand:VWEXTI 3 "register_operand"             "   vr,   vr")
> +     (match_operand:VWEXTI 3 "register_operand"             " vr,vr, vr, vr")
>     (any_extend:VWEXTI
>       (vec_duplicate:<V_DOUBLE_TRUNC>
> - (match_operand:<VSUBEL> 4 "reg_or_0_operand"       "   rJ,   rJ"))))
> -   (match_operand:VWEXTI 2 "vector_merge_operand"           "   vu,    0")))]
> + (match_operand:<VSUBEL> 4 "reg_or_0_operand"       " rJ,rJ, rJ, rJ"))))
> +   (match_operand:VWEXTI 2 "vector_merge_operand"           " vu, 0, vu,  0")))]
>    "TARGET_VECTOR"
>    "vw<plus_minus:insn><any_extend:u>.wx\t%0,%3,%z4%p1"
>    [(set_attr "type" "vi<widen_binop_insn_type>")
>     (set_attr "mode" "<V_DOUBLE_TRUNC>")])
> +(define_insn "@pred_single_widen_add<any_extend:su><mode>_extended_scalar"
> +  [(set (match_operand:VWEXTI 0 "register_operand"                 "=vd,vd, vr, vr")
> + (if_then_else:VWEXTI
> +   (unspec:<VM>
> +     [(match_operand:<VM> 1 "vector_mask_operand"    " vm,vm,Wc1,Wc1")
> +      (match_operand 5 "vector_length_operand"              " rK,rK, rK, rK")
> +      (match_operand 6 "const_int_operand"                  "  i, i,  i,  i")
> +      (match_operand 7 "const_int_operand"                  "  i, i,  i,  i")
> +      (match_operand 8 "const_int_operand"                  "  i, i,  i,  i")
> +      (reg:SI VL_REGNUM)
> +      (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
> +   (plus:VWEXTI
> +     (vec_duplicate:VWEXTI
> +       (any_extend:<VEL>
> + (match_operand:<VSUBEL> 4 "reg_or_0_operand"       " rJ,rJ, rJ, rJ")))
> +     (match_operand:VWEXTI 3 "register_operand"             " vr,vr, vr, vr"))
> +   (match_operand:VWEXTI 2 "vector_merge_operand"           " vu, 0, vu,  0")))]
> +  "TARGET_VECTOR"
> +  "vwadd<any_extend:u>.wx\t%0,%3,%z4%p1"
> +  [(set_attr "type" "viwalu")
> +   (set_attr "mode" "<V_DOUBLE_TRUNC>")])
> +
> +(define_insn "@pred_single_widen_sub<any_extend:su><mode>_extended_scalar"
> +  [(set (match_operand:VWEXTI 0 "register_operand"                 "=vd,vd, vr, vr")
> + (if_then_else:VWEXTI
> +   (unspec:<VM>
> +     [(match_operand:<VM> 1 "vector_mask_operand"    " vm,vm,Wc1,Wc1")
> +      (match_operand 5 "vector_length_operand"              " rK,rK, rK, rK")
> +      (match_operand 6 "const_int_operand"                  "  i, i,  i,  i")
> +      (match_operand 7 "const_int_operand"                  "  i, i,  i,  i")
> +      (match_operand 8 "const_int_operand"                  "  i, i,  i,  i")
> +      (reg:SI VL_REGNUM)
> +      (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
> +   (minus:VWEXTI
> +     (match_operand:VWEXTI 3 "register_operand"             " vr,vr, vr, vr")
> +     (vec_duplicate:VWEXTI
> +       (any_extend:<VEL>
> + (match_operand:<VSUBEL> 4 "reg_or_0_operand"       " rJ,rJ, rJ, rJ"))))
> +   (match_operand:VWEXTI 2 "vector_merge_operand"           " vu, 0, vu,  0")))]
> +  "TARGET_VECTOR"
> +  "vwsub<any_extend:u>.wx\t%0,%3,%z4%p1"
> +  [(set_attr "type" "viwalu")
> +   (set_attr "mode" "<V_DOUBLE_TRUNC>")])
> +
> (define_insn "@pred_widen_mulsu<mode>"
>    [(set (match_operand:VWEXTI 0 "register_operand"                  "=&vr,&vr")
> (if_then_else:VWEXTI
> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/pr115068-run.c b/gcc/testsuite/gcc.target/riscv/rvv/base/pr115068-run.c
> index 95ec8e06021..d552eb568f6 100644
> --- a/gcc/testsuite/gcc.target/riscv/rvv/base/pr115068-run.c
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/pr115068-run.c
> @@ -3,26 +3,4 @@
> /* { dg-add-options riscv_v } */
> /* { dg-additional-options "-std=gnu99" } */
> -#include <stdint.h>
> -#include <riscv_vector.h>
> -
> -vfloat64m8_t
> -test_vfwadd_wf_f64m8_m (vbool8_t vm, vfloat64m8_t vs2, float rs1, size_t vl)
> -{
> -  return __riscv_vfwadd_wf_f64m8_m (vm, vs2, rs1, vl);
> -}
> -
> -char global_memory[1024];
> -void *fake_memory = (void *) global_memory;
> -
> -int
> -main ()
> -{
> -  asm volatile ("fence" ::: "memory");
> -  vfloat64m8_t vfwadd_wf_f64m8_m_vd = test_vfwadd_wf_f64m8_m (
> -    __riscv_vreinterpret_v_i8m1_b8 (__riscv_vundefined_i8m1 ()),
> -    __riscv_vundefined_f64m8 (), 1.0, __riscv_vsetvlmax_e64m8 ());
> -  asm volatile ("" ::"vr"(vfwadd_wf_f64m8_m_vd) : "memory");
> -
> -  return 0;
> -}
> +#include "pr115068.c"
> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/pr115068.c b/gcc/testsuite/gcc.target/riscv/rvv/base/pr115068.c
> index 6d680037aa1..8359e81629d 100644
> --- a/gcc/testsuite/gcc.target/riscv/rvv/base/pr115068.c
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/pr115068.c
> @@ -11,6 +11,18 @@ test_vfwadd_wf_f64m8_m (vbool8_t vm, vfloat64m8_t vs2, float rs1, size_t vl)
>    return __riscv_vfwadd_wf_f64m8_m (vm, vs2, rs1, vl);
> }
> +vint64m8_t
> +test_vwadd_wx_i64m8_m (vbool8_t vm, vint64m8_t vs2, int32_t rs1, size_t vl)
> +{
> +  return __riscv_vwadd_wx_i64m8_m (vm, vs2, rs1, vl);
> +}
> +
> +vint64m8_t
> +test_vwsub_wx_i64m8_m (vbool8_t vm, vint64m8_t vs2, int32_t rs1, size_t vl)
> +{
> +  return __riscv_vwsub_wx_i64m8_m (vm, vs2, rs1, vl);
> +}
> +
> char global_memory[1024];
> void *fake_memory = (void *) global_memory;
> @@ -23,7 +35,21 @@ main ()
>      __riscv_vundefined_f64m8 (), 1.0, __riscv_vsetvlmax_e64m8 ());
>    asm volatile ("" ::"vr"(vfwadd_wf_f64m8_m_vd) : "memory");
> +  asm volatile ("fence" ::: "memory");
> +  vint64m8_t vwadd_wx_i64m8_m_vd = test_vwadd_wx_i64m8_m (
> +    __riscv_vreinterpret_v_i8m1_b8 (__riscv_vundefined_i8m1 ()),
> +    __riscv_vundefined_i64m8 (), 1.0, __riscv_vsetvlmax_e64m8 ());
> +  asm volatile ("" ::"vr"(vwadd_wx_i64m8_m_vd) : "memory");
> +
> +  asm volatile ("fence" ::: "memory");
> +  vint64m8_t vwsub_wx_i64m8_m_vd = test_vwsub_wx_i64m8_m (
> +    __riscv_vreinterpret_v_i8m1_b8 (__riscv_vundefined_i8m1 ()),
> +    __riscv_vundefined_i64m8 (), 1.0, __riscv_vsetvlmax_e64m8 ());
> +  asm volatile ("" ::"vr"(vwsub_wx_i64m8_m_vd) : "memory");
> +
>    return 0;
> }
> /* { dg-final { scan-assembler-not "vfwadd.wf\tv0.*v0" } } */
> +/* { dg-final { scan-assembler-not "vwadd.wx\tv0.*v0" } } */
> +/* { dg-final { scan-assembler-not "vwsub.wx\tv0.*v0" } } */
> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/vwaddsub-1.c b/gcc/testsuite/gcc.target/riscv/rvv/base/vwaddsub-1.c
> new file mode 100644
> index 00000000000..1ee45823b48
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/vwaddsub-1.c
> @@ -0,0 +1,47 @@
> +/* { dg-do compile } */
> +/* { dg-add-options riscv_v } */
> +/* { dg-additional-options "-std=gnu99 -O3 -fno-schedule-insns -fno-schedule-insns2" } */
> +
> +#include <stdint.h>
> +#include <riscv_vector.h>
> +
> +extern int8_t bla;
> +
> +/*
> +** vwadd_wx_i64m8_m:
> +**    vsetvli\s+zero,[a-x0-9]+,\s*e32,\s*m4,\s*t[au],\s*m[au]
> +**    vwadd\.wx\tv8,v8,a0,v0.t
> +**    ret
> +*/
> +vint64m8_t
> +vwadd_wx_i64m8_m (vbool8_t vm, vint64m8_t vs2, int64_t rs1, size_t vl)
> +{
> +  return __riscv_vwadd_wx_i64m8_m (vm, vs2, rs1, vl);
> +}
> +
> +/*
> +** vwsub_wx_i64m8_m:
> +**    vsetvli\s+zero,[a-x0-9]+,\s*e32,\s*m4,\s*t[au],\s*m[au]
> +**    vwsub\.wx\tv8,v8,a0,v0.t
> +**    ret
> +*/
> +vint64m8_t
> +vwsub_wx_i64m8_m (vbool8_t vm, vint64m8_t vs2, int64_t rs1, size_t vl)
> +{
> +  return __riscv_vwsub_wx_i64m8_m (vm, vs2, rs1, vl);
> +}
> +
> +/*
> +** vwsub_wx_i32m8_m:
> +**    vsetvli\s+zero,[a-x0-9]+,\s*e16,\s*m4,\s*t[au],\s*m[au]
> +**    ..
> +**    vwadd\.wx\tv8,v8,a5,v0.t
> +**    ret
> +*/
> +vint32m8_t
> +vwadd_wx_i32m8_m (vbool4_t vm, vint32m8_t vs2, int16_t rs1, size_t vl)
> +{
> +  return __riscv_vwadd_wx_i32m8_m (vm, vs2, bla, vl);
> +}
> +
> +/* { dg-final { check-function-bodies "**" "" } } */
> -- 
> 2.45.0
>
diff mbox series

Patch

diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md
index 107914afa3a..248461302dd 100644
--- a/gcc/config/riscv/vector.md
+++ b/gcc/config/riscv/vector.md
@@ -3900,27 +3900,71 @@  (define_insn "@pred_single_widen_add<any_extend:su><mode>"
    (set_attr "mode" "<V_DOUBLE_TRUNC>")])
 
 (define_insn "@pred_single_widen_<plus_minus:optab><any_extend:su><mode>_scalar"
-  [(set (match_operand:VWEXTI 0 "register_operand"                   "=vr,   vr")
+  [(set (match_operand:VWEXTI 0 "register_operand"                 "=vd,vd, vr, vr")
 	(if_then_else:VWEXTI
 	  (unspec:<VM>
-	    [(match_operand:<VM> 1 "vector_mask_operand"           "vmWc1,vmWc1")
-	     (match_operand 5 "vector_length_operand"              "   rK,   rK")
-	     (match_operand 6 "const_int_operand"                  "    i,    i")
-	     (match_operand 7 "const_int_operand"                  "    i,    i")
-	     (match_operand 8 "const_int_operand"                  "    i,    i")
+	    [(match_operand:<VM> 1 "vector_mask_operand"	   " vm,vm,Wc1,Wc1")
+	     (match_operand 5 "vector_length_operand"              " rK,rK, rK, rK")
+	     (match_operand 6 "const_int_operand"                  "  i, i,  i,  i")
+	     (match_operand 7 "const_int_operand"                  "  i, i,  i,  i")
+	     (match_operand 8 "const_int_operand"                  "  i, i,  i,  i")
 	     (reg:SI VL_REGNUM)
 	     (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
 	  (plus_minus:VWEXTI
-	    (match_operand:VWEXTI 3 "register_operand"             "   vr,   vr")
+	    (match_operand:VWEXTI 3 "register_operand"             " vr,vr, vr, vr")
 	    (any_extend:VWEXTI
 	      (vec_duplicate:<V_DOUBLE_TRUNC>
-		(match_operand:<VSUBEL> 4 "reg_or_0_operand"       "   rJ,   rJ"))))
-	  (match_operand:VWEXTI 2 "vector_merge_operand"           "   vu,    0")))]
+		(match_operand:<VSUBEL> 4 "reg_or_0_operand"       " rJ,rJ, rJ, rJ"))))
+	  (match_operand:VWEXTI 2 "vector_merge_operand"           " vu, 0, vu,  0")))]
   "TARGET_VECTOR"
   "vw<plus_minus:insn><any_extend:u>.wx\t%0,%3,%z4%p1"
   [(set_attr "type" "vi<widen_binop_insn_type>")
    (set_attr "mode" "<V_DOUBLE_TRUNC>")])
 
+(define_insn "@pred_single_widen_add<any_extend:su><mode>_extended_scalar"
+  [(set (match_operand:VWEXTI 0 "register_operand"                 "=vd,vd, vr, vr")
+	(if_then_else:VWEXTI
+	  (unspec:<VM>
+	    [(match_operand:<VM> 1 "vector_mask_operand"	   " vm,vm,Wc1,Wc1")
+	     (match_operand 5 "vector_length_operand"              " rK,rK, rK, rK")
+	     (match_operand 6 "const_int_operand"                  "  i, i,  i,  i")
+	     (match_operand 7 "const_int_operand"                  "  i, i,  i,  i")
+	     (match_operand 8 "const_int_operand"                  "  i, i,  i,  i")
+	     (reg:SI VL_REGNUM)
+	     (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
+	  (plus:VWEXTI
+	    (vec_duplicate:VWEXTI
+	      (any_extend:<VEL>
+		(match_operand:<VSUBEL> 4 "reg_or_0_operand"       " rJ,rJ, rJ, rJ")))
+	    (match_operand:VWEXTI 3 "register_operand"             " vr,vr, vr, vr"))
+	  (match_operand:VWEXTI 2 "vector_merge_operand"           " vu, 0, vu,  0")))]
+  "TARGET_VECTOR"
+  "vwadd<any_extend:u>.wx\t%0,%3,%z4%p1"
+  [(set_attr "type" "viwalu")
+   (set_attr "mode" "<V_DOUBLE_TRUNC>")])
+
+(define_insn "@pred_single_widen_sub<any_extend:su><mode>_extended_scalar"
+  [(set (match_operand:VWEXTI 0 "register_operand"                 "=vd,vd, vr, vr")
+	(if_then_else:VWEXTI
+	  (unspec:<VM>
+	    [(match_operand:<VM> 1 "vector_mask_operand"	   " vm,vm,Wc1,Wc1")
+	     (match_operand 5 "vector_length_operand"              " rK,rK, rK, rK")
+	     (match_operand 6 "const_int_operand"                  "  i, i,  i,  i")
+	     (match_operand 7 "const_int_operand"                  "  i, i,  i,  i")
+	     (match_operand 8 "const_int_operand"                  "  i, i,  i,  i")
+	     (reg:SI VL_REGNUM)
+	     (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
+	  (minus:VWEXTI
+	    (match_operand:VWEXTI 3 "register_operand"             " vr,vr, vr, vr")
+	    (vec_duplicate:VWEXTI
+	      (any_extend:<VEL>
+		(match_operand:<VSUBEL> 4 "reg_or_0_operand"       " rJ,rJ, rJ, rJ"))))
+	  (match_operand:VWEXTI 2 "vector_merge_operand"           " vu, 0, vu,  0")))]
+  "TARGET_VECTOR"
+  "vwsub<any_extend:u>.wx\t%0,%3,%z4%p1"
+  [(set_attr "type" "viwalu")
+   (set_attr "mode" "<V_DOUBLE_TRUNC>")])
+
 (define_insn "@pred_widen_mulsu<mode>"
   [(set (match_operand:VWEXTI 0 "register_operand"                  "=&vr,&vr")
 	(if_then_else:VWEXTI
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/pr115068-run.c b/gcc/testsuite/gcc.target/riscv/rvv/base/pr115068-run.c
index 95ec8e06021..d552eb568f6 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/base/pr115068-run.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/pr115068-run.c
@@ -3,26 +3,4 @@ 
 /* { dg-add-options riscv_v } */
 /* { dg-additional-options "-std=gnu99" } */
 
-#include <stdint.h>
-#include <riscv_vector.h>
-
-vfloat64m8_t
-test_vfwadd_wf_f64m8_m (vbool8_t vm, vfloat64m8_t vs2, float rs1, size_t vl)
-{
-  return __riscv_vfwadd_wf_f64m8_m (vm, vs2, rs1, vl);
-}
-
-char global_memory[1024];
-void *fake_memory = (void *) global_memory;
-
-int
-main ()
-{
-  asm volatile ("fence" ::: "memory");
-  vfloat64m8_t vfwadd_wf_f64m8_m_vd = test_vfwadd_wf_f64m8_m (
-    __riscv_vreinterpret_v_i8m1_b8 (__riscv_vundefined_i8m1 ()),
-    __riscv_vundefined_f64m8 (), 1.0, __riscv_vsetvlmax_e64m8 ());
-  asm volatile ("" ::"vr"(vfwadd_wf_f64m8_m_vd) : "memory");
-
-  return 0;
-}
+#include "pr115068.c"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/pr115068.c b/gcc/testsuite/gcc.target/riscv/rvv/base/pr115068.c
index 6d680037aa1..8359e81629d 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/base/pr115068.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/pr115068.c
@@ -11,6 +11,18 @@  test_vfwadd_wf_f64m8_m (vbool8_t vm, vfloat64m8_t vs2, float rs1, size_t vl)
   return __riscv_vfwadd_wf_f64m8_m (vm, vs2, rs1, vl);
 }
 
+vint64m8_t
+test_vwadd_wx_i64m8_m (vbool8_t vm, vint64m8_t vs2, int32_t rs1, size_t vl)
+{
+  return __riscv_vwadd_wx_i64m8_m (vm, vs2, rs1, vl);
+}
+
+vint64m8_t
+test_vwsub_wx_i64m8_m (vbool8_t vm, vint64m8_t vs2, int32_t rs1, size_t vl)
+{
+  return __riscv_vwsub_wx_i64m8_m (vm, vs2, rs1, vl);
+}
+
 char global_memory[1024];
 void *fake_memory = (void *) global_memory;
 
@@ -23,7 +35,21 @@  main ()
     __riscv_vundefined_f64m8 (), 1.0, __riscv_vsetvlmax_e64m8 ());
   asm volatile ("" ::"vr"(vfwadd_wf_f64m8_m_vd) : "memory");
 
+  asm volatile ("fence" ::: "memory");
+  vint64m8_t vwadd_wx_i64m8_m_vd = test_vwadd_wx_i64m8_m (
+    __riscv_vreinterpret_v_i8m1_b8 (__riscv_vundefined_i8m1 ()),
+    __riscv_vundefined_i64m8 (), 1.0, __riscv_vsetvlmax_e64m8 ());
+  asm volatile ("" ::"vr"(vwadd_wx_i64m8_m_vd) : "memory");
+
+  asm volatile ("fence" ::: "memory");
+  vint64m8_t vwsub_wx_i64m8_m_vd = test_vwsub_wx_i64m8_m (
+    __riscv_vreinterpret_v_i8m1_b8 (__riscv_vundefined_i8m1 ()),
+    __riscv_vundefined_i64m8 (), 1.0, __riscv_vsetvlmax_e64m8 ());
+  asm volatile ("" ::"vr"(vwsub_wx_i64m8_m_vd) : "memory");
+
   return 0;
 }
 
 /* { dg-final { scan-assembler-not "vfwadd.wf\tv0.*v0" } } */
+/* { dg-final { scan-assembler-not "vwadd.wx\tv0.*v0" } } */
+/* { dg-final { scan-assembler-not "vwsub.wx\tv0.*v0" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/vwaddsub-1.c b/gcc/testsuite/gcc.target/riscv/rvv/base/vwaddsub-1.c
new file mode 100644
index 00000000000..1ee45823b48
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/vwaddsub-1.c
@@ -0,0 +1,47 @@ 
+/* { dg-do compile } */
+/* { dg-add-options riscv_v } */
+/* { dg-additional-options "-std=gnu99 -O3 -fno-schedule-insns -fno-schedule-insns2" } */
+
+#include <stdint.h>
+#include <riscv_vector.h>
+
+extern int8_t bla;
+
+/*
+** vwadd_wx_i64m8_m:
+**    vsetvli\s+zero,[a-x0-9]+,\s*e32,\s*m4,\s*t[au],\s*m[au]
+**    vwadd\.wx\tv8,v8,a0,v0.t
+**    ret
+*/
+vint64m8_t
+vwadd_wx_i64m8_m (vbool8_t vm, vint64m8_t vs2, int64_t rs1, size_t vl)
+{
+  return __riscv_vwadd_wx_i64m8_m (vm, vs2, rs1, vl);
+}
+
+/*
+** vwsub_wx_i64m8_m:
+**    vsetvli\s+zero,[a-x0-9]+,\s*e32,\s*m4,\s*t[au],\s*m[au]
+**    vwsub\.wx\tv8,v8,a0,v0.t
+**    ret
+*/
+vint64m8_t
+vwsub_wx_i64m8_m (vbool8_t vm, vint64m8_t vs2, int64_t rs1, size_t vl)
+{
+  return __riscv_vwsub_wx_i64m8_m (vm, vs2, rs1, vl);
+}
+
+/*
+** vwsub_wx_i32m8_m:
+**    vsetvli\s+zero,[a-x0-9]+,\s*e16,\s*m4,\s*t[au],\s*m[au]
+**    ..
+**    vwadd\.wx\tv8,v8,a5,v0.t
+**    ret
+*/
+vint32m8_t
+vwadd_wx_i32m8_m (vbool4_t vm, vint32m8_t vs2, int16_t rs1, size_t vl)
+{
+  return __riscv_vwadd_wx_i32m8_m (vm, vs2, bla, vl);
+}
+
+/* { dg-final { check-function-bodies "**" "" } } */