re PR tree-optimization/51005 (-ftree-tail-merge slows down compilation of 20001226-1.c)
2011-11-15 Tom de Vries <tom@codesourcery.com> PR tree-optimization/51005 * tree-ssa-tail-merge.c (delete_basic_block_same_succ): Rename to mark_basic_block_deleted. (update_worklist): Inline purge_bbs. (purge_bbs, unlink_virtual_phi, update_vuses, vop_at_entry) (delete_block_update_dominator_info): Remove. (replace_block_by): Remove update_vops parameter. Partially evaluate for update_vops == false. (apply_clusters): Remove update_vops parameter. Remove update_vops argument in replace_block_by call. (update_debug_stmts): Remove MAY_HAVE_DEBUG_STMTS test. (tail_merge_optimize): Remove update_vops argument to apply_clusters. Remove call to purge_bbs. Add calls to calculate_dominance_info and free_dominance_info. Add MAY_HAVE_DEBUG_STMTS before calling update_debug_stmts. Mark vop var for renaming, if necessary. From-SVN: r181372
This commit is contained in:
parent
894a84b5ed
commit
643400b8c9
2 changed files with 52 additions and 318 deletions
|
@ -1,3 +1,21 @@
|
|||
2011-11-15 Tom de Vries <tom@codesourcery.com>
|
||||
|
||||
PR tree-optimization/51005
|
||||
* tree-ssa-tail-merge.c (delete_basic_block_same_succ): Rename to
|
||||
mark_basic_block_deleted.
|
||||
(update_worklist): Inline purge_bbs.
|
||||
(purge_bbs, unlink_virtual_phi, update_vuses, vop_at_entry)
|
||||
(delete_block_update_dominator_info): Remove.
|
||||
(replace_block_by): Remove update_vops parameter. Partially evaluate
|
||||
for update_vops == false.
|
||||
(apply_clusters): Remove update_vops parameter. Remove update_vops
|
||||
argument in replace_block_by call.
|
||||
(update_debug_stmts): Remove MAY_HAVE_DEBUG_STMTS test.
|
||||
(tail_merge_optimize): Remove update_vops argument to apply_clusters.
|
||||
Remove call to purge_bbs. Add calls to calculate_dominance_info and
|
||||
free_dominance_info. Add MAY_HAVE_DEBUG_STMTS before calling
|
||||
update_debug_stmts. Mark vop var for renaming, if necessary.
|
||||
|
||||
2011-11-15 Bernd Schmidt <bernds@codesourcery.com>
|
||||
|
||||
PR rtl-optimization/51051
|
||||
|
|
|
@ -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;
|
||||
gimple bb2_phi;
|
||||
|
||||
phi_vuse2 = vop_at_entry (bb2);
|
||||
if (phi_vuse2 != NULL_TREE && TREE_CODE (phi_vuse2) != SSA_NAME)
|
||||
phi_vuse2 = NULL_TREE;
|
||||
bb2_phi = vop_phi (bb2);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* Mark the basic block for later deletion. */
|
||||
delete_basic_block_same_succ (bb1);
|
||||
|
||||
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,23 @@ 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);
|
||||
}
|
||||
|
||||
/* 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 +1408,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 +1434,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 +1486,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 +1511,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 +1541,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 +1561,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 +1575,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 ();
|
||||
|
|
Loading…
Add table
Reference in a new issue