aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJuzhe-Zhong <juzhe.zhong@rivai.ai>2023-12-20 14:50:11 +0800
committerPan Li <pan2.li@intel.com>2023-12-21 07:05:57 +0800
commitd82bb518fa372cc30cc3352e0a124d0bd6deb36f (patch)
treefbb59936c8cc4e23ef21317f5775847af9ef38b2 /gcc
parentd7e9ae4fa94afd5517536b4dfc7d6be0b3e8c2c3 (diff)
downloadgcc-d82bb518fa372cc30cc3352e0a124d0bd6deb36f.zip
gcc-d82bb518fa372cc30cc3352e0a124d0bd6deb36f.tar.gz
gcc-d82bb518fa372cc30cc3352e0a124d0bd6deb36f.tar.bz2
RISC-V: Fix bug of VSETVL fusion
This patch fixes bugs in the fusion of this following case: li a5,-1 vmv.s.x v0,a5 -> demand any non-zero AVL vsetvli a5, ... Incorrect fusion after VSETVL PASS: li a5,-1 vsetvli a5... vmv.s.x v0, a5 --> a5 is modified as incorrect value. We disallow this incorrect fusion above. Full coverage testing of RV64 and RV32 no regression. PR target/113087 gcc/ChangeLog: * config/riscv/riscv-vsetvl.cc: Disallow fusion when VL modification pollutes non AVL use. gcc/testsuite/ChangeLog: * gcc.target/riscv/rvv/autovec/pr113087-1.c: New test.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/riscv/riscv-vsetvl.cc41
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/pr113087-1.c60
2 files changed, 99 insertions, 2 deletions
diff --git a/gcc/config/riscv/riscv-vsetvl.cc b/gcc/config/riscv/riscv-vsetvl.cc
index 6af8d84..eabaef8 100644
--- a/gcc/config/riscv/riscv-vsetvl.cc
+++ b/gcc/config/riscv/riscv-vsetvl.cc
@@ -1128,6 +1128,27 @@ public:
return gen_vsetvl_discard_result (Pmode, avl, sew, vlmul, ta, ma);
}
+ /* Return true that the non-AVL operands of THIS will be modified
+ if we fuse the VL modification from OTHER into THIS. */
+ bool vl_modify_non_avl_op_p (const vsetvl_info &other) const
+ {
+ /* We don't need to worry about any operands from THIS be
+ modified by OTHER vsetvl since we OTHER vsetvl doesn't
+ modify any operand. */
+ if (!other.has_vl ())
+ return false;
+
+ /* THIS VL operand always preempt OTHER VL operand. */
+ if (this->has_vl ())
+ return false;
+
+ /* If THIS has non IMM AVL and THIS is AVL compatible with
+ OTHER, the AVL value of THIS is same as VL value of OTHER. */
+ if (!this->has_imm_avl ())
+ return false;
+ return find_access (this->get_insn ()->uses (), REGNO (other.get_vl ()));
+ }
+
bool operator== (const vsetvl_info &other) const
{
gcc_assert (!uninit_p () && !other.uninit_p ()
@@ -1896,6 +1917,20 @@ public:
gcc_unreachable ();
}
+ bool vl_not_in_conflict_p (const vsetvl_info &prev, const vsetvl_info &next)
+ {
+ /* We don't fuse this following case:
+
+ li a5, -1
+ vmv.s.x v0, a5 -- PREV
+ vsetvli a5, ... -- NEXT
+
+ Don't fuse NEXT into PREV.
+ */
+ return !prev.vl_modify_non_avl_op_p (next)
+ && !next.vl_modify_non_avl_op_p (prev);
+ }
+
bool avl_compatible_p (const vsetvl_info &prev, const vsetvl_info &next)
{
gcc_assert (prev.valid_p () && next.valid_p ());
@@ -1953,7 +1988,8 @@ public:
{
bool compatible_p = sew_lmul_compatible_p (prev, next)
&& policy_compatible_p (prev, next)
- && avl_compatible_p (prev, next);
+ && avl_compatible_p (prev, next)
+ && vl_not_in_conflict_p (prev, next);
return compatible_p;
}
@@ -1961,7 +1997,8 @@ public:
{
bool available_p = sew_lmul_available_p (prev, next)
&& policy_available_p (prev, next)
- && avl_available_p (prev, next);
+ && avl_available_p (prev, next)
+ && vl_not_in_conflict_p (prev, next);
gcc_assert (!available_p || compatible_p (prev, next));
return available_p;
}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr113087-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr113087-1.c
new file mode 100644
index 0000000..7b743ef
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr113087-1.c
@@ -0,0 +1,60 @@
+/* { dg-do run } */
+/* { dg-options "-O3" } */
+/* { dg-require-effective-target riscv_v } */
+
+#include <assert.h>
+int (e) (int g, int h) { return h > 0x10 || g > 0xFFFFFFFF >> h ? g : g << h; }
+struct i
+{
+ int j;
+ int l : 1;
+};
+struct m
+{
+ char k;
+ int n;
+};
+char o;
+char p;
+short s;
+int q;
+struct m r;
+int v;
+int t;
+short z;
+long ac;
+int ad;
+int ae;
+
+static void
+ai (struct i bf)
+{
+ for (; v; v++)
+ r.k = 0;
+ do
+ ac ^= bf.j;
+ while (bf.j < 0);
+ s = 0;
+ if (bf.l)
+ q |= 0x800;
+}
+
+int
+main ()
+{
+ struct i aw = {0xE00, 1};
+ o = 4;
+ s = p;
+ ai (aw);
+ t = 1;
+ ++p;
+ for (; t <= 7; t++)
+ {
+ ad &= 1;
+ (o &= 1 - e (0x40000012, ++ae)) & (z |= 1);
+ }
+ for (; r.n;)
+ ;
+ assert (o == 4);
+ return 0;
+}