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.
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