RISC-V: Fix dead loop for user vsetvli intrinsic avl checking [PR109773]

Message ID 20230509021934.958640-1-juzhe.zhong@rivai.ai
State Accepted
Headers
Series RISC-V: Fix dead loop for user vsetvli intrinsic avl checking [PR109773] |

Checks

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

Commit Message

juzhe.zhong@rivai.ai May 9, 2023, 2:19 a.m. UTC
  From: Juzhe-Zhong <juzhe.zhong@rivai.ai>

This patch is fix dead loop in vsetvl intrinsic avl checking.

vsetvli->get_def () has vsetvli->get_def () has vsetvli.....
Then it will keep looping in the vsetvli avl checking which is a dead loop.

        PR target/109773

gcc/ChangeLog:

        * config/riscv/riscv-vsetvl.cc (avl_source_has_vsetvl_p): New function.
        (source_equal_p): Fix dead loop in vsetvl avl checking.

gcc/testsuite/ChangeLog:

        * gcc.target/riscv/rvv/vsetvl/pr109773-1.c: New test.
        * gcc.target/riscv/rvv/vsetvl/pr109773-2.c: New test.

---
 gcc/config/riscv/riscv-vsetvl.cc              | 25 ++++++++++++++++++
 .../gcc.target/riscv/rvv/vsetvl/pr109773-1.c  | 20 ++++++++++++++
 .../gcc.target/riscv/rvv/vsetvl/pr109773-2.c  | 26 +++++++++++++++++++
 3 files changed, 71 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/vsetvl/pr109773-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/vsetvl/pr109773-2.c
  

Comments

Kito Cheng May 10, 2023, 8:24 a.m. UTC | #1
Thanks, pushed to trunk.

On Tue, May 9, 2023 at 10:20 AM <juzhe.zhong@rivai.ai> wrote:
>
> From: Juzhe-Zhong <juzhe.zhong@rivai.ai>
>
> This patch is fix dead loop in vsetvl intrinsic avl checking.
>
> vsetvli->get_def () has vsetvli->get_def () has vsetvli.....
> Then it will keep looping in the vsetvli avl checking which is a dead loop.
>
>         PR target/109773
>
> gcc/ChangeLog:
>
>         * config/riscv/riscv-vsetvl.cc (avl_source_has_vsetvl_p): New function.
>         (source_equal_p): Fix dead loop in vsetvl avl checking.
>
> gcc/testsuite/ChangeLog:
>
>         * gcc.target/riscv/rvv/vsetvl/pr109773-1.c: New test.
>         * gcc.target/riscv/rvv/vsetvl/pr109773-2.c: New test.
>
> ---
>  gcc/config/riscv/riscv-vsetvl.cc              | 25 ++++++++++++++++++
>  .../gcc.target/riscv/rvv/vsetvl/pr109773-1.c  | 20 ++++++++++++++
>  .../gcc.target/riscv/rvv/vsetvl/pr109773-2.c  | 26 +++++++++++++++++++
>  3 files changed, 71 insertions(+)
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/vsetvl/pr109773-1.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/vsetvl/pr109773-2.c
>
> diff --git a/gcc/config/riscv/riscv-vsetvl.cc b/gcc/config/riscv/riscv-vsetvl.cc
> index 72aa2bfcf6f..2577b2bd9b7 100644
> --- a/gcc/config/riscv/riscv-vsetvl.cc
> +++ b/gcc/config/riscv/riscv-vsetvl.cc
> @@ -1056,6 +1056,24 @@ change_vsetvl_insn (const insn_info *insn, const vector_insn_info &info)
>    change_insn (rinsn, new_pat);
>  }
>
> +static bool
> +avl_source_has_vsetvl_p (set_info *avl_source)
> +{
> +  if (!avl_source)
> +    return false;
> +  if (!avl_source->insn ())
> +    return false;
> +  if (avl_source->insn ()->is_real ())
> +    return vsetvl_insn_p (avl_source->insn ()->rtl ());
> +  hash_set<set_info *> sets = get_all_sets (avl_source, true, false, true);
> +  for (const auto set : sets)
> +    {
> +      if (set->insn ()->is_real () && vsetvl_insn_p (set->insn ()->rtl ()))
> +       return true;
> +    }
> +  return false;
> +}
> +
>  static bool
>  source_equal_p (insn_info *insn1, insn_info *insn2)
>  {
> @@ -1098,6 +1116,13 @@ source_equal_p (insn_info *insn1, insn_info *insn2)
>        vector_insn_info insn1_info, insn2_info;
>        insn1_info.parse_insn (insn1);
>        insn2_info.parse_insn (insn2);
> +
> +      /* To avoid dead loop, we don't optimize a vsetvli def has vsetvli
> +        instructions which will complicate the situation.  */
> +      if (avl_source_has_vsetvl_p (insn1_info.get_avl_source ())
> +         || avl_source_has_vsetvl_p (insn2_info.get_avl_source ()))
> +       return false;
> +
>        if (insn1_info.same_vlmax_p (insn2_info)
>           && insn1_info.compatible_avl_p (insn2_info))
>         return true;
> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/vsetvl/pr109773-1.c b/gcc/testsuite/gcc.target/riscv/rvv/vsetvl/pr109773-1.c
> new file mode 100644
> index 00000000000..8656e473117
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/vsetvl/pr109773-1.c
> @@ -0,0 +1,20 @@
> +/* { dg-do compile } */
> +/* { dg-options "-march=rv32gcv -mabi=ilp32 -fno-tree-vectorize -fno-schedule-insns -fno-schedule-insns2" } */
> +
> +#include "riscv_vector.h"
> +
> +void f (int32_t *a, int32_t *b, int n)
> +{
> +  if (n <= 0)
> +    return;
> +  int i = n;
> +  size_t vl = __riscv_vsetvl_e8mf4 (i);
> +  for (; i >= 0; i--)
> +    {
> +      vint32m1_t v = __riscv_vle32_v_i32m1 (a + i, vl);
> +      __riscv_vse32_v_i32m1 (b + i, v, vl);
> +      vl = __riscv_vsetvl_e8mf4 (vl);
> +    }
> +}
> +
> +/* { dg-final { scan-assembler-times {vsetvli} 3 { target { no-opts "-O0" no-opts "-O1" no-opts "-Os" no-opts "-Oz" no-opts "-g" no-opts "-funroll-loops" } } } } */
> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/vsetvl/pr109773-2.c b/gcc/testsuite/gcc.target/riscv/rvv/vsetvl/pr109773-2.c
> new file mode 100644
> index 00000000000..7bfbaaf3713
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/vsetvl/pr109773-2.c
> @@ -0,0 +1,26 @@
> +/* { dg-do compile } */
> +/* { dg-options "-march=rv32gcv -mabi=ilp32 -fno-tree-vectorize -fno-schedule-insns -fno-schedule-insns2" } */
> +
> +#include "riscv_vector.h"
> +
> +void f (int32_t * a, int32_t * b, int n)
> +{
> +    if (n <= 0)
> +      return;
> +    int i = n;
> +    size_t vl = __riscv_vsetvl_e8mf4 (i);
> +    for (; i >= 0; i--)
> +      {
> +        vint32m1_t v = __riscv_vle32_v_i32m1 (a + i, vl);
> +       v = __riscv_vle32_v_i32m1_tu (v, a + i + 100, vl);
> +        __riscv_vse32_v_i32m1 (b + i, v, vl);
> +
> +        if (i >= vl)
> +          continue;
> +        if (i == 0)
> +          return;
> +        vl = __riscv_vsetvl_e8mf4 (vl);
> +      }
> +}
> +
> +/* { dg-final { scan-assembler {vsetvli} { target { no-opts "-O0" no-opts "-O1" no-opts "-Os" no-opts "-Oz" no-opts "-g" no-opts "-funroll-loops" } } } } */
> --
> 2.36.3
>
  

Patch

diff --git a/gcc/config/riscv/riscv-vsetvl.cc b/gcc/config/riscv/riscv-vsetvl.cc
index 72aa2bfcf6f..2577b2bd9b7 100644
--- a/gcc/config/riscv/riscv-vsetvl.cc
+++ b/gcc/config/riscv/riscv-vsetvl.cc
@@ -1056,6 +1056,24 @@  change_vsetvl_insn (const insn_info *insn, const vector_insn_info &info)
   change_insn (rinsn, new_pat);
 }
 
+static bool
+avl_source_has_vsetvl_p (set_info *avl_source)
+{
+  if (!avl_source)
+    return false;
+  if (!avl_source->insn ())
+    return false;
+  if (avl_source->insn ()->is_real ())
+    return vsetvl_insn_p (avl_source->insn ()->rtl ());
+  hash_set<set_info *> sets = get_all_sets (avl_source, true, false, true);
+  for (const auto set : sets)
+    {
+      if (set->insn ()->is_real () && vsetvl_insn_p (set->insn ()->rtl ()))
+	return true;
+    }
+  return false;
+}
+
 static bool
 source_equal_p (insn_info *insn1, insn_info *insn2)
 {
@@ -1098,6 +1116,13 @@  source_equal_p (insn_info *insn1, insn_info *insn2)
       vector_insn_info insn1_info, insn2_info;
       insn1_info.parse_insn (insn1);
       insn2_info.parse_insn (insn2);
+
+      /* To avoid dead loop, we don't optimize a vsetvli def has vsetvli
+	 instructions which will complicate the situation.  */
+      if (avl_source_has_vsetvl_p (insn1_info.get_avl_source ())
+	  || avl_source_has_vsetvl_p (insn2_info.get_avl_source ()))
+	return false;
+
       if (insn1_info.same_vlmax_p (insn2_info)
 	  && insn1_info.compatible_avl_p (insn2_info))
 	return true;
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/vsetvl/pr109773-1.c b/gcc/testsuite/gcc.target/riscv/rvv/vsetvl/pr109773-1.c
new file mode 100644
index 00000000000..8656e473117
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/vsetvl/pr109773-1.c
@@ -0,0 +1,20 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gcv -mabi=ilp32 -fno-tree-vectorize -fno-schedule-insns -fno-schedule-insns2" } */
+
+#include "riscv_vector.h"
+
+void f (int32_t *a, int32_t *b, int n)
+{
+  if (n <= 0)
+    return;
+  int i = n;
+  size_t vl = __riscv_vsetvl_e8mf4 (i);
+  for (; i >= 0; i--)
+    {
+      vint32m1_t v = __riscv_vle32_v_i32m1 (a + i, vl);
+      __riscv_vse32_v_i32m1 (b + i, v, vl);
+      vl = __riscv_vsetvl_e8mf4 (vl);
+    }
+}
+
+/* { dg-final { scan-assembler-times {vsetvli} 3 { target { no-opts "-O0" no-opts "-O1" no-opts "-Os" no-opts "-Oz" no-opts "-g" no-opts "-funroll-loops" } } } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/vsetvl/pr109773-2.c b/gcc/testsuite/gcc.target/riscv/rvv/vsetvl/pr109773-2.c
new file mode 100644
index 00000000000..7bfbaaf3713
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/vsetvl/pr109773-2.c
@@ -0,0 +1,26 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gcv -mabi=ilp32 -fno-tree-vectorize -fno-schedule-insns -fno-schedule-insns2" } */
+
+#include "riscv_vector.h"
+
+void f (int32_t * a, int32_t * b, int n)
+{
+    if (n <= 0)
+      return;
+    int i = n;
+    size_t vl = __riscv_vsetvl_e8mf4 (i);
+    for (; i >= 0; i--)
+      {
+        vint32m1_t v = __riscv_vle32_v_i32m1 (a + i, vl);
+	v = __riscv_vle32_v_i32m1_tu (v, a + i + 100, vl);
+        __riscv_vse32_v_i32m1 (b + i, v, vl);
+
+        if (i >= vl)
+          continue;
+        if (i == 0)
+          return;
+        vl = __riscv_vsetvl_e8mf4 (vl);
+      }
+}
+
+/* { dg-final { scan-assembler {vsetvli} { target { no-opts "-O0" no-opts "-O1" no-opts "-Os" no-opts "-Oz" no-opts "-g" no-opts "-funroll-loops" } } } } */