RISC-V: Fix bug of PR109535

Message ID 20230419104151.936002-1-juzhe.zhong@rivai.ai
State Accepted
Headers
Series RISC-V: Fix bug of PR109535 |

Checks

Context Check Description
snail/gcc-patch-check success Github commit url

Commit Message

juzhe.zhong@rivai.ai April 19, 2023, 10:41 a.m. UTC
  From: Ju-Zhe Zhong <juzhe.zhong@rivai.ai>

Testcase coming from Kito.

Co-authored-by: kito-cheng <kito.cheng@sifive.com>
Co-authored-by: kito-cheng <kito.cheng@gmail.com>

        PR 109535

gcc/ChangeLog:

        * config/riscv/riscv-vsetvl.cc (count_regno_occurrences): New function.
        (pass_vsetvl::cleanup_insns): Fix bug.

gcc/testsuite/ChangeLog:

        * g++.target/riscv/rvv/base/pr109535.C: New test.
        * gcc.target/riscv/rvv/base/pr109535.c: New test.

Signed-off-by: Ju-Zhe Zhong <juzhe.zhong@rivai.ai>
Co-authored-by: kito-cheng <kito.cheng@sifive.com>
Co-authored-by: kito-cheng <kito.cheng@gmail.com>

---
 gcc/config/riscv/riscv-vsetvl.cc              |  14 +-
 .../g++.target/riscv/rvv/base/pr109535.C      | 144 ++++++++++++++++++
 .../gcc.target/riscv/rvv/base/pr109535.c      |  11 ++
 3 files changed, 168 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.target/riscv/rvv/base/pr109535.C
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/pr109535.c
  

Comments

Kito Cheng April 20, 2023, 1:22 p.m. UTC | #1
Committed, thanks!

On Wed, Apr 19, 2023 at 6:42 PM <juzhe.zhong@rivai.ai> wrote:
>
> From: Ju-Zhe Zhong <juzhe.zhong@rivai.ai>
>
> Testcase coming from Kito.
>
> Co-authored-by: kito-cheng <kito.cheng@sifive.com>
> Co-authored-by: kito-cheng <kito.cheng@gmail.com>
>
>         PR 109535
>
> gcc/ChangeLog:
>
>         * config/riscv/riscv-vsetvl.cc (count_regno_occurrences): New function.
>         (pass_vsetvl::cleanup_insns): Fix bug.
>
> gcc/testsuite/ChangeLog:
>
>         * g++.target/riscv/rvv/base/pr109535.C: New test.
>         * gcc.target/riscv/rvv/base/pr109535.c: New test.
>
> Signed-off-by: Ju-Zhe Zhong <juzhe.zhong@rivai.ai>
> Co-authored-by: kito-cheng <kito.cheng@sifive.com>
> Co-authored-by: kito-cheng <kito.cheng@gmail.com>
>
> ---
>  gcc/config/riscv/riscv-vsetvl.cc              |  14 +-
>  .../g++.target/riscv/rvv/base/pr109535.C      | 144 ++++++++++++++++++
>  .../gcc.target/riscv/rvv/base/pr109535.c      |  11 ++
>  3 files changed, 168 insertions(+), 1 deletion(-)
>  create mode 100644 gcc/testsuite/g++.target/riscv/rvv/base/pr109535.C
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/pr109535.c
>
> diff --git a/gcc/config/riscv/riscv-vsetvl.cc b/gcc/config/riscv/riscv-vsetvl.cc
> index 1b66e3b9eeb..9c356ce5157 100644
> --- a/gcc/config/riscv/riscv-vsetvl.cc
> +++ b/gcc/config/riscv/riscv-vsetvl.cc
> @@ -1592,6 +1592,18 @@ backward_propagate_worthwhile_p (const basic_block cfg_bb,
>    return true;
>  }
>
> +/* Count the number of REGNO in RINSN.  */
> +static int
> +count_regno_occurrences (rtx_insn *rinsn, unsigned int regno)
> +{
> +  int count = 0;
> +  extract_insn (rinsn);
> +  for (int i = 0; i < recog_data.n_operands; i++)
> +    if (refers_to_regno_p (regno, recog_data.operand[i]))
> +      count++;
> +  return count;
> +}
> +
>  avl_info::avl_info (const avl_info &other)
>  {
>    m_value = other.get_value ();
> @@ -3924,7 +3936,7 @@ pass_vsetvl::cleanup_insns (void) const
>           if (!has_vl_op (rinsn) || !REG_P (get_vl (rinsn)))
>             continue;
>           rtx avl = get_vl (rinsn);
> -         if (count_occurrences (PATTERN (rinsn), avl, 0) == 1)
> +         if (count_regno_occurrences (rinsn, REGNO (avl)) == 1)
>             {
>               /* Get the list of uses for the new instruction.  */
>               auto attempt = crtl->ssa->new_change_attempt ();
> diff --git a/gcc/testsuite/g++.target/riscv/rvv/base/pr109535.C b/gcc/testsuite/g++.target/riscv/rvv/base/pr109535.C
> new file mode 100644
> index 00000000000..7013cfcf4ee
> --- /dev/null
> +++ b/gcc/testsuite/g++.target/riscv/rvv/base/pr109535.C
> @@ -0,0 +1,144 @@
> +/* { dg-do compile } */
> +/* { dg-options "-march=rv64gcv -mabi=lp64d -O3" } */
> +
> +typedef long size_t;
> +typedef signed char int8_t;
> +typedef  char uint8_t
> +
> +;
> +template < typename > struct Relations{ using Unsigned = uint8_t; };
> +template < typename T > using MakeUnsigned = typename Relations< T >::Unsigned;
> +#pragma riscv intrinsic "vector"
> +size_t ScaleByPower() {  return 0;}
> +template < typename Lane, size_t , int > struct Simd {
> +using T = Lane;
> +
> +template < typename NewT > using Rebind = Simd< NewT, 1, 0 >;
> +};
> +template < typename T > struct ClampNAndPow2 {
> +using type = Simd< T, 65536, 0 >
> +;
> +};
> +struct CappedTagChecker {
> +using type = ClampNAndPow2< signed char >::type;
> +};
> +template < typename , size_t , int >
> +using CappedTag = CappedTagChecker::type;
> +template < class D > using TFromD = typename D::T;
> +template < class T, class D > using Rebind = typename D::Rebind< T >;
> +template < class D >
> +using RebindToUnsigned = Rebind< MakeUnsigned<  D  >, D >;
> +template < size_t N >
> +size_t
> +Lanes(Simd< uint8_t, N, 0 > ) {
> +size_t kFull = 0;
> +size_t kCap ;
> +size_t actual =
> +        __riscv_vsetvl_e8m1(kCap);
> +return actual;
> +}
> +template < size_t N >
> +size_t
> +Lanes(Simd< int8_t, N, 0 > ) {
> +size_t kFull  ;
> +size_t kCap ;
> +size_t actual =
> +        __riscv_vsetvl_e8m1(kCap);
> +return actual;
> +}
> +template < size_t N >
> +vuint8m1_t
> +Set(Simd< uint8_t, N, 0 > d, uint8_t arg) {
> +size_t __trans_tmp_1 = Lanes(d);
> +return __riscv_vmv_v_x_u8m1(arg, __trans_tmp_1);
> +}
> +template < size_t N >
> +vint8m1_t Set(Simd< int8_t, N, 0 > , int8_t );
> +template < class D > using VFromD = decltype(Set(D(), TFromD< D >()));
> +template < class D >
> +VFromD< D >
> +Zero(D )
> +;
> +
> +template < size_t N >
> +vint8m1_t
> +BitCastFromByte(Simd< int8_t, N, 0 >, vuint8m1_t v) {
> +return __riscv_vreinterpret_v_u8m1_i8m1(v);
> +}
> +template < class D, class FromV >
> +VFromD< D >
> +BitCast(D d, FromV v) {
> +return BitCastFromByte(d, v)
> +
> +;
> +}
> +template < size_t N >
> +void
> +Store(vint8m1_t v, Simd< int8_t, N, 0 > d) {
> +int8_t *p ;
> +__riscv_vse8_v_i8m1(p, v, Lanes(d));
> +}
> +template < class V, class D >
> +void
> +StoreU(V v, D d) {
> +Store(v, d)
> +;
> +}
> +template < class D > using Vec = decltype(Zero(D()));
> +size_t Generate_count;
> +template < class D, class Func>
> +void Generate(D d, Func func) {
> +RebindToUnsigned< D > du
> +;
> +size_t N = Lanes(d);
> +Vec< decltype(du) > vidx ;
> +for (; ; ) {
> +   StoreU(func(d, vidx), d);
> +   vidx = (Set(du, N));
> +}
> +}
> +template < typename T, int , int kMinArg, class Test, int kPow2 >
> +struct ForeachCappedR {
> +static void Do(size_t , size_t ) {
> +   CappedTag< T, kMinArg, kPow2 > d;
> +   Test()(T(), d);
> +}
> +};
> +template < class > struct ForeachCountAndMisalign;
> +struct TestGenerate;
> +template < int kPow2 = 1 > class ForExtendableVectors {
> +public:
> +
> +template < typename T > void operator()(T) {
> +   size_t max_lanes  ;
> +   ForeachCappedR< T, 0, size_t{} ,
> +                   ForeachCountAndMisalign< int >, kPow2 >::Do(1, max_lanes);
> +}
> +};
> +class ForPartialVectors {
> +public:
> +template < typename T > void operator()(T t)  {
> +   ForExtendableVectors()(t);
> +}
> +};
> +void ForSignedTypes(ForPartialVectors func) { func(int8_t()); }
> +template < class > struct ForeachCountAndMisalign {
> +template < typename T, class D >
> +void operator()(T, D d) {
> +   int rng
> +   ;
> +   size_t misalignments[1] ;
> +   for (   size_t ma : misalignments)
> +       for (size_t mb : misalignments)
> +         TestGenerate()(d, 0, ma, mb, rng);
> +}
> +};
> +struct TestGenerate {
> +template < class D >
> +void operator()(D d, size_t , size_t , size_t, int ) {
> +   auto gen2 = [](auto d, auto vidx) {
> +     return BitCast(d, (vidx));
> +   };
> +   Generate(d, gen2);
> +}
> +};
> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/pr109535.c b/gcc/testsuite/gcc.target/riscv/rvv/base/pr109535.c
> new file mode 100644
> index 00000000000..7582fe9c392
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/pr109535.c
> @@ -0,0 +1,11 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=rv32gcv -mabi=ilp32d" } */
> +
> +#include "riscv_vector.h"
> +
> +void foo(void *in1, void *in2, void *in3, void *out, size_t vl) {
> +  vint8m1_t a = __riscv_vle8_v_i8m1(in1, vl);
> +  vint8m1_t b = __riscv_vadd_vx_i8m1 (a, vl, vl);
> +  __riscv_vse8_v_i8m1(out, b, vl);
> +}
> +
> --
> 2.36.3
>
  

Patch

diff --git a/gcc/config/riscv/riscv-vsetvl.cc b/gcc/config/riscv/riscv-vsetvl.cc
index 1b66e3b9eeb..9c356ce5157 100644
--- a/gcc/config/riscv/riscv-vsetvl.cc
+++ b/gcc/config/riscv/riscv-vsetvl.cc
@@ -1592,6 +1592,18 @@  backward_propagate_worthwhile_p (const basic_block cfg_bb,
   return true;
 }
 
+/* Count the number of REGNO in RINSN.  */
+static int
+count_regno_occurrences (rtx_insn *rinsn, unsigned int regno)
+{
+  int count = 0;
+  extract_insn (rinsn);
+  for (int i = 0; i < recog_data.n_operands; i++)
+    if (refers_to_regno_p (regno, recog_data.operand[i]))
+      count++;
+  return count;
+}
+
 avl_info::avl_info (const avl_info &other)
 {
   m_value = other.get_value ();
@@ -3924,7 +3936,7 @@  pass_vsetvl::cleanup_insns (void) const
 	  if (!has_vl_op (rinsn) || !REG_P (get_vl (rinsn)))
 	    continue;
 	  rtx avl = get_vl (rinsn);
-	  if (count_occurrences (PATTERN (rinsn), avl, 0) == 1)
+	  if (count_regno_occurrences (rinsn, REGNO (avl)) == 1)
 	    {
 	      /* Get the list of uses for the new instruction.  */
 	      auto attempt = crtl->ssa->new_change_attempt ();
diff --git a/gcc/testsuite/g++.target/riscv/rvv/base/pr109535.C b/gcc/testsuite/g++.target/riscv/rvv/base/pr109535.C
new file mode 100644
index 00000000000..7013cfcf4ee
--- /dev/null
+++ b/gcc/testsuite/g++.target/riscv/rvv/base/pr109535.C
@@ -0,0 +1,144 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64d -O3" } */
+
+typedef long size_t;
+typedef signed char int8_t;
+typedef  char uint8_t
+
+;
+template < typename > struct Relations{ using Unsigned = uint8_t; };
+template < typename T > using MakeUnsigned = typename Relations< T >::Unsigned;
+#pragma riscv intrinsic "vector"
+size_t ScaleByPower() {  return 0;}
+template < typename Lane, size_t , int > struct Simd {
+using T = Lane;
+
+template < typename NewT > using Rebind = Simd< NewT, 1, 0 >;
+};
+template < typename T > struct ClampNAndPow2 {
+using type = Simd< T, 65536, 0 >
+;
+};
+struct CappedTagChecker {
+using type = ClampNAndPow2< signed char >::type;
+};
+template < typename , size_t , int >
+using CappedTag = CappedTagChecker::type;
+template < class D > using TFromD = typename D::T;
+template < class T, class D > using Rebind = typename D::Rebind< T >;
+template < class D >
+using RebindToUnsigned = Rebind< MakeUnsigned<  D  >, D >;
+template < size_t N >
+size_t
+Lanes(Simd< uint8_t, N, 0 > ) {
+size_t kFull = 0;
+size_t kCap ;
+size_t actual =
+        __riscv_vsetvl_e8m1(kCap);
+return actual;
+}
+template < size_t N >
+size_t
+Lanes(Simd< int8_t, N, 0 > ) {
+size_t kFull  ;
+size_t kCap ;
+size_t actual =
+        __riscv_vsetvl_e8m1(kCap);
+return actual;
+}
+template < size_t N >
+vuint8m1_t
+Set(Simd< uint8_t, N, 0 > d, uint8_t arg) {
+size_t __trans_tmp_1 = Lanes(d);
+return __riscv_vmv_v_x_u8m1(arg, __trans_tmp_1);
+}
+template < size_t N >
+vint8m1_t Set(Simd< int8_t, N, 0 > , int8_t );
+template < class D > using VFromD = decltype(Set(D(), TFromD< D >()));
+template < class D >
+VFromD< D >
+Zero(D )
+;
+
+template < size_t N >
+vint8m1_t
+BitCastFromByte(Simd< int8_t, N, 0 >, vuint8m1_t v) {
+return __riscv_vreinterpret_v_u8m1_i8m1(v);
+}
+template < class D, class FromV >
+VFromD< D >
+BitCast(D d, FromV v) {
+return BitCastFromByte(d, v)
+
+;
+}
+template < size_t N >
+void
+Store(vint8m1_t v, Simd< int8_t, N, 0 > d) {
+int8_t *p ;
+__riscv_vse8_v_i8m1(p, v, Lanes(d));
+}
+template < class V, class D >
+void
+StoreU(V v, D d) {
+Store(v, d)
+;
+}
+template < class D > using Vec = decltype(Zero(D()));
+size_t Generate_count;
+template < class D, class Func>
+void Generate(D d, Func func) {
+RebindToUnsigned< D > du
+;
+size_t N = Lanes(d);
+Vec< decltype(du) > vidx ;
+for (; ; ) {
+   StoreU(func(d, vidx), d);
+   vidx = (Set(du, N));
+}
+}
+template < typename T, int , int kMinArg, class Test, int kPow2 >
+struct ForeachCappedR {
+static void Do(size_t , size_t ) {
+   CappedTag< T, kMinArg, kPow2 > d;
+   Test()(T(), d);
+}
+};
+template < class > struct ForeachCountAndMisalign;
+struct TestGenerate;
+template < int kPow2 = 1 > class ForExtendableVectors {
+public:
+
+template < typename T > void operator()(T) {
+   size_t max_lanes  ;
+   ForeachCappedR< T, 0, size_t{} ,
+                   ForeachCountAndMisalign< int >, kPow2 >::Do(1, max_lanes);
+}
+};
+class ForPartialVectors {
+public:
+template < typename T > void operator()(T t)  {
+   ForExtendableVectors()(t);
+}
+};
+void ForSignedTypes(ForPartialVectors func) { func(int8_t()); }
+template < class > struct ForeachCountAndMisalign {
+template < typename T, class D >
+void operator()(T, D d) {
+   int rng
+   ;
+   size_t misalignments[1] ;
+   for (   size_t ma : misalignments)
+       for (size_t mb : misalignments)
+         TestGenerate()(d, 0, ma, mb, rng);
+}
+};
+struct TestGenerate {
+template < class D >
+void operator()(D d, size_t , size_t , size_t, int ) {
+   auto gen2 = [](auto d, auto vidx) {
+     return BitCast(d, (vidx));
+   };
+   Generate(d, gen2);
+}
+};
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/pr109535.c b/gcc/testsuite/gcc.target/riscv/rvv/base/pr109535.c
new file mode 100644
index 00000000000..7582fe9c392
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/pr109535.c
@@ -0,0 +1,11 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=rv32gcv -mabi=ilp32d" } */
+
+#include "riscv_vector.h"
+
+void foo(void *in1, void *in2, void *in3, void *out, size_t vl) {
+  vint8m1_t a = __riscv_vle8_v_i8m1(in1, vl);
+  vint8m1_t b = __riscv_vadd_vx_i8m1 (a, vl, vl);
+  __riscv_vse8_v_i8m1(out, b, vl);
+}
+