tree-cfg.c (tree_can_merge_blocks_p): Allow phi nodes in the merged block.

* tree-cfg.c (tree_can_merge_blocks_p): Allow phi nodes in the
	merged block.
	(replace_uses_by): New function.
	(tree_merge_blocks): Eliminate the phi nodes in the merged block.
	* tree-flow.h (fold_stmt_inplace): Declare.
	* tree-ssa-ccp.c (fold_stmt_inplace): New function.
	* tree-ssa-dom.c (tree_ssa_dominator_optimize): Update dominance
	info after cfg cleanup.

From-SVN: r99850
This commit is contained in:
Zdenek Dvorak 2005-05-17 21:55:53 +02:00 committed by Zdenek Dvorak
parent 6c878b231d
commit 38965eb29c
5 changed files with 132 additions and 3 deletions

View File

@ -1,3 +1,14 @@
2005-05-17 Zdenek Dvorak <dvorakz@suse.cz>
* tree-cfg.c (tree_can_merge_blocks_p): Allow phi nodes in the
merged block.
(replace_uses_by): New function.
(tree_merge_blocks): Eliminate the phi nodes in the merged block.
* tree-flow.h (fold_stmt_inplace): Declare.
* tree-ssa-ccp.c (fold_stmt_inplace): New function.
* tree-ssa-dom.c (tree_ssa_dominator_optimize): Update dominance
info after cfg cleanup.
2005-05-17 Zdenek Dvorak <dvorakz@suse.cz>
* cfgloop.h (just_once_each_iteration_p): Declaration changed.

View File

@ -1261,6 +1261,7 @@ tree_can_merge_blocks_p (basic_block a, basic_block b)
{
tree stmt;
block_stmt_iterator bsi;
tree phi;
if (!single_succ_p (a))
return false;
@ -1288,9 +1289,19 @@ tree_can_merge_blocks_p (basic_block a, basic_block b)
&& DECL_NONLOCAL (LABEL_EXPR_LABEL (stmt)))
return false;
/* There may be no PHI nodes at the start of B. */
if (phi_nodes (b))
return false;
/* It must be possible to eliminate all phi nodes in B. If ssa form
is not up-to-date, we cannot eliminate any phis. */
phi = phi_nodes (b);
if (phi)
{
if (need_ssa_update_p ())
return false;
for (; phi; phi = PHI_CHAIN (phi))
if (!is_gimple_reg (PHI_RESULT (phi))
&& !may_propagate_copy (PHI_RESULT (phi), PHI_ARG_DEF (phi, 0)))
return false;
}
/* Do not remove user labels. */
for (bsi = bsi_start (b); !bsi_end_p (bsi); bsi_next (&bsi))
@ -1310,6 +1321,55 @@ tree_can_merge_blocks_p (basic_block a, basic_block b)
return true;
}
/* Replaces all uses of NAME by VAL. */
static void
replace_uses_by (tree name, tree val)
{
imm_use_iterator imm_iter;
use_operand_p use;
tree stmt;
edge e;
unsigned i;
VEC(tree,heap) *stmts = VEC_alloc (tree, heap, 20);
FOR_EACH_IMM_USE_SAFE (use, imm_iter, name)
{
stmt = USE_STMT (use);
SET_USE (use, val);
if (TREE_CODE (stmt) == PHI_NODE)
{
e = PHI_ARG_EDGE (stmt, PHI_ARG_INDEX_FROM_USE (use));
if (e->flags & EDGE_ABNORMAL)
{
/* This can only occur for virtual operands, since
for the real ones SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name))
would prevent replacement. */
gcc_assert (!is_gimple_reg (name));
SSA_NAME_OCCURS_IN_ABNORMAL_PHI (val) = 1;
}
}
else
VEC_safe_push (tree, heap, stmts, stmt);
}
/* We do not update the statements in the loop above. Consider
x = w * w;
If we performed the update in the first loop, the statement
would be rescanned after first occurence of w is replaced,
the new uses would be placed to the beginning of the list,
and we would never process them. */
for (i = 0; VEC_iterate (tree, stmts, i, stmt); i++)
{
fold_stmt_inplace (stmt);
update_stmt (stmt);
}
VEC_free (tree, heap, stmts);
}
/* Merge block B into block A. */
@ -1318,10 +1378,40 @@ tree_merge_blocks (basic_block a, basic_block b)
{
block_stmt_iterator bsi;
tree_stmt_iterator last;
tree phi;
if (dump_file)
fprintf (dump_file, "Merging blocks %d and %d\n", a->index, b->index);
/* Remove the phi nodes. */
bsi = bsi_last (a);
for (phi = phi_nodes (b); phi; phi = phi_nodes (b))
{
tree def = PHI_RESULT (phi), use = PHI_ARG_DEF (phi, 0);
tree copy;
if (!may_propagate_copy (def, use)
/* Propagating pointers might cause the set of vops for statements
to be changed, and thus require ssa form update. */
|| (is_gimple_reg (def)
&& POINTER_TYPE_P (TREE_TYPE (def))))
{
gcc_assert (is_gimple_reg (def));
/* Note that just emiting the copies is fine -- there is no problem
with ordering of phi nodes. This is because A is the single
predecessor of B, therefore results of the phi nodes cannot
appear as arguments of the phi nodes. */
copy = build2 (MODIFY_EXPR, void_type_node, def, use);
bsi_insert_after (&bsi, copy, BSI_NEW_STMT);
SET_PHI_RESULT (phi, NULL_TREE);
SSA_NAME_DEF_STMT (def) = copy;
}
else
replace_uses_by (def, use);
remove_phi_node (phi, NULL);
}
/* Ensure that B follows A. */
move_block_after (b, a);

View File

@ -630,6 +630,7 @@ void set_current_def (tree, tree);
/* In tree-ssa-ccp.c */
bool fold_stmt (tree *);
bool fold_stmt_inplace (tree);
tree widen_bitfield (tree, tree, tree);
/* In tree-vrp.c */

View File

@ -2308,6 +2308,32 @@ fold_stmt (tree *stmt_p)
return changed;
}
/* Perform the minimal folding on statement STMT. Only operations like
*&x created by constant propagation are handled. The statement cannot
be replaced with a new one. */
bool
fold_stmt_inplace (tree stmt)
{
tree old_stmt = stmt, rhs, new_rhs;
bool changed = false;
walk_tree (&stmt, fold_stmt_r, &changed, NULL);
gcc_assert (stmt == old_stmt);
rhs = get_rhs (stmt);
if (!rhs || rhs == stmt)
return changed;
new_rhs = fold (rhs);
if (new_rhs == rhs)
return changed;
changed |= set_rhs (&stmt, new_rhs);
gcc_assert (stmt == old_stmt);
return changed;
}
/* Convert EXPR into a GIMPLE value suitable for substitution on the
RHS of an assignment. Insert the necessary statements before

View File

@ -404,6 +404,7 @@ tree_ssa_dominator_optimize (void)
/* Clean up the CFG so that any forwarder blocks created by loop
canonicalization are removed. */
cleanup_tree_cfg ();
calculate_dominance_info (CDI_DOMINATORS);
/* If we prove certain blocks are unreachable, then we want to
repeat the dominator optimization process as PHI nodes may