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