RISC-V: Do not delete fused vsetvl if it has uses [PR119115].
In PR119115 we end up with an orphaned vsetvli zero,t1,e16,m1,ta,ma. t1 originally came from another vsetvl that was fused from vsetvli a4,a3,e8,mf2,ta,ma vsetvli t1,a3,e8,mf2,ta,ma (1) to vsetvli zero,a3,e16,m1,ta,ma. This patch checks if t1, the VL operand of (1), has AVL uses and does not delete the vsetvl if so. While doing so, it also wraps the search for VL uses into two new functions reg_used and reg_single_use_in_avl. PR target/119115 gcc/ChangeLog: * config/riscv/riscv-vsetvl.cc (reg_used): New function. (reg_single_use_in_avl): Ditto. (pre_vsetvl::fuse_local_vsetvl_info): Use reg_single_use_in_avl when checking if vsetvl can be deleted. gcc/testsuite/ChangeLog: * gcc.target/riscv/rvv/base/pr119115.c: New test.
This commit is contained in:
parent
f043ef2b6a
commit
77ef91d715
2 changed files with 131 additions and 23 deletions
|
@ -780,6 +780,36 @@ enum class avl_demand_type : unsigned
|
|||
ignore_avl = demand_flags::DEMAND_EMPTY_P,
|
||||
};
|
||||
|
||||
/* Go through all uses of INSN looking for a single use of register REG.
|
||||
Return true if we find
|
||||
- Uses in a non-RVV insn
|
||||
- More than one use in an RVV insn
|
||||
- A single use in the VL operand of an RVV insn
|
||||
and false otherwise.
|
||||
A single use in the AVL operand does not count as use as we take care of
|
||||
those separately in the pass. */
|
||||
|
||||
static bool
|
||||
reg_used (insn_info *insn, rtx reg)
|
||||
{
|
||||
unsigned int regno = REGNO (reg);
|
||||
const hash_set<use_info *> vl_uses = get_all_real_uses (insn, regno);
|
||||
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) != 1)
|
||||
return true;
|
||||
|
||||
rtx avl = ::get_avl (rinsn);
|
||||
if (!avl || !REG_P (avl) || regno != REGNO (avl))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
class vsetvl_info
|
||||
{
|
||||
private:
|
||||
|
@ -1142,27 +1172,7 @@ public:
|
|||
|
||||
/* Determine if dest operand(vl) has been used by non-RVV instructions. */
|
||||
if (dest_vl)
|
||||
{
|
||||
const hash_set<use_info *> vl_uses
|
||||
= 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 (dest_vl)) != 1)
|
||||
{
|
||||
m_vl_used_by_non_rvv_insn = true;
|
||||
break;
|
||||
}
|
||||
rtx avl = ::get_avl (rinsn);
|
||||
if (!avl || !REG_P (avl) || REGNO (dest_vl) != REGNO (avl))
|
||||
{
|
||||
m_vl_used_by_non_rvv_insn = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
m_vl_used_by_non_rvv_insn = reg_used (get_insn (), dest_vl);
|
||||
|
||||
/* Collect the read vl insn for the fault-only-first rvv loads. */
|
||||
if (fault_first_load_p (insn->rtl ()))
|
||||
|
@ -1369,6 +1379,35 @@ public:
|
|||
void set_empty_info () { global_info.set_empty (); }
|
||||
};
|
||||
|
||||
/* Same as REG_USED () but looks for a single use in an RVV insn's AVL
|
||||
operand. */
|
||||
static bool
|
||||
reg_single_use_in_avl (insn_info *insn, rtx reg)
|
||||
{
|
||||
if (!reg)
|
||||
return false;
|
||||
unsigned int regno = REGNO (reg);
|
||||
const hash_set<use_info *> vl_uses = get_all_real_uses (insn, regno);
|
||||
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) != 1)
|
||||
return false;
|
||||
|
||||
vsetvl_info info = vsetvl_info (use->insn ());
|
||||
|
||||
if (!info.has_nonvlmax_reg_avl ())
|
||||
return false;
|
||||
|
||||
rtx avl = info.get_avl ();
|
||||
if (avl && REG_P (avl) && regno == REGNO (avl))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Demand system is the RVV-based VSETVL info analysis tools wrapper.
|
||||
It defines compatible rules for SEW/LMUL, POLICY and AVL.
|
||||
Also, it provides 3 interfaces available_p, compatible_p and
|
||||
|
@ -2797,8 +2836,18 @@ pre_vsetvl::fuse_local_vsetvl_info ()
|
|||
64 into 32. */
|
||||
prev_info.set_max_sew (
|
||||
MIN (prev_info.get_max_sew (), curr_info.get_max_sew ()));
|
||||
if (!curr_info.vl_used_by_non_rvv_insn_p ()
|
||||
&& vsetvl_insn_p (curr_info.get_insn ()->rtl ()))
|
||||
|
||||
/* If we fuse and the current, to be deleted vsetvl has uses
|
||||
of its VL as AVL operand in other vsetvls those will be
|
||||
orphaned. Therefore only delete if that's not the case.
|
||||
*/
|
||||
rtx cur_dest = curr_info.has_vl ()
|
||||
? curr_info.get_vl ()
|
||||
: NULL_RTX;
|
||||
|
||||
if (vsetvl_insn_p (curr_info.get_insn ()->rtl ())
|
||||
&& !reg_single_use_in_avl (curr_info.get_insn (),
|
||||
cur_dest))
|
||||
m_delete_list.safe_push (curr_info);
|
||||
|
||||
if (curr_info.get_read_vl_insn ())
|
||||
|
|
59
gcc/testsuite/gcc.target/riscv/rvv/base/pr119115.c
Normal file
59
gcc/testsuite/gcc.target/riscv/rvv/base/pr119115.c
Normal file
|
@ -0,0 +1,59 @@
|
|||
/* { dg-do run } */
|
||||
/* { dg-require-effective-target rv64 } */
|
||||
/* { dg-require-effective-target rvv_zvl256b_ok } */
|
||||
/* { dg-additional-options "-march=rv64gcv_zvl256b -mabi=lp64d -O3 -fsigned-char -fwrapv -mrvv-vector-bits=zvl" } */
|
||||
|
||||
short a[4][14][14];
|
||||
void
|
||||
b (short d, short e, _Bool f, short g, int h, int i, char j, int k, int l,
|
||||
short m[][14], char n[], unsigned short o[][14][14], short p[])
|
||||
{
|
||||
for (unsigned q = 0; q < (char) i; q++)
|
||||
for (unsigned char r = 0; r < (char) (-1748723647U * m[q][q]) - 20; r++)
|
||||
a[q][q][r] = p[q] || o[q][q][r];
|
||||
}
|
||||
|
||||
__attribute__ ((noipa))
|
||||
void
|
||||
check (long long val)
|
||||
{
|
||||
if (val != 0)
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
long long seed;
|
||||
short d;
|
||||
short e;
|
||||
_Bool f;
|
||||
short g;
|
||||
int h;
|
||||
int i = 15963650;
|
||||
char j;
|
||||
int k;
|
||||
int l;
|
||||
short m[4][14];
|
||||
char n[4];
|
||||
unsigned short o[4][14][14];
|
||||
short p[4];
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
for (int q = 0; q < 4; ++q)
|
||||
{
|
||||
p[q] = 4084;
|
||||
for (int r = 0; r < 4; ++r)
|
||||
{
|
||||
m[q][r] = 24482;
|
||||
for (int u = 0; u < 4; ++u)
|
||||
a[q][r][u] = 81;
|
||||
}
|
||||
}
|
||||
b (d, e, f, g, h, i, j, k, l, m, n, o, p);
|
||||
for (int q = 0; q < 4; ++q)
|
||||
for (int r = 0; r < 4; ++r)
|
||||
for (int u = 0; u < 14; ++u)
|
||||
seed ^= a[q][r][u] + (seed >> 2);
|
||||
|
||||
check (seed);
|
||||
}
|
Loading…
Add table
Reference in a new issue