On Thu, Nov 13, 2025 at 5:57 AM Andrew Pinski <[email protected]> wrote: > > 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.
OK. Richard. > 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 >
