[V2,08/14] RISC-V: P8: Unified insert and delete of vsetvl insn into Phase 4
Checks
Commit Message
This sub-patch move the modification of rtl codes from pass_vsetvl
into pre_vsetvl class.
gcc/ChangeLog:
* config/riscv/riscv-vsetvl.cc (pre_vsetvl::emit_vsetvl): New.
(pass_vsetvl::can_refine_vsetvl_p): Removed.
(pass_vsetvl::refine_vsetvls): Removed.
(pass_vsetvl::cleanup_vsetvls): Removed.
(pass_vsetvl::commit_vsetvls): Removed.
---
gcc/config/riscv/riscv-vsetvl.cc | 389 +++++++++++--------------------
1 file changed, 134 insertions(+), 255 deletions(-)
--
2.36.3
Comments
LGTM.
juzhe.zhong@rivai.ai
From: Lehua Ding
Date: 2023-10-17 19:34
To: gcc-patches
CC: juzhe.zhong; kito.cheng; rdapp.gcc; palmer; jeffreyalaw; lehua.ding
Subject: [PATCH V2 08/14] RISC-V: P8: Unified insert and delete of vsetvl insn into Phase 4
This sub-patch move the modification of rtl codes from pass_vsetvl
into pre_vsetvl class.
gcc/ChangeLog:
* config/riscv/riscv-vsetvl.cc (pre_vsetvl::emit_vsetvl): New.
(pass_vsetvl::can_refine_vsetvl_p): Removed.
(pass_vsetvl::refine_vsetvls): Removed.
(pass_vsetvl::cleanup_vsetvls): Removed.
(pass_vsetvl::commit_vsetvls): Removed.
---
gcc/config/riscv/riscv-vsetvl.cc | 389 +++++++++++--------------------
1 file changed, 134 insertions(+), 255 deletions(-)
diff --git a/gcc/config/riscv/riscv-vsetvl.cc b/gcc/config/riscv/riscv-vsetvl.cc
index a112895a283..5d84d290e9e 100644
--- a/gcc/config/riscv/riscv-vsetvl.cc
+++ b/gcc/config/riscv/riscv-vsetvl.cc
@@ -3658,6 +3658,140 @@ pre_vsetvl::pre_global_vsetvl_info ()
}
}
+void
+pre_vsetvl::emit_vsetvl ()
+{
+ bool need_commit = false;
+
+ for (const bb_info *bb : crtl->ssa->bbs ())
+ {
+ for (const auto &curr_info : get_block_info (bb).infos)
+ {
+ insn_info *insn = curr_info.get_insn ();
+ if (curr_info.ignore_p ())
+ {
+ if (vsetvl_insn_p (insn->rtl ()))
+ eliminate_insn (insn->rtl ());
+ continue;
+ }
+ else if (curr_info.valid_p ())
+ {
+ if (vsetvl_insn_p (insn->rtl ()))
+ {
+ const vsetvl_info temp = vsetvl_info (insn);
+ if (!(curr_info == temp))
+ {
+ if (dump_file)
+ {
+ fprintf (dump_file, "\n Change vsetvl info from: ");
+ temp.dump (dump_file, " ");
+ fprintf (dump_file, " to: ");
+ curr_info.dump (dump_file, " ");
+ }
+ change_vsetvl_insn (insn, curr_info);
+ }
+ }
+ else
+ {
+ if (dump_file)
+ {
+ fprintf (dump_file,
+ "\n Insert vsetvl info before insn %d: ",
+ insn->uid ());
+ curr_info.dump (dump_file, " ");
+ }
+ insert_vsetvl (EMIT_BEFORE, insn->rtl (), curr_info);
+ }
+ }
+ }
+ }
+
+ for (const vsetvl_info &item : delete_list)
+ {
+ gcc_assert (vsetvl_insn_p (item.get_insn ()->rtl ()));
+ eliminate_insn (item.get_insn ()->rtl ());
+ }
+
+ /* Insert vsetvl as LCM suggest. */
+ for (int ed = 0; ed < NUM_EDGES (edges); ed++)
+ {
+ edge eg = INDEX_EDGE (edges, ed);
+ sbitmap i = insert[ed];
+ if (bitmap_count_bits (i) < 1)
+ continue;
+
+ if (bitmap_count_bits (i) > 1)
+ /* For code with infinite loop (e.g. pr61634.c), The data flow is
+ completely wrong. */
+ continue;
+
+ gcc_assert (bitmap_count_bits (i) == 1);
+ unsigned expr_index = bitmap_first_set_bit (i);
+ const vsetvl_info &info = *exprs[expr_index];
+ gcc_assert (info.valid_p ());
+ if (dump_file)
+ {
+ fprintf (dump_file,
+ "\n Insert vsetvl info at edge(bb %u -> bb %u): ",
+ eg->src->index, eg->dest->index);
+ info.dump (dump_file, " ");
+ }
+ rtl_profile_for_edge (eg);
+ start_sequence ();
+
+ insn_info *insn = info.get_insn ();
+ insert_vsetvl (EMIT_DIRECT, insn->rtl (), info);
+ rtx_insn *rinsn = get_insns ();
+ end_sequence ();
+ default_rtl_profile ();
+
+ /* We should not get an abnormal edge here. */
+ gcc_assert (!(eg->flags & EDGE_ABNORMAL));
+ need_commit = true;
+ insert_insn_on_edge (rinsn, eg);
+ }
+
+ /* Insert vsetvl info that was not deleted after lift up. */
+ for (const bb_info *bb : crtl->ssa->bbs ())
+ {
+ const vsetvl_block_info &block_info = get_block_info (bb);
+ if (!block_info.has_info ())
+ continue;
+
+ const vsetvl_info &footer_info = block_info.get_footer_info ();
+ insn_info *insn = footer_info.get_insn ();
+
+ if (footer_info.ignore_p ())
+ continue;
+
+ edge eg;
+ edge_iterator eg_iterator;
+ FOR_EACH_EDGE (eg, eg_iterator, bb->cfg_bb ()->succs)
+ {
+ gcc_assert (!(eg->flags & EDGE_ABNORMAL));
+ if (dump_file)
+ {
+ fprintf (
+ dump_file,
+ "\n Insert missed vsetvl info at edge(bb %u -> bb %u): ",
+ eg->src->index, eg->dest->index);
+ footer_info.dump (dump_file, " ");
+ }
+ start_sequence ();
+ insert_vsetvl (EMIT_DIRECT, insn->rtl (), footer_info);
+ rtx_insn *rinsn = get_insns ();
+ end_sequence ();
+ default_rtl_profile ();
+ insert_insn_on_edge (rinsn, eg);
+ need_commit = true;
+ }
+ }
+
+ if (need_commit)
+ commit_edge_insertions ();
+}
+
+
const pass_data pass_data_vsetvl = {
RTL_PASS, /* type */
"vsetvl", /* name */
@@ -3790,261 +3924,6 @@ make_pass_vsetvl (gcc::context *ctxt)
return new pass_vsetvl (ctxt);
}
-
-/* Return true if VSETVL in the block can be refined as vsetvl zero,zero. */
-bool
-pass_vsetvl::can_refine_vsetvl_p (const basic_block cfg_bb,
- const vector_insn_info &info) const
-{
- if (!m_vector_manager->all_same_ratio_p (
- m_vector_manager->vector_avin[cfg_bb->index]))
- return false;
-
- if (!m_vector_manager->all_same_avl_p (
- cfg_bb, m_vector_manager->vector_avin[cfg_bb->index]))
- return false;
-
- size_t expr_id
- = bitmap_first_set_bit (m_vector_manager->vector_avin[cfg_bb->index]);
- if (!m_vector_manager->vector_exprs[expr_id]->same_vlmax_p (info))
- return false;
- if (!m_vector_manager->vector_exprs[expr_id]->compatible_avl_p (info))
- return false;
-
- edge e;
- edge_iterator ei;
- bool all_valid_p = true;
- FOR_EACH_EDGE (e, ei, cfg_bb->preds)
- {
- if (bitmap_empty_p (m_vector_manager->vector_avout[e->src->index]))
- {
- all_valid_p = false;
- break;
- }
- }
-
- if (!all_valid_p)
- return false;
- return true;
-}
-
-/* Optimize athe case like this:
-
- bb 0:
- vsetvl 0 a5,zero,e8,mf8
- insn 0 (demand SEW + LMUL)
- bb 1:
- vsetvl 1 a5,zero,e16,mf4
- insn 1 (demand SEW + LMUL)
-
- In this case, we should be able to refine
- vsetvl 1 into vsetvl zero, zero according AVIN. */
-void
-pass_vsetvl::refine_vsetvls (void) const
-{
- basic_block cfg_bb;
- FOR_EACH_BB_FN (cfg_bb, cfun)
- {
- auto info = get_block_info (cfg_bb).local_dem;
- insn_info *insn = info.get_insn ();
- if (!info.valid_p ())
- continue;
-
- rtx_insn *rinsn = insn->rtl ();
- if (!can_refine_vsetvl_p (cfg_bb, info))
- continue;
-
- /* We can't refine user vsetvl into vsetvl zero,zero since the dest
- will be used by the following instructions. */
- if (vector_config_insn_p (rinsn))
- {
- m_vector_manager->to_refine_vsetvls.add (rinsn);
- continue;
- }
-
- /* If all incoming edges to a block have a vector state that is compatbile
- with the block. In such a case we need not emit a vsetvl in the current
- block. */
-
- gcc_assert (has_vtype_op (insn->rtl ()));
- rinsn = PREV_INSN (insn->rtl ());
- gcc_assert (vector_config_insn_p (PREV_INSN (insn->rtl ())));
- if (m_vector_manager->all_avail_in_compatible_p (cfg_bb))
- {
- size_t id = m_vector_manager->get_expr_id (info);
- if (bitmap_bit_p (m_vector_manager->vector_del[cfg_bb->index], id))
- continue;
- eliminate_insn (rinsn);
- }
- else
- {
- rtx new_pat
- = gen_vsetvl_pat (VSETVL_VTYPE_CHANGE_ONLY, info, NULL_RTX);
- change_insn (rinsn, new_pat);
- }
- }
-}
-
-void
-pass_vsetvl::cleanup_vsetvls ()
-{
- basic_block cfg_bb;
- FOR_EACH_BB_FN (cfg_bb, cfun)
- {
- auto &info = get_block_info (cfg_bb).reaching_out;
- gcc_assert (m_vector_manager->expr_set_num (
- m_vector_manager->vector_del[cfg_bb->index])
- <= 1);
- for (size_t i = 0; i < m_vector_manager->vector_exprs.length (); i++)
- {
- if (bitmap_bit_p (m_vector_manager->vector_del[cfg_bb->index], i))
- {
- if (info.dirty_p ())
- info.set_unknown ();
- else
- {
- const auto dem = get_block_info (cfg_bb).local_dem;
- gcc_assert (dem == *m_vector_manager->vector_exprs[i]);
- insn_info *insn = dem.get_insn ();
- gcc_assert (insn && insn->rtl ());
- rtx_insn *rinsn;
- /* We can't eliminate user vsetvl since the dest will be used
- * by the following instructions. */
- if (vector_config_insn_p (insn->rtl ()))
- {
- m_vector_manager->to_delete_vsetvls.add (insn->rtl ());
- continue;
- }
-
- gcc_assert (has_vtype_op (insn->rtl ()));
- rinsn = PREV_INSN (insn->rtl ());
- gcc_assert (vector_config_insn_p (PREV_INSN (insn->rtl ())));
- eliminate_insn (rinsn);
- }
- }
- }
- }
-}
-
-bool
-pass_vsetvl::commit_vsetvls (void)
-{
- bool need_commit = false;
-
- for (int ed = 0; ed < NUM_EDGES (m_vector_manager->vector_edge_list); ed++)
- {
- for (size_t i = 0; i < m_vector_manager->vector_exprs.length (); i++)
- {
- edge eg = INDEX_EDGE (m_vector_manager->vector_edge_list, ed);
- if (bitmap_bit_p (m_vector_manager->vector_insert[ed], i))
- {
- const vector_insn_info *require
- = m_vector_manager->vector_exprs[i];
- gcc_assert (require->valid_or_dirty_p ());
- rtl_profile_for_edge (eg);
- start_sequence ();
-
- insn_info *insn = require->get_insn ();
- vector_insn_info prev_info = vector_insn_info ();
- sbitmap bitdata = m_vector_manager->vector_avout[eg->src->index];
- if (m_vector_manager->all_same_ratio_p (bitdata)
- && m_vector_manager->all_same_avl_p (eg->dest, bitdata))
- {
- size_t first = bitmap_first_set_bit (bitdata);
- prev_info = *m_vector_manager->vector_exprs[first];
- }
-
- insert_vsetvl (EMIT_DIRECT, insn->rtl (), *require, prev_info);
- rtx_insn *rinsn = get_insns ();
- end_sequence ();
- default_rtl_profile ();
-
- /* We should not get an abnormal edge here. */
- gcc_assert (!(eg->flags & EDGE_ABNORMAL));
- need_commit = true;
- insert_insn_on_edge (rinsn, eg);
-
- if (dump_file)
- {
- fprintf (dump_file,
- "\nInsert vsetvl insn %d at edge %d from <bb %d> to "
- "<bb %d>:\n",
- INSN_UID (rinsn), ed, eg->src->index,
- eg->dest->index);
- print_rtl_single (dump_file, rinsn);
- }
- }
- }
- }
-
- for (const bb_info *bb : crtl->ssa->bbs ())
- {
- basic_block cfg_bb = bb->cfg_bb ();
- const auto reaching_out = get_block_info (cfg_bb).reaching_out;
- if (!reaching_out.dirty_p ())
- continue;
-
- rtx new_pat;
- if (!reaching_out.demand_p (DEMAND_AVL))
- {
- vl_vtype_info new_info = reaching_out;
- new_info.set_avl_info (avl_info (const0_rtx, nullptr));
- new_pat = gen_vsetvl_pat (VSETVL_DISCARD_RESULT, new_info, NULL_RTX);
- }
- else if (can_refine_vsetvl_p (cfg_bb, reaching_out))
- new_pat
- = gen_vsetvl_pat (VSETVL_VTYPE_CHANGE_ONLY, reaching_out, NULL_RTX);
- else if (vlmax_avl_p (reaching_out.get_avl ()))
- {
- rtx vl = reaching_out.get_avl_or_vl_reg ();
- new_pat = gen_vsetvl_pat (VSETVL_NORMAL, reaching_out, vl);
- }
- else
- new_pat
- = gen_vsetvl_pat (VSETVL_DISCARD_RESULT, reaching_out, NULL_RTX);
-
- edge eg;
- edge_iterator eg_iterator;
- FOR_EACH_EDGE (eg, eg_iterator, cfg_bb->succs)
- {
- /* We should not get an abnormal edge here. */
- gcc_assert (!(eg->flags & EDGE_ABNORMAL));
- /* We failed to optimize this case in Phase 3 (earliest fusion):
-
- bb 2: vsetvl a5, a3 ...
- goto bb 4
- bb 3: vsetvl a5, a2 ...
- goto bb 4
- bb 4: vsetvli zero, a5 ---> Redundant, should be elided.
-
- Since "a5" value can come from either bb 2 or bb 3, we can't make
- it optimized in Phase 3 which will make phase 3 so complicated.
- Now, we do post optimization here to elide the redundant VSETVL
- insn in bb4. */
- if (m_vector_manager->vsetvl_dominated_by_all_preds_p (cfg_bb,
- reaching_out))
- continue;
-
- start_sequence ();
- emit_insn (copy_rtx (new_pat));
- rtx_insn *rinsn = get_insns ();
- end_sequence ();
-
- insert_insn_on_edge (rinsn, eg);
- need_commit = true;
- if (dump_file)
- {
- fprintf (dump_file,
- "\nInsert vsetvl insn %d from <bb %d> to <bb %d>:\n",
- INSN_UID (rinsn), cfg_bb->index, eg->dest->index);
- print_rtl_single (dump_file, rinsn);
- }
- }
- }
-
- return need_commit;
-}
-
/* Some instruction can not be accessed in RTL_SSA when we don't re-init
the new RTL_SSA framework but it is definetely at the END of the block.
--
2.36.3
@@ -3658,6 +3658,140 @@ pre_vsetvl::pre_global_vsetvl_info ()
}
}
+void
+pre_vsetvl::emit_vsetvl ()
+{
+ bool need_commit = false;
+
+ for (const bb_info *bb : crtl->ssa->bbs ())
+ {
+ for (const auto &curr_info : get_block_info (bb).infos)
+ {
+ insn_info *insn = curr_info.get_insn ();
+ if (curr_info.ignore_p ())
+ {
+ if (vsetvl_insn_p (insn->rtl ()))
+ eliminate_insn (insn->rtl ());
+ continue;
+ }
+ else if (curr_info.valid_p ())
+ {
+ if (vsetvl_insn_p (insn->rtl ()))
+ {
+ const vsetvl_info temp = vsetvl_info (insn);
+ if (!(curr_info == temp))
+ {
+ if (dump_file)
+ {
+ fprintf (dump_file, "\n Change vsetvl info from: ");
+ temp.dump (dump_file, " ");
+ fprintf (dump_file, " to: ");
+ curr_info.dump (dump_file, " ");
+ }
+ change_vsetvl_insn (insn, curr_info);
+ }
+ }
+ else
+ {
+ if (dump_file)
+ {
+ fprintf (dump_file,
+ "\n Insert vsetvl info before insn %d: ",
+ insn->uid ());
+ curr_info.dump (dump_file, " ");
+ }
+ insert_vsetvl (EMIT_BEFORE, insn->rtl (), curr_info);
+ }
+ }
+ }
+ }
+
+ for (const vsetvl_info &item : delete_list)
+ {
+ gcc_assert (vsetvl_insn_p (item.get_insn ()->rtl ()));
+ eliminate_insn (item.get_insn ()->rtl ());
+ }
+
+ /* Insert vsetvl as LCM suggest. */
+ for (int ed = 0; ed < NUM_EDGES (edges); ed++)
+ {
+ edge eg = INDEX_EDGE (edges, ed);
+ sbitmap i = insert[ed];
+ if (bitmap_count_bits (i) < 1)
+ continue;
+
+ if (bitmap_count_bits (i) > 1)
+ /* For code with infinite loop (e.g. pr61634.c), The data flow is
+ completely wrong. */
+ continue;
+
+ gcc_assert (bitmap_count_bits (i) == 1);
+ unsigned expr_index = bitmap_first_set_bit (i);
+ const vsetvl_info &info = *exprs[expr_index];
+ gcc_assert (info.valid_p ());
+ if (dump_file)
+ {
+ fprintf (dump_file,
+ "\n Insert vsetvl info at edge(bb %u -> bb %u): ",
+ eg->src->index, eg->dest->index);
+ info.dump (dump_file, " ");
+ }
+ rtl_profile_for_edge (eg);
+ start_sequence ();
+
+ insn_info *insn = info.get_insn ();
+ insert_vsetvl (EMIT_DIRECT, insn->rtl (), info);
+ rtx_insn *rinsn = get_insns ();
+ end_sequence ();
+ default_rtl_profile ();
+
+ /* We should not get an abnormal edge here. */
+ gcc_assert (!(eg->flags & EDGE_ABNORMAL));
+ need_commit = true;
+ insert_insn_on_edge (rinsn, eg);
+ }
+
+ /* Insert vsetvl info that was not deleted after lift up. */
+ for (const bb_info *bb : crtl->ssa->bbs ())
+ {
+ const vsetvl_block_info &block_info = get_block_info (bb);
+ if (!block_info.has_info ())
+ continue;
+
+ const vsetvl_info &footer_info = block_info.get_footer_info ();
+ insn_info *insn = footer_info.get_insn ();
+
+ if (footer_info.ignore_p ())
+ continue;
+
+ edge eg;
+ edge_iterator eg_iterator;
+ FOR_EACH_EDGE (eg, eg_iterator, bb->cfg_bb ()->succs)
+ {
+ gcc_assert (!(eg->flags & EDGE_ABNORMAL));
+ if (dump_file)
+ {
+ fprintf (
+ dump_file,
+ "\n Insert missed vsetvl info at edge(bb %u -> bb %u): ",
+ eg->src->index, eg->dest->index);
+ footer_info.dump (dump_file, " ");
+ }
+ start_sequence ();
+ insert_vsetvl (EMIT_DIRECT, insn->rtl (), footer_info);
+ rtx_insn *rinsn = get_insns ();
+ end_sequence ();
+ default_rtl_profile ();
+ insert_insn_on_edge (rinsn, eg);
+ need_commit = true;
+ }
+ }
+
+ if (need_commit)
+ commit_edge_insertions ();
+}
+
+
const pass_data pass_data_vsetvl = {
RTL_PASS, /* type */
"vsetvl", /* name */
@@ -3790,261 +3924,6 @@ make_pass_vsetvl (gcc::context *ctxt)
return new pass_vsetvl (ctxt);
}
-
-/* Return true if VSETVL in the block can be refined as vsetvl zero,zero. */
-bool
-pass_vsetvl::can_refine_vsetvl_p (const basic_block cfg_bb,
- const vector_insn_info &info) const
-{
- if (!m_vector_manager->all_same_ratio_p (
- m_vector_manager->vector_avin[cfg_bb->index]))
- return false;
-
- if (!m_vector_manager->all_same_avl_p (
- cfg_bb, m_vector_manager->vector_avin[cfg_bb->index]))
- return false;
-
- size_t expr_id
- = bitmap_first_set_bit (m_vector_manager->vector_avin[cfg_bb->index]);
- if (!m_vector_manager->vector_exprs[expr_id]->same_vlmax_p (info))
- return false;
- if (!m_vector_manager->vector_exprs[expr_id]->compatible_avl_p (info))
- return false;
-
- edge e;
- edge_iterator ei;
- bool all_valid_p = true;
- FOR_EACH_EDGE (e, ei, cfg_bb->preds)
- {
- if (bitmap_empty_p (m_vector_manager->vector_avout[e->src->index]))
- {
- all_valid_p = false;
- break;
- }
- }
-
- if (!all_valid_p)
- return false;
- return true;
-}
-
-/* Optimize athe case like this:
-
- bb 0:
- vsetvl 0 a5,zero,e8,mf8
- insn 0 (demand SEW + LMUL)
- bb 1:
- vsetvl 1 a5,zero,e16,mf4
- insn 1 (demand SEW + LMUL)
-
- In this case, we should be able to refine
- vsetvl 1 into vsetvl zero, zero according AVIN. */
-void
-pass_vsetvl::refine_vsetvls (void) const
-{
- basic_block cfg_bb;
- FOR_EACH_BB_FN (cfg_bb, cfun)
- {
- auto info = get_block_info (cfg_bb).local_dem;
- insn_info *insn = info.get_insn ();
- if (!info.valid_p ())
- continue;
-
- rtx_insn *rinsn = insn->rtl ();
- if (!can_refine_vsetvl_p (cfg_bb, info))
- continue;
-
- /* We can't refine user vsetvl into vsetvl zero,zero since the dest
- will be used by the following instructions. */
- if (vector_config_insn_p (rinsn))
- {
- m_vector_manager->to_refine_vsetvls.add (rinsn);
- continue;
- }
-
- /* If all incoming edges to a block have a vector state that is compatbile
- with the block. In such a case we need not emit a vsetvl in the current
- block. */
-
- gcc_assert (has_vtype_op (insn->rtl ()));
- rinsn = PREV_INSN (insn->rtl ());
- gcc_assert (vector_config_insn_p (PREV_INSN (insn->rtl ())));
- if (m_vector_manager->all_avail_in_compatible_p (cfg_bb))
- {
- size_t id = m_vector_manager->get_expr_id (info);
- if (bitmap_bit_p (m_vector_manager->vector_del[cfg_bb->index], id))
- continue;
- eliminate_insn (rinsn);
- }
- else
- {
- rtx new_pat
- = gen_vsetvl_pat (VSETVL_VTYPE_CHANGE_ONLY, info, NULL_RTX);
- change_insn (rinsn, new_pat);
- }
- }
-}
-
-void
-pass_vsetvl::cleanup_vsetvls ()
-{
- basic_block cfg_bb;
- FOR_EACH_BB_FN (cfg_bb, cfun)
- {
- auto &info = get_block_info (cfg_bb).reaching_out;
- gcc_assert (m_vector_manager->expr_set_num (
- m_vector_manager->vector_del[cfg_bb->index])
- <= 1);
- for (size_t i = 0; i < m_vector_manager->vector_exprs.length (); i++)
- {
- if (bitmap_bit_p (m_vector_manager->vector_del[cfg_bb->index], i))
- {
- if (info.dirty_p ())
- info.set_unknown ();
- else
- {
- const auto dem = get_block_info (cfg_bb).local_dem;
- gcc_assert (dem == *m_vector_manager->vector_exprs[i]);
- insn_info *insn = dem.get_insn ();
- gcc_assert (insn && insn->rtl ());
- rtx_insn *rinsn;
- /* We can't eliminate user vsetvl since the dest will be used
- * by the following instructions. */
- if (vector_config_insn_p (insn->rtl ()))
- {
- m_vector_manager->to_delete_vsetvls.add (insn->rtl ());
- continue;
- }
-
- gcc_assert (has_vtype_op (insn->rtl ()));
- rinsn = PREV_INSN (insn->rtl ());
- gcc_assert (vector_config_insn_p (PREV_INSN (insn->rtl ())));
- eliminate_insn (rinsn);
- }
- }
- }
- }
-}
-
-bool
-pass_vsetvl::commit_vsetvls (void)
-{
- bool need_commit = false;
-
- for (int ed = 0; ed < NUM_EDGES (m_vector_manager->vector_edge_list); ed++)
- {
- for (size_t i = 0; i < m_vector_manager->vector_exprs.length (); i++)
- {
- edge eg = INDEX_EDGE (m_vector_manager->vector_edge_list, ed);
- if (bitmap_bit_p (m_vector_manager->vector_insert[ed], i))
- {
- const vector_insn_info *require
- = m_vector_manager->vector_exprs[i];
- gcc_assert (require->valid_or_dirty_p ());
- rtl_profile_for_edge (eg);
- start_sequence ();
-
- insn_info *insn = require->get_insn ();
- vector_insn_info prev_info = vector_insn_info ();
- sbitmap bitdata = m_vector_manager->vector_avout[eg->src->index];
- if (m_vector_manager->all_same_ratio_p (bitdata)
- && m_vector_manager->all_same_avl_p (eg->dest, bitdata))
- {
- size_t first = bitmap_first_set_bit (bitdata);
- prev_info = *m_vector_manager->vector_exprs[first];
- }
-
- insert_vsetvl (EMIT_DIRECT, insn->rtl (), *require, prev_info);
- rtx_insn *rinsn = get_insns ();
- end_sequence ();
- default_rtl_profile ();
-
- /* We should not get an abnormal edge here. */
- gcc_assert (!(eg->flags & EDGE_ABNORMAL));
- need_commit = true;
- insert_insn_on_edge (rinsn, eg);
-
- if (dump_file)
- {
- fprintf (dump_file,
- "\nInsert vsetvl insn %d at edge %d from <bb %d> to "
- "<bb %d>:\n",
- INSN_UID (rinsn), ed, eg->src->index,
- eg->dest->index);
- print_rtl_single (dump_file, rinsn);
- }
- }
- }
- }
-
- for (const bb_info *bb : crtl->ssa->bbs ())
- {
- basic_block cfg_bb = bb->cfg_bb ();
- const auto reaching_out = get_block_info (cfg_bb).reaching_out;
- if (!reaching_out.dirty_p ())
- continue;
-
- rtx new_pat;
- if (!reaching_out.demand_p (DEMAND_AVL))
- {
- vl_vtype_info new_info = reaching_out;
- new_info.set_avl_info (avl_info (const0_rtx, nullptr));
- new_pat = gen_vsetvl_pat (VSETVL_DISCARD_RESULT, new_info, NULL_RTX);
- }
- else if (can_refine_vsetvl_p (cfg_bb, reaching_out))
- new_pat
- = gen_vsetvl_pat (VSETVL_VTYPE_CHANGE_ONLY, reaching_out, NULL_RTX);
- else if (vlmax_avl_p (reaching_out.get_avl ()))
- {
- rtx vl = reaching_out.get_avl_or_vl_reg ();
- new_pat = gen_vsetvl_pat (VSETVL_NORMAL, reaching_out, vl);
- }
- else
- new_pat
- = gen_vsetvl_pat (VSETVL_DISCARD_RESULT, reaching_out, NULL_RTX);
-
- edge eg;
- edge_iterator eg_iterator;
- FOR_EACH_EDGE (eg, eg_iterator, cfg_bb->succs)
- {
- /* We should not get an abnormal edge here. */
- gcc_assert (!(eg->flags & EDGE_ABNORMAL));
- /* We failed to optimize this case in Phase 3 (earliest fusion):
-
- bb 2: vsetvl a5, a3 ...
- goto bb 4
- bb 3: vsetvl a5, a2 ...
- goto bb 4
- bb 4: vsetvli zero, a5 ---> Redundant, should be elided.
-
- Since "a5" value can come from either bb 2 or bb 3, we can't make
- it optimized in Phase 3 which will make phase 3 so complicated.
- Now, we do post optimization here to elide the redundant VSETVL
- insn in bb4. */
- if (m_vector_manager->vsetvl_dominated_by_all_preds_p (cfg_bb,
- reaching_out))
- continue;
-
- start_sequence ();
- emit_insn (copy_rtx (new_pat));
- rtx_insn *rinsn = get_insns ();
- end_sequence ();
-
- insert_insn_on_edge (rinsn, eg);
- need_commit = true;
- if (dump_file)
- {
- fprintf (dump_file,
- "\nInsert vsetvl insn %d from <bb %d> to <bb %d>:\n",
- INSN_UID (rinsn), cfg_bb->index, eg->dest->index);
- print_rtl_single (dump_file, rinsn);
- }
- }
- }
-
- return need_commit;
-}
-
/* Some instruction can not be accessed in RTL_SSA when we don't re-init
the new RTL_SSA framework but it is definetely at the END of the block.