Re: [PATCH] RISC-V: Fix bugs of supporting AVL=REG (single-real-def) in VSETVL PASS

2023-01-26 Thread Kito Cheng via Gcc-patches
committed, thanks.

On Tue, Jan 10, 2023 at 7:29 AM  wrote:

> From: Ju-Zhe Zhong 
>
> gcc/ChangeLog:
>
> * config/riscv/riscv-vsetvl.cc (same_bb_and_before_p): Remove it.
> (real_insn_and_same_bb_p): New function.
> (same_bb_and_after_or_equal_p): Remove it.
> (before_p): New function.
> (reg_killed_by_bb_p): Ditto.
> (has_vsetvl_killed_avl_p): Ditto.
> (get_vl): Move location so that we can call it.
> (anticipatable_occurrence_p): Fix issue of AVL=REG support.
> (available_occurrence_p): Ditto.
> (dominate_probability_p): Remove it.
> (can_backward_propagate_p): Remove it.
> (get_all_nonphi_defs): New function.
> (get_all_predecessors): Ditto.
> (any_insn_in_bb_p): Ditto.
> (insert_vsetvl): Adjust AVL REG.
> (source_equal_p): New function.
> (extract_single_source): Ditto.
> (avl_info::single_source_equal_p): Ditto.
> (avl_info::operator==): Adjust for AVL=REG.
> (vl_vtype_info::same_avl_p): Ditto.
> (vector_insn_info::set_demand_info): Remove it.
> (vector_insn_info::compatible_p): Adjust for AVL=REG.
> (vector_insn_info::compatible_avl_p): New function.
> (vector_insn_info::merge): Adjust AVL=REG.
> (vector_insn_info::dump): Ditto.
> (pass_vsetvl::merge_successors): Remove it.
> (enum fusion_type): New enum.
> (pass_vsetvl::get_backward_fusion_type): New function.
> (pass_vsetvl::backward_demand_fusion): Adjust for AVL=REG.
> (pass_vsetvl::forward_demand_fusion): Ditto.
> (pass_vsetvl::demand_fusion): Ditto.
> (pass_vsetvl::prune_expressions): Ditto.
> (pass_vsetvl::compute_local_properties): Ditto.
> (pass_vsetvl::cleanup_vsetvls): Ditto.
> (pass_vsetvl::commit_vsetvls): Ditto.
> (pass_vsetvl::init): Ditto.
> * config/riscv/riscv-vsetvl.h (enum fusion_type): New enum.
> (enum merge_type): New enum.
>
> ---
>  gcc/config/riscv/riscv-vsetvl.cc | 928 +--
>  gcc/config/riscv/riscv-vsetvl.h  |  68 ++-
>  2 files changed, 710 insertions(+), 286 deletions(-)
>
> diff --git a/gcc/config/riscv/riscv-vsetvl.cc
> b/gcc/config/riscv/riscv-vsetvl.cc
> index 7aa2852b456..0245124e28f 100644
> --- a/gcc/config/riscv/riscv-vsetvl.cc
> +++ b/gcc/config/riscv/riscv-vsetvl.cc
> @@ -178,34 +178,97 @@ vsetvl_insn_p (rtx_insn *rinsn)
>  || INSN_CODE (rinsn) == CODE_FOR_vsetvlsi);
>  }
>
> -/* Return true if INSN1 comes befeore INSN2 in the same block.  */
>  static bool
> -same_bb_and_before_p (const insn_info *insn1, const insn_info *insn2)
> +real_insn_and_same_bb_p (const insn_info *insn, const bb_info *bb)
>  {
> -  return ((insn1->bb ()->index () == insn2->bb ()->index ())
> -&& (*insn1 < *insn2));
> +  return insn != nullptr && insn->is_real () && insn->bb () == bb;
>  }
>
> -/* Return true if INSN1 comes after or equal INSN2 in the same block.  */
>  static bool
> -same_bb_and_after_or_equal_p (const insn_info *insn1, const insn_info
> *insn2)
> +before_p (const insn_info *insn1, const insn_info *insn2)
>  {
> -  return ((insn1->bb ()->index () == insn2->bb ()->index ())
> -&& (*insn1 >= *insn2));
> +  return insn1->compare_with (insn2) == -1;
> +}
> +
> +static bool
> +reg_killed_by_bb_p (const bb_info *bb, rtx x)
> +{
> +  if (!x || vlmax_avl_p (x))
> +return false;
> +  for (const insn_info *insn : bb->real_nondebug_insns ())
> +if (find_access (insn->defs (), REGNO (x)))
> +  return true;
> +  return false;
> +}
> +
> +static bool
> +has_vsetvl_killed_avl_p (const bb_info *bb, const vector_insn_info &info)
> +{
> +  if (info.dirty_with_killed_avl_p ())
> +{
> +  rtx avl = info.get_avl ();
> +  for (const insn_info *insn : bb->reverse_real_nondebug_insns ())
> +   {
> + def_info *def = find_access (insn->defs (), REGNO (avl));
> + if (def)
> +   {
> + set_info *set = safe_dyn_cast (def);
> + if (!set)
> +   return false;
> +
> + rtx new_avl = gen_rtx_REG (GET_MODE (avl), REGNO (avl));
> + gcc_assert (new_avl != avl);
> + if (!info.compatible_avl_p (avl_info (new_avl, set)))
> +   return false;
> +
> + return true;
> +   }
> +   }
> +}
> +  return false;
> +}
> +
> +/* Helper function to get VL operand.  */
> +static rtx
> +get_vl (rtx_insn *rinsn)
> +{
> +  if (has_vl_op (rinsn))
> +{
> +  extract_insn_cached (rinsn);
> +  return recog_data.operand[get_attr_vl_op_idx (rinsn)];
> +}
> +  return SET_DEST (XVECEXP (PATTERN (rinsn), 0, 0));
>  }
>
>  /* An "anticipatable occurrence" is one that is the first occurrence in
> the
> basic block, the operands are not modified in the basic block prior
> to the occurrence and the output is not used between the start of
> -   the block and th

[PATCH] RISC-V: Fix bugs of supporting AVL=REG (single-real-def) in VSETVL PASS

2023-01-09 Thread juzhe . zhong
From: Ju-Zhe Zhong 

gcc/ChangeLog:

* config/riscv/riscv-vsetvl.cc (same_bb_and_before_p): Remove it.
(real_insn_and_same_bb_p): New function.
(same_bb_and_after_or_equal_p): Remove it.
(before_p): New function.
(reg_killed_by_bb_p): Ditto.
(has_vsetvl_killed_avl_p): Ditto.
(get_vl): Move location so that we can call it.
(anticipatable_occurrence_p): Fix issue of AVL=REG support.
(available_occurrence_p): Ditto.
(dominate_probability_p): Remove it.
(can_backward_propagate_p): Remove it.
(get_all_nonphi_defs): New function.
(get_all_predecessors): Ditto.
(any_insn_in_bb_p): Ditto.
(insert_vsetvl): Adjust AVL REG.
(source_equal_p): New function.
(extract_single_source): Ditto.
(avl_info::single_source_equal_p): Ditto.
(avl_info::operator==): Adjust for AVL=REG.
(vl_vtype_info::same_avl_p): Ditto.
(vector_insn_info::set_demand_info): Remove it.
(vector_insn_info::compatible_p): Adjust for AVL=REG.
(vector_insn_info::compatible_avl_p): New function.
(vector_insn_info::merge): Adjust AVL=REG.
(vector_insn_info::dump): Ditto.
(pass_vsetvl::merge_successors): Remove it.
(enum fusion_type): New enum.
(pass_vsetvl::get_backward_fusion_type): New function.
(pass_vsetvl::backward_demand_fusion): Adjust for AVL=REG.
(pass_vsetvl::forward_demand_fusion): Ditto.
(pass_vsetvl::demand_fusion): Ditto.
(pass_vsetvl::prune_expressions): Ditto.
(pass_vsetvl::compute_local_properties): Ditto.
(pass_vsetvl::cleanup_vsetvls): Ditto.
(pass_vsetvl::commit_vsetvls): Ditto.
(pass_vsetvl::init): Ditto.
* config/riscv/riscv-vsetvl.h (enum fusion_type): New enum.
(enum merge_type): New enum.

---
 gcc/config/riscv/riscv-vsetvl.cc | 928 +--
 gcc/config/riscv/riscv-vsetvl.h  |  68 ++-
 2 files changed, 710 insertions(+), 286 deletions(-)

diff --git a/gcc/config/riscv/riscv-vsetvl.cc b/gcc/config/riscv/riscv-vsetvl.cc
index 7aa2852b456..0245124e28f 100644
--- a/gcc/config/riscv/riscv-vsetvl.cc
+++ b/gcc/config/riscv/riscv-vsetvl.cc
@@ -178,34 +178,97 @@ vsetvl_insn_p (rtx_insn *rinsn)
 || INSN_CODE (rinsn) == CODE_FOR_vsetvlsi);
 }
 
-/* Return true if INSN1 comes befeore INSN2 in the same block.  */
 static bool
-same_bb_and_before_p (const insn_info *insn1, const insn_info *insn2)
+real_insn_and_same_bb_p (const insn_info *insn, const bb_info *bb)
 {
-  return ((insn1->bb ()->index () == insn2->bb ()->index ())
-&& (*insn1 < *insn2));
+  return insn != nullptr && insn->is_real () && insn->bb () == bb;
 }
 
-/* Return true if INSN1 comes after or equal INSN2 in the same block.  */
 static bool
-same_bb_and_after_or_equal_p (const insn_info *insn1, const insn_info *insn2)
+before_p (const insn_info *insn1, const insn_info *insn2)
 {
-  return ((insn1->bb ()->index () == insn2->bb ()->index ())
-&& (*insn1 >= *insn2));
+  return insn1->compare_with (insn2) == -1;
+}
+
+static bool
+reg_killed_by_bb_p (const bb_info *bb, rtx x)
+{
+  if (!x || vlmax_avl_p (x))
+return false;
+  for (const insn_info *insn : bb->real_nondebug_insns ())
+if (find_access (insn->defs (), REGNO (x)))
+  return true;
+  return false;
+}
+
+static bool
+has_vsetvl_killed_avl_p (const bb_info *bb, const vector_insn_info &info)
+{
+  if (info.dirty_with_killed_avl_p ())
+{
+  rtx avl = info.get_avl ();
+  for (const insn_info *insn : bb->reverse_real_nondebug_insns ())
+   {
+ def_info *def = find_access (insn->defs (), REGNO (avl));
+ if (def)
+   {
+ set_info *set = safe_dyn_cast (def);
+ if (!set)
+   return false;
+
+ rtx new_avl = gen_rtx_REG (GET_MODE (avl), REGNO (avl));
+ gcc_assert (new_avl != avl);
+ if (!info.compatible_avl_p (avl_info (new_avl, set)))
+   return false;
+
+ return true;
+   }
+   }
+}
+  return false;
+}
+
+/* Helper function to get VL operand.  */
+static rtx
+get_vl (rtx_insn *rinsn)
+{
+  if (has_vl_op (rinsn))
+{
+  extract_insn_cached (rinsn);
+  return recog_data.operand[get_attr_vl_op_idx (rinsn)];
+}
+  return SET_DEST (XVECEXP (PATTERN (rinsn), 0, 0));
 }
 
 /* An "anticipatable occurrence" is one that is the first occurrence in the
basic block, the operands are not modified in the basic block prior
to the occurrence and the output is not used between the start of
-   the block and the occurrence.  */
+   the block and the occurrence.
+
+   For VSETVL instruction, we have these following formats:
+ 1. vsetvl zero, rs1.
+ 2. vsetvl zero, imm.
+ 3. vsetvl rd, rs1.
+
+   So base on these circumstances, a DEM is considered as a local anticipatable
+   occurrence should satisfy these foll