aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgarthlei <garthlei@linux.alibaba.com>2024-09-11 17:09:37 +0800
committerPan Li <pan2.li@intel.com>2024-09-12 09:14:58 +0800
commitc08e493ceee47bbeb466eeef100be7c1dd01a4e5 (patch)
tree552c80ec508143e9a127a203e80d72516dcf296f
parentba393bf8879e5cf1f917bd88246d6b80ac081052 (diff)
downloadgcc-c08e493ceee47bbeb466eeef100be7c1dd01a4e5.zip
gcc-c08e493ceee47bbeb466eeef100be7c1dd01a4e5.tar.gz
gcc-c08e493ceee47bbeb466eeef100be7c1dd01a4e5.tar.bz2
RISC-V: Fix vl_used_by_non_rvv_insn logic of vsetvl pass
This patch fixes a bug in the current vsetvl pass. The current pass uses `m_vl` to determine whether the dest operand has been used by non-RVV instructions. However, `m_vl` may have been modified as a result of an `update_avl` call, and thus would be no longer the dest operand of the original instruction. This can lead to incorrect vsetvl eliminations, as is shown in the testcase. In this patch, we create a `dest_vl` variable for this scenerio. gcc/ChangeLog: * config/riscv/riscv-vsetvl.cc: Use `dest_vl` for dest VL operand gcc/testsuite/ChangeLog: * gcc.target/riscv/rvv/vsetvl/vsetvl_bug-3.c: New test.
-rw-r--r--gcc/config/riscv/riscv-vsetvl.cc16
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/vsetvl/vsetvl_bug-3.c17
2 files changed, 28 insertions, 5 deletions
diff --git a/gcc/config/riscv/riscv-vsetvl.cc b/gcc/config/riscv/riscv-vsetvl.cc
index 017efa8..ce83168 100644
--- a/gcc/config/riscv/riscv-vsetvl.cc
+++ b/gcc/config/riscv/riscv-vsetvl.cc
@@ -1002,6 +1002,9 @@ public:
void parse_insn (insn_info *insn)
{
+ /* The VL dest of the insn */
+ rtx dest_vl = NULL_RTX;
+
m_insn = insn;
m_bb = insn->bb ();
/* Return if it is debug insn for the consistency with optimize == 0. */
@@ -1035,7 +1038,10 @@ public:
if (m_avl)
{
if (vsetvl_insn_p (insn->rtl ()) || has_vlmax_avl ())
- m_vl = ::get_vl (insn->rtl ());
+ {
+ m_vl = ::get_vl (insn->rtl ());
+ dest_vl = m_vl;
+ }
if (has_nonvlmax_reg_avl ())
m_avl_def = find_access (insn->uses (), REGNO (m_avl))->def ();
@@ -1132,22 +1138,22 @@ public:
}
/* Determine if dest operand(vl) has been used by non-RVV instructions. */
- if (has_vl ())
+ if (dest_vl)
{
const hash_set<use_info *> vl_uses
- = get_all_real_uses (get_insn (), REGNO (get_vl ()));
+ = get_all_real_uses (get_insn (), REGNO (dest_vl));
for (use_info *use : vl_uses)
{
gcc_assert (use->insn ()->is_real ());
rtx_insn *rinsn = use->insn ()->rtl ();
if (!has_vl_op (rinsn)
- || count_regno_occurrences (rinsn, REGNO (get_vl ())) != 1)
+ || count_regno_occurrences (rinsn, REGNO (dest_vl)) != 1)
{
m_vl_used_by_non_rvv_insn = true;
break;
}
rtx avl = ::get_avl (rinsn);
- if (!avl || !REG_P (avl) || REGNO (get_vl ()) != REGNO (avl))
+ if (!avl || !REG_P (avl) || REGNO (dest_vl) != REGNO (avl))
{
m_vl_used_by_non_rvv_insn = true;
break;
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/vsetvl/vsetvl_bug-3.c b/gcc/testsuite/gcc.target/riscv/rvv/vsetvl/vsetvl_bug-3.c
new file mode 100644
index 0000000..c155f56
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/vsetvl/vsetvl_bug-3.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gcv -mabi=ilp32d -O2 -fdump-rtl-vsetvl-details" } */
+
+#include <riscv_vector.h>
+
+uint64_t a[2], b[2];
+
+void
+foo ()
+{
+ size_t vl = __riscv_vsetvl_e64m1 (2);
+ vuint64m1_t vx = __riscv_vle64_v_u64m1 (a, vl);
+ vx = __riscv_vslide1down_vx_u64m1 (vx, 0xffffffffull, vl);
+ __riscv_vse64_v_u64m1 (b, vx, vl);
+}
+
+/* { dg-final { scan-rtl-dump-not "Eliminate insn" "vsetvl" } } */