Commit 38965eb2 by Zdenek Dvorak Committed by Zdenek Dvorak

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
parent 6c878b23
2005-05-17 Zdenek Dvorak <dvorakz@suse.cz> 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. * cfgloop.h (just_once_each_iteration_p): Declaration changed.
* cfgloopanal.c (just_once_each_iteration_p): Make the loop argument * cfgloopanal.c (just_once_each_iteration_p): Make the loop argument
const. const.
......
...@@ -1261,6 +1261,7 @@ tree_can_merge_blocks_p (basic_block a, basic_block b) ...@@ -1261,6 +1261,7 @@ tree_can_merge_blocks_p (basic_block a, basic_block b)
{ {
tree stmt; tree stmt;
block_stmt_iterator bsi; block_stmt_iterator bsi;
tree phi;
if (!single_succ_p (a)) if (!single_succ_p (a))
return false; return false;
...@@ -1288,10 +1289,20 @@ tree_can_merge_blocks_p (basic_block a, basic_block b) ...@@ -1288,10 +1289,20 @@ tree_can_merge_blocks_p (basic_block a, basic_block b)
&& DECL_NONLOCAL (LABEL_EXPR_LABEL (stmt))) && DECL_NONLOCAL (LABEL_EXPR_LABEL (stmt)))
return false; return false;
/* There may be no PHI nodes at the start of B. */ /* It must be possible to eliminate all phi nodes in B. If ssa form
if (phi_nodes (b)) is not up-to-date, we cannot eliminate any phis. */
phi = phi_nodes (b);
if (phi)
{
if (need_ssa_update_p ())
return false; 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. */ /* Do not remove user labels. */
for (bsi = bsi_start (b); !bsi_end_p (bsi); bsi_next (&bsi)) 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) ...@@ -1310,6 +1321,55 @@ tree_can_merge_blocks_p (basic_block a, basic_block b)
return true; 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. */ /* Merge block B into block A. */
...@@ -1318,10 +1378,40 @@ tree_merge_blocks (basic_block a, basic_block b) ...@@ -1318,10 +1378,40 @@ tree_merge_blocks (basic_block a, basic_block b)
{ {
block_stmt_iterator bsi; block_stmt_iterator bsi;
tree_stmt_iterator last; tree_stmt_iterator last;
tree phi;
if (dump_file) if (dump_file)
fprintf (dump_file, "Merging blocks %d and %d\n", a->index, b->index); 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. */ /* Ensure that B follows A. */
move_block_after (b, a); move_block_after (b, a);
......
...@@ -630,6 +630,7 @@ void set_current_def (tree, tree); ...@@ -630,6 +630,7 @@ void set_current_def (tree, tree);
/* In tree-ssa-ccp.c */ /* In tree-ssa-ccp.c */
bool fold_stmt (tree *); bool fold_stmt (tree *);
bool fold_stmt_inplace (tree);
tree widen_bitfield (tree, tree, tree); tree widen_bitfield (tree, tree, tree);
/* In tree-vrp.c */ /* In tree-vrp.c */
......
...@@ -2308,6 +2308,32 @@ fold_stmt (tree *stmt_p) ...@@ -2308,6 +2308,32 @@ fold_stmt (tree *stmt_p)
return changed; 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 /* Convert EXPR into a GIMPLE value suitable for substitution on the
RHS of an assignment. Insert the necessary statements before RHS of an assignment. Insert the necessary statements before
......
...@@ -404,6 +404,7 @@ tree_ssa_dominator_optimize (void) ...@@ -404,6 +404,7 @@ tree_ssa_dominator_optimize (void)
/* Clean up the CFG so that any forwarder blocks created by loop /* Clean up the CFG so that any forwarder blocks created by loop
canonicalization are removed. */ canonicalization are removed. */
cleanup_tree_cfg (); cleanup_tree_cfg ();
calculate_dominance_info (CDI_DOMINATORS);
/* If we prove certain blocks are unreachable, then we want to /* If we prove certain blocks are unreachable, then we want to
repeat the dominator optimization process as PHI nodes may repeat the dominator optimization process as PHI nodes may
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment