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
>

Reply via email to