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:
parent
6c878b231d
commit
38965eb29c
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue