summaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-tail-merge.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-ssa-tail-merge.c')
-rw-r--r--gcc/tree-ssa-tail-merge.c357
1 files changed, 39 insertions, 318 deletions
diff --git a/gcc/tree-ssa-tail-merge.c b/gcc/tree-ssa-tail-merge.c
index 17e7f374b05..a501b0778a2 100644
--- a/gcc/tree-ssa-tail-merge.c
+++ b/gcc/tree-ssa-tail-merge.c
@@ -742,7 +742,7 @@ delete_worklist (void)
/* Mark BB as deleted, and mark its predecessors. */
static void
-delete_basic_block_same_succ (basic_block bb)
+mark_basic_block_deleted (basic_block bb)
{
edge e;
edge_iterator ei;
@@ -809,15 +809,6 @@ release_last_vdef (basic_block bb)
}
-/* Delete all deleted_bbs. */
-
-static void
-purge_bbs (void)
-{
- bitmap_and_compl_into (deleted_bb_preds, deleted_bbs);
- bitmap_clear (deleted_bbs);
-}
-
/* For deleted_bb_preds, find bbs with same successors. */
static void
@@ -828,6 +819,9 @@ update_worklist (void)
basic_block bb;
same_succ same;
+ bitmap_and_compl_into (deleted_bb_preds, deleted_bbs);
+ bitmap_clear (deleted_bbs);
+
bitmap_clear_bit (deleted_bb_preds, ENTRY_BLOCK);
same_succ_flush_bbs (deleted_bb_preds);
@@ -1353,125 +1347,6 @@ find_clusters (void)
}
}
-/* Replace uses of the result of PHI with NAME. */
-
-static void
-unlink_virtual_phi (gimple phi, tree name)
-{
- use_operand_p use_p;
- imm_use_iterator iter;
- gimple use_stmt;
- tree vdef = gimple_phi_result (phi);
-
- if (!vdef
- || TREE_CODE (vdef) != SSA_NAME)
- return;
-
- FOR_EACH_IMM_USE_STMT (use_stmt, iter, vdef)
- {
- FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
- SET_USE (use_p, name);
- }
-
- if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (vdef))
- SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name) = 1;
-}
-
-/* Create or update a vop phi in BB2. Use VUSE1 arguments for all the
- REDIRECTED_EDGES, or if VUSE1 is NULL_TREE, use BB_VOP_AT_EXIT. If a new
- phis is created, use the phi instead of VUSE2 in BB2. */
-
-static void
-update_vuses (bool vuse1_phi_args, tree vuse1, tree vuse2, basic_block bb2,
- VEC (edge,heap) *redirected_edges)
-{
- gimple stmt, phi = NULL;
- tree lhs = NULL_TREE, arg, var;
- unsigned int i;
- gimple def_stmt2 = NULL;
- imm_use_iterator iter;
- use_operand_p use_p;
- edge_iterator ei;
- edge e;
-
- if (vuse2 != NULL_TREE)
- {
- var = SSA_NAME_VAR (vuse2);
- def_stmt2 = SSA_NAME_DEF_STMT (vuse2);
- }
- else
- var = SSA_NAME_VAR (vuse1);
-
- if (def_stmt2 && gimple_bb (def_stmt2) == bb2)
- /* Update existing phi. */
- phi = def_stmt2;
- else
- {
- /* No need to create a phi with 2 equal arguments. */
- if (vuse1 == vuse2)
- return;
-
- /* Create a phi. */
- lhs = make_ssa_name (var, NULL);
- VN_INFO_GET (lhs);
- phi = create_phi_node (lhs, bb2);
- SSA_NAME_DEF_STMT (lhs) = phi;
-
- /* Set default argument vuse2 for all preds. */
- arg = vuse2 == NULL_TREE ? gimple_phi_result (phi): vuse2;
- FOR_EACH_EDGE (e, ei, bb2->preds)
- add_phi_arg (phi, arg, e, UNKNOWN_LOCATION);
- }
-
- /* Update phi. */
- for (i = 0; i < EDGE_COUNT (redirected_edges); ++i)
- {
- e = VEC_index (edge, redirected_edges, i);
- if (vuse1_phi_args)
- arg = BB_VOP_AT_EXIT (e->src);
- else
- arg = vuse1 == NULL_TREE ? gimple_phi_result (phi): vuse1;
-
- add_phi_arg (phi, arg, e, UNKNOWN_LOCATION);
- }
-
- /* Return if we updated an existing phi. */
- if (def_stmt2 && gimple_bb (def_stmt2) == bb2)
- return;
-
- /* Replace relevant uses with the newly created phi. */
- FOR_EACH_IMM_USE_STMT (stmt, iter, vuse2 == NULL_TREE ? vuse1 : vuse2)
- {
- if (stmt == phi)
- continue;
-
- if (gimple_code (stmt) != GIMPLE_PHI
- && !dominated_by_p (CDI_DOMINATORS, gimple_bb (stmt), bb2))
- continue;
-
- FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
- {
- if (gimple_code (stmt) == GIMPLE_PHI)
- {
- unsigned int pred_index = PHI_ARG_INDEX_FROM_USE (use_p);
- basic_block pred = EDGE_PRED (gimple_bb (stmt), pred_index)->src;
- if (!dominated_by_p (CDI_DOMINATORS, pred, bb2))
- continue;
-
- if (pred == bb2 && EDGE_COUNT (gimple_bb (stmt)->preds) == 1)
- {
- gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
- unlink_virtual_phi (stmt, lhs);
- remove_phi_node (&gsi, true);
- break;
- }
- }
- SET_USE (use_p, lhs);
- update_stmt (stmt);
- }
- }
-}
-
/* Returns the vop phi of BB, if any. */
static gimple
@@ -1489,176 +1364,19 @@ vop_phi (basic_block bb)
return NULL;
}
-/* Returns the vop state at the entry of BB, if found in BB or a successor
- bb. */
-
-static tree
-vop_at_entry (basic_block bb)
-{
- gimple bb_phi, succ_phi;
- gimple_stmt_iterator gsi;
- gimple stmt;
- tree vuse, vdef;
- basic_block succ;
-
- bb_phi = vop_phi (bb);
- if (bb_phi != NULL)
- return gimple_phi_result (bb_phi);
-
- for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
- {
- stmt = gsi_stmt (gsi);
- vuse = gimple_vuse (stmt);
- vdef = gimple_vdef (stmt);
- if (vuse != NULL_TREE)
- return vuse;
- if (vdef != NULL_TREE)
- return NULL_TREE;
- }
-
- if (EDGE_COUNT (bb->succs) == 0)
- return NULL_TREE;
-
- succ = EDGE_SUCC (bb, 0)->dest;
- succ_phi = vop_phi (succ);
- return (succ_phi != NULL
- ? PHI_ARG_DEF_FROM_EDGE (succ_phi, find_edge (bb, succ))
- : NULL_TREE);
-}
-
-/* Given that all incoming edges of BB1 have been redirected to BB2, delete BB1
- and recompute dominator info. */
+/* Redirect all edges from BB1 to BB2, removes BB1 and marks it as removed. */
static void
-delete_block_update_dominator_info (basic_block bb1, basic_block bb2)
-{
- VEC (basic_block,heap) *fix_dom_bb;
- unsigned int i;
- basic_block bb, dom;
- edge e;
- edge_iterator ei;
-
- /* Consider the following cfg, where A is the direct dominator of I:
-
- A
- / \
- B \
- / \ \
- C D
- /| |\
- E F
- |\ /|
- | x |
- |/ \|
- G H
- \ /
- I
-
- Say E and F are duplicates, and F is removed. The cfg then looks like
- this:
-
- A
- / \
- B \
- / \ \
- C D
- / \ / \
- E
- / \
- G H
- \ /
- I
-
- E is now the new direct dominator of I.
-
- In order to calculate the new dominator info, we take the nearest common
- dominator (A) of bb1 (F) and bb2 (E), and get the set of bbs immediately
- dominated by it. Some of this set may now be directly dominated by bb2.
-
- Ideally we would have a means to determine which bbs in the set are now
- dominated by bb2, and call set_immediate_dominator for those bbs, but we
- don't, so instead we let iterate_fix_dominators figure it out. */
-
- /* Add bbs immediately dominated by the most common dominator. */
- dom = nearest_common_dominator (CDI_DOMINATORS, bb1, bb2);
- fix_dom_bb = get_dominated_by (CDI_DOMINATORS, dom);
-
- if (get_immediate_dominator (CDI_DOMINATORS, bb1) == dom)
- for (i = 0; VEC_iterate (basic_block, fix_dom_bb, i, bb); ++i)
- {
- if (bb != bb1)
- continue;
- VEC_unordered_remove (basic_block, fix_dom_bb, i);
- break;
- }
-
- /* Add bb2, but not twice. */
- if (get_immediate_dominator (CDI_DOMINATORS, bb2) != dom)
- VEC_safe_push (basic_block, heap, fix_dom_bb, bb2);
- /* Add succs of bb2, but not twice. */
- FOR_EACH_EDGE (e, ei, bb2->succs)
- if (get_immediate_dominator (CDI_DOMINATORS, e->dest) != dom)
- VEC_safe_push (basic_block, heap, fix_dom_bb, e->dest);
-
- delete_basic_block (bb1);
- iterate_fix_dominators (CDI_DOMINATORS, fix_dom_bb, false);
-#if defined (ENABLE_CHECKING)
- verify_dominators (CDI_DOMINATORS);
-#endif
- VEC_free (basic_block, heap, fix_dom_bb);
-}
-
-/* Redirect all edges from BB1 to BB2, marks BB1 for removal, and if
- UPDATE_VOPS, inserts vop phis. */
-
-static void
-replace_block_by (basic_block bb1, basic_block bb2, bool update_vops)
+replace_block_by (basic_block bb1, basic_block bb2)
{
edge pred_edge;
unsigned int i;
- tree phi_vuse1 = NULL_TREE, phi_vuse2 = NULL_TREE, arg;
- VEC (edge,heap) *redirected_edges = NULL;
- edge e;
- edge_iterator ei;
- bool vuse1_phi_args = false;
-
- phi_vuse2 = vop_at_entry (bb2);
- if (phi_vuse2 != NULL_TREE && TREE_CODE (phi_vuse2) != SSA_NAME)
- phi_vuse2 = NULL_TREE;
-
- if (update_vops)
- {
- /* Find the vops at entry of bb1 and bb2. */
- phi_vuse1 = vop_at_entry (bb1);
-
- /* If both are not found, it means there's no need to update. Uses old
- dominator info. */
- if (phi_vuse1 == NULL_TREE && phi_vuse2 == NULL_TREE)
- update_vops = false;
- else if (phi_vuse1 == NULL_TREE)
- update_vops = dominated_by_p (CDI_DOMINATORS, bb1, bb2);
- else if (phi_vuse2 == NULL_TREE)
- update_vops = dominated_by_p (CDI_DOMINATORS, bb2, bb1);
- }
-
- if (phi_vuse1 && gimple_bb (SSA_NAME_DEF_STMT (phi_vuse1)) == bb1)
- {
- /* If the vop at entry of bb1 is a phi, save the phi alternatives in
- BB_VOP_AT_EXIT, before we lose that information by redirecting the
- edges. */
- FOR_EACH_EDGE (e, ei, bb1->preds)
- {
- arg = PHI_ARG_DEF_FROM_EDGE (SSA_NAME_DEF_STMT (phi_vuse1), e);
- BB_VOP_AT_EXIT (e->src) = arg;
- }
- vuse1_phi_args = true;
- }
+ gimple bb2_phi;
- /* Mark the basic block for later deletion. */
- delete_basic_block_same_succ (bb1);
+ bb2_phi = vop_phi (bb2);
- if (update_vops)
- redirected_edges = VEC_alloc (edge, heap, 10);
+ /* Mark the basic block as deleted. */
+ mark_basic_block_deleted (bb1);
/* Redirect the incoming edges of bb1 to bb2. */
for (i = EDGE_COUNT (bb1->preds); i > 0 ; --i)
@@ -1666,27 +1384,28 @@ replace_block_by (basic_block bb1, basic_block bb2, bool update_vops)
pred_edge = EDGE_PRED (bb1, i - 1);
pred_edge = redirect_edge_and_branch (pred_edge, bb2);
gcc_assert (pred_edge != NULL);
- if (update_vops)
- VEC_safe_push (edge, heap, redirected_edges, pred_edge);
- else if (phi_vuse2 && gimple_bb (SSA_NAME_DEF_STMT (phi_vuse2)) == bb2)
- add_phi_arg (SSA_NAME_DEF_STMT (phi_vuse2), SSA_NAME_VAR (phi_vuse2),
- pred_edge, UNKNOWN_LOCATION);
+
+ if (bb2_phi == NULL)
+ continue;
+
+ /* The phi might have run out of capacity when the redirect added an
+ argument, which means it could have been replaced. Refresh it. */
+ bb2_phi = vop_phi (bb2);
+
+ add_phi_arg (bb2_phi, SSA_NAME_VAR (gimple_phi_result (bb2_phi)),
+ pred_edge, UNKNOWN_LOCATION);
}
+ bb2->frequency += bb1->frequency;
+ if (bb2->frequency > BB_FREQ_MAX)
+ bb2->frequency = BB_FREQ_MAX;
+ bb1->frequency = 0;
+
/* Do updates that use bb1, before deleting bb1. */
- if (!update_vops)
- release_last_vdef (bb1);
+ release_last_vdef (bb1);
same_succ_flush_bb (bb1);
- delete_block_update_dominator_info (bb1, bb2);
-
- /* Update the vops. Uses new dominator info. */
- if (update_vops)
- {
- update_vuses (vuse1_phi_args, phi_vuse1, phi_vuse2, bb2,
- redirected_edges);
- VEC_free (edge, heap, redirected_edges);
- }
+ delete_basic_block (bb1);
}
/* Bbs for which update_debug_stmt need to be called. */
@@ -1694,10 +1413,10 @@ replace_block_by (basic_block bb1, basic_block bb2, bool update_vops)
static bitmap update_bbs;
/* For each cluster in all_clusters, merge all cluster->bbs. Returns
- number of bbs removed. Insert vop phis if UPDATE_VOPS. */
+ number of bbs removed. */
static int
-apply_clusters (bool update_vops)
+apply_clusters (void)
{
basic_block bb1, bb2;
bb_cluster c;
@@ -1720,7 +1439,7 @@ apply_clusters (bool update_vops)
bb1 = BASIC_BLOCK (j);
bitmap_clear_bit (update_bbs, bb1->index);
- replace_block_by (bb1, bb2, update_vops);
+ replace_block_by (bb1, bb2);
nr_bbs_removed++;
}
}
@@ -1772,9 +1491,6 @@ update_debug_stmts (void)
bitmap_iterator bi;
unsigned int i;
- if (!MAY_HAVE_DEBUG_STMTS)
- return;
-
EXECUTE_IF_SET_IN_BITMAP (update_bbs, 0, i, bi)
{
gimple stmt;
@@ -1800,7 +1516,6 @@ tail_merge_optimize (unsigned int todo)
int nr_bbs_removed;
bool loop_entered = false;
int iteration_nr = 0;
- bool update_vops = !symbol_marked_for_renaming (gimple_vop (cfun));
int max_iterations = PARAM_VALUE (PARAM_MAX_TAIL_MERGE_ITERATIONS);
if (!flag_tree_tail_merge || max_iterations == 0)
@@ -1831,16 +1546,17 @@ tail_merge_optimize (unsigned int todo)
if (VEC_empty (bb_cluster, all_clusters))
break;
- nr_bbs_removed = apply_clusters (update_vops);
+ nr_bbs_removed = apply_clusters ();
nr_bbs_removed_total += nr_bbs_removed;
if (nr_bbs_removed == 0)
break;
- purge_bbs ();
+ free_dominance_info (CDI_DOMINATORS);
if (iteration_nr == max_iterations)
break;
+ calculate_dominance_info (CDI_DOMINATORS);
update_worklist ();
}
@@ -1850,7 +1566,11 @@ tail_merge_optimize (unsigned int todo)
if (nr_bbs_removed_total > 0)
{
- update_debug_stmts ();
+ if (MAY_HAVE_DEBUG_STMTS)
+ {
+ calculate_dominance_info (CDI_DOMINATORS);
+ update_debug_stmts ();
+ }
if (dump_file && (dump_flags & TDF_DETAILS))
{
@@ -1860,6 +1580,7 @@ tail_merge_optimize (unsigned int todo)
todo |= (TODO_verify_ssa | TODO_verify_stmts | TODO_verify_flow
| TODO_dump_func);
+ mark_sym_for_renaming (gimple_vop (cfun));
}
delete_worklist ();