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.
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)
{
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;
--- /dev/null
+/* { 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" } } } } */
--- /dev/null
+/* { 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" } } } } */