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

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.
This commit is contained in:
Ju-Zhe Zhong 2023-01-10 07:29:11 +08:00 committed by Kito Cheng
parent acc10c7931
commit 4f673c5ee2
2 changed files with 717 additions and 293 deletions

File diff suppressed because it is too large Load diff

View file

@ -52,6 +52,19 @@ enum demand_type
NUM_DEMAND
};
enum fusion_type
{
INVALID_FUSION,
VALID_AVL_FUSION,
KILLED_AVL_FUSION
};
enum merge_type
{
LOCAL_MERGE,
GLOBAL_MERGE
};
/* AVL info for RVV instruction. Most RVV instructions have AVL operand in
implicit dependency. The AVL comparison between 2 RVV instructions is
very important since it affects our decision whether we should insert
@ -129,6 +142,7 @@ public:
avl_info (rtx, rtl_ssa::set_info *);
rtx get_value () const { return m_value; }
rtl_ssa::set_info *get_source () const { return m_source; }
bool single_source_equal_p (const avl_info &) const;
avl_info &operator= (const avl_info &);
bool operator== (const avl_info &) const;
bool operator!= (const avl_info &) const;
@ -174,6 +188,7 @@ public:
rtx get_avl () const { return m_avl.get_value (); }
const avl_info &get_avl_info () const { return m_avl; }
rtl_ssa::set_info *get_avl_source () const { return m_avl.get_source (); }
void set_avl_info (const avl_info &avl) { m_avl = avl; }
uint8_t get_sew () const { return m_sew; }
riscv_vector::vlmul_type get_vlmul () const { return m_vlmul; }
@ -199,7 +214,25 @@ private:
/* The block is polluted as containing VSETVL instruction during dem
backward propagation to gain better LCM optimization even though
such VSETVL instruction is not really emit yet during this time. */
DIRTY
DIRTY,
/* The block is polluted with killed AVL.
We will backward propagate such case:
bb 0: def a5, 55 (empty).
...
bb 1: vsetvli zero, a5.
...
bb 2: empty.
...
bb 3: def a3, 55 (empty).
...
bb 4: vsetvli zero, a3.
To elide vsetvli in bb 4, we need to backward pollute bb 3 and bb 2
as DIRTY block as long as there is a block def AVL which has the same
source with AVL in bb 4. Such polluted block, we call it as
DIRTY_WITH_KILLED_AVL
*/
DIRTY_WITH_KILLED_AVL
};
enum state_type m_state;
@ -247,10 +280,19 @@ public:
bool valid_p () const { return m_state == VALID; }
bool unknown_p () const { return m_state == UNKNOWN; }
bool empty_p () const { return m_state == EMPTY; }
bool dirty_p () const { return m_state == DIRTY; }
bool dirty_p () const
{
return m_state == DIRTY || m_state == DIRTY_WITH_KILLED_AVL;
}
bool dirty_with_killed_avl_p () const
{
return m_state == DIRTY_WITH_KILLED_AVL;
}
bool real_dirty_p () const { return m_state == DIRTY; }
bool valid_or_dirty_p () const
{
return m_state == VALID || m_state == DIRTY;
return m_state == VALID || m_state == DIRTY
|| m_state == DIRTY_WITH_KILLED_AVL;
}
static vector_insn_info get_unknown ()
@ -263,9 +305,22 @@ public:
void set_valid () { m_state = VALID; }
void set_unknown () { m_state = UNKNOWN; }
void set_empty () { m_state = EMPTY; }
void set_dirty () { m_state = DIRTY; }
void set_dirty (enum fusion_type type)
{
gcc_assert (type == VALID_AVL_FUSION || type == KILLED_AVL_FUSION);
if (type == VALID_AVL_FUSION)
m_state = DIRTY;
else
m_state = DIRTY_WITH_KILLED_AVL;
}
void set_dirty (bool dirty_with_killed_avl_p)
{
if (dirty_with_killed_avl_p)
m_state = DIRTY_WITH_KILLED_AVL;
else
m_state = DIRTY;
}
void set_insn (rtl_ssa::insn_info *insn) { m_insn = insn; }
void set_demand_info (const vector_insn_info &);
bool demand_p (enum demand_type type) const { return m_demands[type]; }
void demand (enum demand_type type) { m_demands[type] = true; }
@ -274,9 +329,10 @@ public:
bool compatible_p (const vector_insn_info &) const;
bool compatible_avl_p (const vl_vtype_info &) const;
bool compatible_avl_p (const avl_info &) const;
bool compatible_vtype_p (const vl_vtype_info &) const;
bool compatible_p (const vl_vtype_info &) const;
vector_insn_info merge (const vector_insn_info &, bool) const;
vector_insn_info merge (const vector_insn_info &, enum merge_type) const;
rtl_ssa::insn_info *get_insn () const { return m_insn; }