]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
RISC-V: Fix vl_used_by_non_rvv_insn logic of vsetvl pass
authorgarthlei <garthlei@linux.alibaba.com>
Wed, 11 Sep 2024 09:09:37 +0000 (17:09 +0800)
committerKito Cheng <kito.cheng@sifive.com>
Wed, 9 Apr 2025 14:03:10 +0000 (22:03 +0800)
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.

gcc/config/riscv/riscv-vsetvl.cc
gcc/testsuite/gcc.target/riscv/rvv/vsetvl/vsetvl_bug-3.c [new file with mode: 0644]

index 96cd82756cf8b4cb014925ee0753b59a24a2e18a..49702a5c6838f32781970a2ed296b2f2dfc3fd74 100644 (file)
@@ -1004,6 +1004,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.  */
@@ -1037,7 +1040,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 ();
@@ -1134,22 +1140,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 (file)
index 0000000..3acbc73
--- /dev/null
@@ -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" } }  */