On Thu, Nov 13, 2025 at 6:02 AM Andrew Pinski
<[email protected]> wrote:
>
> This moves the checks that were in pass_merge_phi::execute into 
> remove_forwarder_block_with_phi
> or tree_forwarder_block_p to make easier to merge 
> remove_forwarder_block_with_phi with remove_forwarder_block.
> This also simplifies the code slightly because we can do `return false` 
> rather than break
> in one location.

So this puts back one O(num-stmts) loop into CFG cleanup which I
previously tried
to make sure to be O(CFG size).  But looking we're already doing
O(#debug-stmts + #labels)
work here, so this is a moot point.

So OK to this (and the previous in the series).
Richard.

> gcc/ChangeLog:
>
>         * tree-cfgcleanup.cc (pass_merge_phi::execute): Move
>         check for abnormal or no phis to remove_forwarder_block_with_phi
>          and the check on dominated to tree_forwarder_block_p.
>         (remove_forwarder_block_with_phi): here.
>
> Signed-off-by: Andrew Pinski <[email protected]>
> ---
>  gcc/tree-cfgcleanup.cc | 102 +++++++++++++++++++----------------------
>  1 file changed, 48 insertions(+), 54 deletions(-)
>
> diff --git a/gcc/tree-cfgcleanup.cc b/gcc/tree-cfgcleanup.cc
> index 2f4fa0a7b8a..9f526492b72 100644
> --- a/gcc/tree-cfgcleanup.cc
> +++ b/gcc/tree-cfgcleanup.cc
> @@ -456,6 +456,43 @@ tree_forwarder_block_p (basic_block bb, bool phi_wanted)
>         }
>      }
>
> +  /* If BB has PHIs and does not dominate DEST,
> +     then the PHI nodes at DEST must be the only
> +     users of the results of the PHI nodes at BB.
> +     So only check when BB dominates dest.  */
> +  if (!gimple_seq_empty_p (phi_nodes (bb))
> +      && dominated_by_p (CDI_DOMINATORS, dest, bb))
> +    {
> +      gphi_iterator gsi;
> +      unsigned int dest_idx = single_succ_edge (bb)->dest_idx;
> +
> +      /* BB dominates DEST.  There may be many users of the PHI
> +        nodes in BB.  However, there is still a trivial case we
> +        can handle.  If the result of every PHI in BB is used
> +        only by a PHI in DEST, then we can trivially merge the
> +        PHI nodes from BB into DEST.  */
> +      for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
> +          gsi_next (&gsi))
> +       {
> +         gphi *phi = gsi.phi ();
> +         tree result = gimple_phi_result (phi);
> +         use_operand_p imm_use;
> +         gimple *use_stmt;
> +
> +         /* If the PHI's result is never used, then we can just
> +            ignore it an.  */
> +         if (has_zero_uses (result))
> +           continue;
> +
> +         /* Get the single use of the result of this PHI node.  */
> +         if (!single_imm_use (result, &imm_use, &use_stmt)
> +             || gimple_code (use_stmt) != GIMPLE_PHI
> +             || gimple_bb (use_stmt) != dest
> +             || gimple_phi_arg_def (use_stmt, dest_idx) != result)
> +           return false;
> +       }
> +    }
> +
>    if (current_loops)
>      {
>        /* Protect loop headers.  */
> @@ -1247,6 +1284,14 @@ remove_forwarder_block_with_phi (basic_block 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;
> @@ -1429,65 +1474,14 @@ pass_merge_phi::execute (function *fun)
>    unsigned n = last_basic_block_for_fn (fun);
>    for (unsigned i = NUM_FIXED_BLOCKS; i < n; i++)
>      {
> -      basic_block dest;
>        basic_block bb = BASIC_BLOCK_FOR_FN (fun, i);
>        if (!bb)
>         continue;
>
>        /* Look for a forwarder block with PHI nodes.  */
> -      if (!tree_forwarder_block_p (bb, true))
> -       continue;
> -
> -      dest = single_succ (bb);
> -
> -      /* 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))
> -       continue;
> -
> -     /* If BB does not dominate DEST, then the PHI nodes at
> -       DEST must be the only users of the results of the PHI
> -       nodes at BB. So only check when BB dominates dest.  */
> -      if (dominated_by_p (CDI_DOMINATORS, dest, bb))
> -       {
> -         gphi_iterator gsi;
> -         unsigned int dest_idx = single_succ_edge (bb)->dest_idx;
> -
> -         /* BB dominates DEST.  There may be many users of the PHI
> -            nodes in BB.  However, there is still a trivial case we
> -            can handle.  If the result of every PHI in BB is used
> -            only by a PHI in DEST, then we can trivially merge the
> -            PHI nodes from BB into DEST.  */
> -         for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
> -              gsi_next (&gsi))
> -           {
> -             gphi *phi = gsi.phi ();
> -             tree result = gimple_phi_result (phi);
> -             use_operand_p imm_use;
> -             gimple *use_stmt;
> -
> -             /* If the PHI's result is never used, then we can just
> -                ignore it.  */
> -             if (has_zero_uses (result))
> -               continue;
> -
> -             /* Get the single use of the result of this PHI node.  */
> -             if (!single_imm_use (result, &imm_use, &use_stmt)
> -                 || gimple_code (use_stmt) != GIMPLE_PHI
> -                 || gimple_bb (use_stmt) != dest
> -                 || gimple_phi_arg_def (use_stmt, dest_idx) != result)
> -               break;
> -           }
> -
> -         /* If the loop above iterated through all the PHI nodes
> -            in BB, then we can merge the PHIs from BB into DEST.  */
> -         if (!gsi_end_p (gsi))
> -           continue;
> -       }
> -      changed |= remove_forwarder_block_with_phi (bb);
> +      if (tree_forwarder_block_p (bb, true)
> +         && remove_forwarder_block_with_phi (bb))
> +       changed = true;
>      }
>
>    /* Removing forwarder blocks can cause formerly irreducible loops
> --
> 2.43.0
>

Reply via email to