This is the last cleanup in this area. Merges the splitting functionality
of remove_forwarder_block_with_phi into remove_forwarder_block.
Now mergephi still has the ability to split the edges when merging the forwarder
block with a phi. But this reduces the non-shared code a lot.
gcc/ChangeLog:
* tree-cfgcleanup.cc (tree_forwarder_block_p): Remove must argument.
(remove_forwarder_block): Add can_split
argument. Handle the splitting case (iff phis in bb).
(cleanup_tree_cfg_bb): Update argument to tree_forwarder_block_p.
(remove_forwarder_block_with_phi): Remove.
(pass_merge_phi::execute): Update argument to tree_forwarder_block_p
and call remove_forwarder_block instead of
remove_forwarder_block_with_phi.
Signed-off-by: Andrew Pinski <[email protected]>
---
gcc/tree-cfgcleanup.cc | 134 +++++++----------------------------------
1 file changed, 22 insertions(+), 112 deletions(-)
diff --git a/gcc/tree-cfgcleanup.cc b/gcc/tree-cfgcleanup.cc
index 636a546a3dc..ac1394ac1d4 100644
--- a/gcc/tree-cfgcleanup.cc
+++ b/gcc/tree-cfgcleanup.cc
@@ -386,7 +386,7 @@ cleanup_control_flow_bb (basic_block bb)
the entry block. */
static bool
-tree_forwarder_block_p (basic_block bb, bool must_have_phis)
+tree_forwarder_block_p (basic_block bb)
{
gimple_stmt_iterator gsi;
location_t locus;
@@ -401,10 +401,6 @@ tree_forwarder_block_p (basic_block bb, bool
must_have_phis)
|| (single_succ_edge (bb)->flags & EDGE_ABNORMAL))
return false;
- /* If MUST_HAVE_PHIS is true and we don't have any phis, return false. */
- if (must_have_phis && gimple_seq_empty_p (phi_nodes (bb)))
- return false;
-
gcc_checking_assert (bb != ENTRY_BLOCK_PTR_FOR_FN (cfun));
locus = single_succ_edge (bb)->goto_locus;
@@ -622,7 +618,7 @@ move_debug_stmts_from_forwarder (basic_block src,
/* Removes forwarder block BB. Returns false if this failed. */
static bool
-remove_forwarder_block (basic_block bb)
+remove_forwarder_block (basic_block bb, bool can_split = false)
{
edge succ = single_succ_edge (bb), e, s;
basic_block dest = succ->dest;
@@ -658,7 +654,8 @@ remove_forwarder_block (basic_block bb)
phi node arguments match.
Otherwise we have to split the edge and that becomes
a "forwarder" again. */
- if (!gimple_seq_empty_p (phi_nodes (dest)))
+ if ((!can_split || !has_phi)
+ && !gimple_seq_empty_p (phi_nodes (dest)))
{
edge_iterator ei;
FOR_EACH_EDGE (e, ei, bb->preds)
@@ -680,7 +677,17 @@ remove_forwarder_block (basic_block bb)
/* Redirect the edges. */
for (edge_iterator ei = ei_start (bb->preds); (e = ei_safe_edge (ei)); )
{
- bitmap_set_bit (cfgcleanup_altered_bbs, e->src->index);
+ if (cfgcleanup_altered_bbs)
+ bitmap_set_bit (cfgcleanup_altered_bbs, e->src->index);
+ s = find_edge (e->src, dest);
+
+ /* See if we can split the edge if we already have an edge from src to
dest. */
+ if (can_split && has_phi)
+ /* PHI arguments are different. Create a forwarder block by
+ splitting E so that we can merge PHI arguments on E to
+ DEST. */
+ if (s && !phi_alternatives_equal (dest, s, succ))
+ e = single_succ_edge (split_edge (e));
if (e->flags & EDGE_ABNORMAL)
{
@@ -709,6 +716,8 @@ remove_forwarder_block (basic_block bb)
here before. */
copy_phi_arg_into_existing_phi (succ, s, has_phi);
}
+ else
+ redirect_edge_var_map_clear (s);
}
/* Move nonlocal labels and computed goto targets as well as user
@@ -741,7 +750,8 @@ remove_forwarder_block (basic_block bb)
move_debug_stmts_from_forwarder (bb, dest, dest_single_pred_p,
pred, pred && single_succ_p (pred));
- bitmap_set_bit (cfgcleanup_altered_bbs, dest->index);
+ if (cfgcleanup_altered_bbs)
+ bitmap_set_bit (cfgcleanup_altered_bbs, dest->index);
/* Update the dominators. */
basic_block dom, dombb, domdest;
@@ -859,7 +869,7 @@ want_merge_blocks_p (basic_block bb1, basic_block bb2)
static bool
cleanup_tree_cfg_bb (basic_block bb)
{
- if (tree_forwarder_block_p (bb, false)
+ if (tree_forwarder_block_p (bb)
&& remove_forwarder_block (bb))
return true;
@@ -1303,106 +1313,6 @@ cleanup_tree_cfg (unsigned ssa_update_flags)
return changed;
}
-/* Tries to merge the PHI nodes at BB into those at BB's sole successor.
- Returns true if successful. */
-
-static bool
-remove_forwarder_block_with_phi (basic_block bb)
-{
- edge e, succ = single_succ_edge (bb);
- basic_block dest = succ->dest;
- basic_block dombb, domdest, dom;
-
- /* We have to feed into another basic block with PHI
- nodes. */
- if (gimple_seq_empty_p (phi_nodes (dest))
- /* We don't want to deal with a basic block with
- abnormal edges. */
- || bb_has_abnormal_pred (bb))
- return false;
-
- /* Record BB's single pred in case we need to update the father
- loop's latch information later. */
- basic_block pred = NULL;
- if (single_pred_p (bb))
- pred = single_pred (bb);
- bool dest_single_pred_p = single_pred_p (dest);
-
- /* Redirect each incoming edge to BB to DEST. */
- for (edge_iterator ei = ei_start (bb->preds); (e = ei_safe_edge (ei)); )
- {
- edge s;
-
- s = find_edge (e->src, dest);
- if (s)
- {
- /* We already have an edge S from E->src to DEST. If S and
- E->dest's sole successor edge have the same PHI arguments
- at DEST, redirect S to DEST. */
- if (phi_alternatives_equal (dest, s, succ))
- {
- e = redirect_edge_and_branch (e, dest);
- redirect_edge_var_map_clear (e);
- continue;
- }
-
- /* PHI arguments are different. Create a forwarder block by
- splitting E so that we can merge PHI arguments on E to
- DEST. */
- e = single_succ_edge (split_edge (e));
- }
- else
- {
- /* If we merge the forwarder into a loop header verify if we
- are creating another loop latch edge. If so, reset
- number of iteration information of the loop. */
- if (dest->loop_father->header == dest
- && dominated_by_p (CDI_DOMINATORS, e->src, dest))
- {
- dest->loop_father->any_upper_bound = false;
- dest->loop_father->any_likely_upper_bound = false;
- free_numbers_of_iterations_estimates (dest->loop_father);
- }
- }
-
- s = redirect_edge_and_branch (e, dest);
-
- /* redirect_edge_and_branch must not create a new edge. */
- gcc_assert (s == e);
- copy_phi_arg_into_existing_phi (succ, s, true);
- }
-
- /* Move debug statements. Reset them if the destination does not
- have a single predecessor. */
- move_debug_stmts_from_forwarder (bb, dest, dest_single_pred_p,
- pred, pred && single_succ_p (pred));
-
- /* Update the dominators. */
- dombb = get_immediate_dominator (CDI_DOMINATORS, bb);
- domdest = get_immediate_dominator (CDI_DOMINATORS, dest);
- if (domdest == bb)
- {
- /* Shortcut to avoid calling (relatively expensive)
- nearest_common_dominator unless necessary. */
- dom = dombb;
- }
- else
- dom = nearest_common_dominator (CDI_DOMINATORS, domdest, dombb);
-
- set_immediate_dominator (CDI_DOMINATORS, dest, dom);
-
- /* Adjust latch infomation of BB's parent loop as otherwise
- the cfg hook has a hard time not to kill the loop. */
- if (current_loops && bb->loop_father->latch == bb)
- bb->loop_father->latch = pred;
-
- /* Remove BB since all of BB's incoming edges have been redirected
- to DEST. */
- delete_basic_block (bb);
-
- return true;
-}
-
/* This pass merges PHI nodes if one feeds into another. For example,
suppose we have the following:
@@ -1471,8 +1381,8 @@ pass_merge_phi::execute (function *fun)
continue;
/* Look for a forwarder block with PHI nodes. */
- if (tree_forwarder_block_p (bb, true)
- && remove_forwarder_block_with_phi (bb))
+ if (tree_forwarder_block_p (bb)
+ && remove_forwarder_block (bb, true))
changed = true;
}
--
2.43.0