Commit 6aa4c5b6 by Richard Biener Committed by Richard Biener

tree-ssa-pre.c (eliminate_dom_walker::before_dom_children): Rewrite to propagate…

tree-ssa-pre.c (eliminate_dom_walker::before_dom_children): Rewrite to propagate the VN result into all uses where possible and to remove...

2014-06-13  Richard Biener  <rguenther@suse.de>

	* tree-ssa-pre.c (eliminate_dom_walker::before_dom_children):
	Rewrite to propagate the VN result into all uses where
	possible and to remove stmts becoming dead because of that.
	(eliminate): Generalize stmt removal handling, remove in
	reverse dominator order to support proper debug stmt
	generation.  Update stmts before removing stmts.
	* tree-ssa-propagate.c (propagate_tree_value): Remove
	bogus assert.

	* c-c++-common/pr46562-2.c: Adjust.
	* g++.dg/tree-ssa/pr8781.C: Likewise.
	* gcc.dg/tree-ssa/ssa-fre-24.c: Likewise.
	* gcc.dg/tree-ssa/ssa-fre-25.c: Likewise.
	* gcc.dg/tree-ssa/ssa-fre-32.c: Likewise.
	* gcc.dg/tree-ssa/ssa-fre-39.c: Likewise.
	* gcc.dg/tree-ssa/ssa-pre-16.c: Likewise.

From-SVN: r211625
parent 80298c3b
2014-06-13 Richard Biener <rguenther@suse.de>
* tree-ssa-pre.c (eliminate_dom_walker::before_dom_children):
Rewrite to propagate the VN result into all uses where
possible and to remove stmts becoming dead because of that.
(eliminate): Generalize stmt removal handling, remove in
reverse dominator order to support proper debug stmt
generation. Update stmts before removing stmts.
* tree-ssa-propagate.c (propagate_tree_value): Remove
bogus assert.
2014-06-13 Thomas Preud'homme <thomas.preudhomme@arm.com>
PR tree-optimization/61375
......
2014-06-13 Richard Biener <rguenther@suse.de>
* c-c++-common/pr46562-2.c: Adjust.
* g++.dg/tree-ssa/pr8781.C: Likewise.
* gcc.dg/tree-ssa/ssa-fre-24.c: Likewise.
* gcc.dg/tree-ssa/ssa-fre-25.c: Likewise.
* gcc.dg/tree-ssa/ssa-fre-32.c: Likewise.
* gcc.dg/tree-ssa/ssa-fre-39.c: Likewise.
* gcc.dg/tree-ssa/ssa-pre-16.c: Likewise.
2014-06-13 Thomas Preud'homme <thomas.preudhomme@arm.com>
PR tree-optimization/61375
......
......@@ -9,5 +9,5 @@ int foo(void)
return *p;
}
/* { dg-final { scan-tree-dump "= 0;" "fre1" } } */
/* { dg-final { scan-tree-dump "return 0;" "fre1" } } */
/* { dg-final { cleanup-tree-dump "fre1" } } */
/* { dg-do compile } */
/* { dg-options "-O -fno-tree-sra -fdump-tree-fre1-details" } */
/* { dg-options "-O -fno-tree-sra -fdump-tree-fre1" } */
int f();
......@@ -24,5 +24,5 @@ int x()
/* We should optimize this to a direct call. */
/* { dg-final { scan-tree-dump "converting indirect call to function int f()" "fre1" } } */
/* { dg-final { scan-tree-dump-times "= f \\(\\);" 1 "fre1" } } */
/* { dg-final { cleanup-tree-dump "fre1" } } */
......@@ -30,5 +30,5 @@ int bazzoo (void)
return b.i;
}
/* { dg-final { scan-tree-dump-times "= 0;" 5 "fre1" } } */
/* { dg-final { scan-tree-dump-times "return 0;" 4 "fre1" } } */
/* { dg-final { cleanup-tree-dump "fre1" } } */
......@@ -14,5 +14,5 @@ int foo (struct X *p)
/* We should optimize this to return 0. */
/* { dg-final { scan-tree-dump "= 0;" "fre1" } } */
/* { dg-final { scan-tree-dump "return 0;" "fre1" } } */
/* { dg-final { cleanup-tree-dump "fre1" } } */
......@@ -23,6 +23,6 @@ bar (_Complex float x)
return z;
}
/* We should CSE all the way to replace the final assignment to z with x. */
/* { dg-final { scan-tree-dump-times "with x_1\\\(D\\\) in z" 3 "fre1" } } */
/* We should CSE all the way to replace the return value with x. */
/* { dg-final { scan-tree-dump-times "return x_\\d\+\\(D\\);" 2 "fre1" } } */
/* { dg-final { cleanup-tree-dump "fre1" } } */
......@@ -15,5 +15,5 @@ int foo (int i)
/* We should be able to value-number the final assignment to k to 1. */
/* { dg-final { scan-tree-dump "k_. = 1;" "fre1" } } */
/* { dg-final { scan-tree-dump "return 1;" "fre1" } } */
/* { dg-final { cleanup-tree-dump "fre1" } } */
......@@ -11,5 +11,5 @@ int foo(int k, int *x)
} while (++j<k);
return res;
}
/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre"} } */
/* { dg-final { scan-tree-dump-times "Eliminated: 2" 1 "pre"} } */
/* { dg-final { cleanup-tree-dump "pre" } } */
......@@ -4012,46 +4012,25 @@ eliminate_dom_walker::before_dom_children (basic_block b)
/* Mark new bb. */
el_avail_stack.safe_push (NULL_TREE);
/* If this block is not reachable do nothing. */
edge_iterator ei;
edge e;
FOR_EACH_EDGE (e, ei, b->preds)
if (e->flags & EDGE_EXECUTABLE)
break;
if (!e)
return;
/* ??? If we do nothing for unreachable blocks then this will confuse
tailmerging. Eventually we can reduce its reliance on SCCVN now
that we fully copy/constant-propagate (most) things. */
for (gsi = gsi_start_phis (b); !gsi_end_p (gsi);)
{
gimple stmt, phi = gsi_stmt (gsi);
tree sprime = NULL_TREE, res = PHI_RESULT (phi);
gimple_stmt_iterator gsi2;
gimple phi = gsi_stmt (gsi);
tree res = PHI_RESULT (phi);
/* We want to perform redundant PHI elimination. Do so by
replacing the PHI with a single copy if possible.
Do not touch inserted, single-argument or virtual PHIs. */
if (gimple_phi_num_args (phi) == 1
|| virtual_operand_p (res))
if (virtual_operand_p (res))
{
gsi_next (&gsi);
continue;
}
sprime = eliminate_avail (res);
if (!sprime
|| sprime == res)
{
eliminate_push_avail (res);
gsi_next (&gsi);
continue;
}
else if (is_gimple_min_invariant (sprime))
tree sprime = eliminate_avail (res);
if (sprime
&& sprime != res)
{
if (!useless_type_conversion_p (TREE_TYPE (res),
TREE_TYPE (sprime)))
sprime = fold_convert (TREE_TYPE (res), sprime);
}
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "Replaced redundant PHI node defining ");
......@@ -4061,6 +4040,23 @@ eliminate_dom_walker::before_dom_children (basic_block b)
fprintf (dump_file, "\n");
}
/* If we inserted this PHI node ourself, it's not an elimination. */
if (inserted_exprs
&& bitmap_bit_p (inserted_exprs, SSA_NAME_VERSION (res)))
pre_stats.phis--;
else
pre_stats.eliminations++;
/* If we will propagate into all uses don't bother to do
anything. */
if (may_propagate_copy (res, sprime))
{
/* Mark the PHI for removal. */
el_to_remove.safe_push (phi);
gsi_next (&gsi);
continue;
}
remove_phi_node (&gsi, false);
if (inserted_exprs
......@@ -4070,62 +4066,39 @@ eliminate_dom_walker::before_dom_children (basic_block b)
if (!useless_type_conversion_p (TREE_TYPE (res), TREE_TYPE (sprime)))
sprime = fold_convert (TREE_TYPE (res), sprime);
stmt = gimple_build_assign (res, sprime);
gimple stmt = gimple_build_assign (res, sprime);
/* ??? It cannot yet be necessary (DOM walk). */
gimple_set_plf (stmt, NECESSARY, gimple_plf (phi, NECESSARY));
gsi2 = gsi_after_labels (b);
gimple_stmt_iterator gsi2 = gsi_after_labels (b);
gsi_insert_before (&gsi2, stmt, GSI_NEW_STMT);
/* Queue the copy for eventual removal. */
el_to_remove.safe_push (stmt);
/* If we inserted this PHI node ourself, it's not an elimination. */
if (inserted_exprs
&& bitmap_bit_p (inserted_exprs, SSA_NAME_VERSION (res)))
pre_stats.phis--;
else
pre_stats.eliminations++;
continue;
}
eliminate_push_avail (res);
gsi_next (&gsi);
}
for (gsi = gsi_start_bb (b); !gsi_end_p (gsi); gsi_next (&gsi))
{
tree lhs = NULL_TREE;
tree rhs = NULL_TREE;
tree sprime = NULL_TREE;
stmt = gsi_stmt (gsi);
if (gimple_has_lhs (stmt))
lhs = gimple_get_lhs (stmt);
if (gimple_assign_single_p (stmt))
rhs = gimple_assign_rhs1 (stmt);
/* Lookup the RHS of the expression, see if we have an
available computation for it. If so, replace the RHS with
the available computation. */
if (gimple_has_lhs (stmt)
&& TREE_CODE (lhs) == SSA_NAME
&& !gimple_has_volatile_ops (stmt))
{
tree sprime;
gimple orig_stmt = stmt;
sprime = eliminate_avail (lhs);
/* If there is no usable leader mark lhs as leader for its value. */
if (!sprime)
eliminate_push_avail (lhs);
tree lhs = gimple_get_lhs (stmt);
if (lhs && TREE_CODE (lhs) == SSA_NAME
&& !gimple_has_volatile_ops (stmt)
/* See PR43491. Do not replace a global register variable when
it is a the RHS of an assignment. Do replace local register
variables since gcc does not guarantee a local variable will
be allocated in register.
Do not perform copy propagation or undo constant propagation. */
if (gimple_assign_single_p (stmt)
&& (TREE_CODE (rhs) == SSA_NAME
|| is_gimple_min_invariant (rhs)
|| (TREE_CODE (rhs) == VAR_DECL
&& is_global_var (rhs)
&& DECL_HARD_REGISTER (rhs))))
continue;
??? The fix isn't effective here. This should instead
be ensured by not value-numbering them the same but treating
them like volatiles? */
&& !(gimple_assign_single_p (stmt)
&& (TREE_CODE (gimple_assign_rhs1 (stmt)) == VAR_DECL
&& DECL_HARD_REGISTER (gimple_assign_rhs1 (stmt))
&& is_global_var (gimple_assign_rhs1 (stmt)))))
{
sprime = eliminate_avail (lhs);
if (!sprime)
{
/* If there is no existing usable leader but SCCVN thinks
......@@ -4139,73 +4112,52 @@ eliminate_dom_walker::before_dom_children (basic_block b)
&& (sprime = eliminate_insert (&gsi, val)) != NULL_TREE)
eliminate_push_avail (sprime);
}
else if (is_gimple_min_invariant (sprime))
{
/* If there is no existing leader but SCCVN knows this
value is constant, use that constant. */
if (!useless_type_conversion_p (TREE_TYPE (lhs),
TREE_TYPE (sprime)))
sprime = fold_convert (TREE_TYPE (lhs), sprime);
if (dump_file && (dump_flags & TDF_DETAILS))
/* If this now constitutes a copy duplicate points-to
and range info appropriately. This is especially
important for inserted code. See tree-ssa-copy.c
for similar code. */
if (sprime
&& TREE_CODE (sprime) == SSA_NAME)
{
fprintf (dump_file, "Replaced ");
print_gimple_expr (dump_file, stmt, 0, 0);
fprintf (dump_file, " with ");
print_generic_expr (dump_file, sprime, 0);
fprintf (dump_file, " in ");
print_gimple_stmt (dump_file, stmt, 0, 0);
}
pre_stats.eliminations++;
tree vdef = gimple_vdef (stmt);
tree vuse = gimple_vuse (stmt);
propagate_tree_value_into_stmt (&gsi, sprime);
stmt = gsi_stmt (gsi);
update_stmt (stmt);
if (vdef != gimple_vdef (stmt))
VN_INFO (vdef)->valnum = vuse;
/* If we removed EH side-effects from the statement, clean
its EH information. */
if (maybe_clean_or_replace_eh_stmt (orig_stmt, stmt))
basic_block sprime_b = gimple_bb (SSA_NAME_DEF_STMT (sprime));
if (POINTER_TYPE_P (TREE_TYPE (lhs))
&& SSA_NAME_PTR_INFO (lhs)
&& !SSA_NAME_PTR_INFO (sprime))
{
bitmap_set_bit (need_eh_cleanup,
gimple_bb (stmt)->index);
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, " Removed EH side-effects.\n");
duplicate_ssa_name_ptr_info (sprime,
SSA_NAME_PTR_INFO (lhs));
if (b != sprime_b)
mark_ptr_info_alignment_unknown
(SSA_NAME_PTR_INFO (sprime));
}
continue;
else if (!POINTER_TYPE_P (TREE_TYPE (lhs))
&& SSA_NAME_RANGE_INFO (lhs)
&& !SSA_NAME_RANGE_INFO (sprime)
&& b == sprime_b)
duplicate_ssa_name_range_info (sprime,
SSA_NAME_RANGE_TYPE (lhs),
SSA_NAME_RANGE_INFO (lhs));
}
if (sprime
&& sprime != lhs
&& (rhs == NULL_TREE
|| TREE_CODE (rhs) != SSA_NAME
|| may_propagate_copy (rhs, sprime)))
{
bool can_make_abnormal_goto
= is_gimple_call (stmt)
&& stmt_can_make_abnormal_goto (stmt);
gcc_assert (sprime != rhs);
/* Inhibit the use of an inserted PHI on a loop header when
the address of the memory reference is a simple induction
variable. In other cases the vectorizer won't do anything
anyway (either it's loop invariant or a complicated
expression). */
if (do_pre
&& flag_tree_loop_vectorize
&& gimple_assign_single_p (stmt)
if (sprime
&& TREE_CODE (sprime) == SSA_NAME
&& loop_outer (b->loop_father))
&& do_pre
&& flag_tree_loop_vectorize
&& loop_outer (b->loop_father)
&& has_zero_uses (sprime)
&& bitmap_bit_p (inserted_exprs, SSA_NAME_VERSION (sprime))
&& gimple_assign_load_p (stmt))
{
gimple def_stmt = SSA_NAME_DEF_STMT (sprime);
basic_block def_bb = gimple_bb (def_stmt);
if (gimple_code (def_stmt) == GIMPLE_PHI
&& b->loop_father->header == def_bb
&& has_zero_uses (sprime))
&& b->loop_father->header == def_bb)
{
ssa_op_iter iter;
tree op;
......@@ -4215,8 +4167,7 @@ eliminate_dom_walker::before_dom_children (basic_block b)
affine_iv iv;
def_bb = gimple_bb (SSA_NAME_DEF_STMT (op));
if (def_bb
&& flow_bb_inside_loop_p (b->loop_father,
def_bb)
&& flow_bb_inside_loop_p (b->loop_father, def_bb)
&& simple_iv (b->loop_father,
b->loop_father, op, &iv, true))
{
......@@ -4236,11 +4187,54 @@ eliminate_dom_walker::before_dom_children (basic_block b)
" carried dependence to loop %d\n",
b->loop_father->num);
}
continue;
/* Don't keep sprime available. */
eliminate_push_avail (lhs);
sprime = NULL_TREE;
}
}
}
if (sprime)
{
/* If we can propagate the value computed for LHS into
all uses don't bother doing anything with this stmt. */
if (may_propagate_copy (lhs, sprime))
{
/* Mark it for removal. */
el_to_remove.safe_push (stmt);
/* ??? Don't count copy/constant propagations. */
if (gimple_assign_single_p (stmt)
&& (TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME
|| gimple_assign_rhs1 (stmt) == sprime))
continue;
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "Replaced ");
print_gimple_expr (dump_file, stmt, 0, 0);
fprintf (dump_file, " with ");
print_generic_expr (dump_file, sprime, 0);
fprintf (dump_file, " in all uses of ");
print_gimple_stmt (dump_file, stmt, 0, 0);
}
pre_stats.eliminations++;
continue;
}
/* If this is an assignment from our leader (which
happens in the case the value-number is a constant)
then there is nothing to do. */
if (gimple_assign_single_p (stmt)
&& sprime == gimple_assign_rhs1 (stmt))
continue;
/* Else replace its RHS. */
bool can_make_abnormal_goto
= is_gimple_call (stmt)
&& stmt_can_make_abnormal_goto (stmt);
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "Replaced ");
......@@ -4254,16 +4248,12 @@ eliminate_dom_walker::before_dom_children (basic_block b)
if (TREE_CODE (sprime) == SSA_NAME)
gimple_set_plf (SSA_NAME_DEF_STMT (sprime),
NECESSARY, true);
/* We need to make sure the new and old types actually match,
which may require adding a simple cast, which fold_convert
will do for us. */
if ((!rhs || TREE_CODE (rhs) != SSA_NAME)
&& !useless_type_conversion_p (gimple_expr_type (stmt),
TREE_TYPE (sprime)))
sprime = fold_convert (gimple_expr_type (stmt), sprime);
pre_stats.eliminations++;
gimple orig_stmt = stmt;
if (!useless_type_conversion_p (TREE_TYPE (lhs),
TREE_TYPE (sprime)))
sprime = fold_convert (TREE_TYPE (lhs), sprime);
tree vdef = gimple_vdef (stmt);
tree vuse = gimple_vuse (stmt);
propagate_tree_value_into_stmt (&gsi, sprime);
......@@ -4291,18 +4281,22 @@ eliminate_dom_walker::before_dom_children (basic_block b)
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, " Removed AB side-effects.\n");
}
continue;
}
}
/* If the statement is a scalar store, see if the expression
has the same value number as its rhs. If so, the store is
dead. */
else if (gimple_assign_single_p (stmt)
if (gimple_assign_single_p (stmt)
&& !gimple_has_volatile_ops (stmt)
&& !is_gimple_reg (gimple_assign_lhs (stmt))
&& (TREE_CODE (rhs) == SSA_NAME
|| is_gimple_min_invariant (rhs)))
&& (TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME
|| is_gimple_min_invariant (gimple_assign_rhs1 (stmt))))
{
tree val;
tree rhs = gimple_assign_rhs1 (stmt);
val = vn_reference_lookup (gimple_assign_lhs (stmt),
gimple_vuse (stmt), VN_WALK, NULL);
if (TREE_CODE (rhs) == SSA_NAME)
......@@ -4318,94 +4312,113 @@ eliminate_dom_walker::before_dom_children (basic_block b)
/* Queue stmt for removal. */
el_to_remove.safe_push (stmt);
continue;
}
}
/* Visit COND_EXPRs and fold the comparison with the
available value-numbers. */
else if (gimple_code (stmt) == GIMPLE_COND)
{
tree op0 = gimple_cond_lhs (stmt);
tree op1 = gimple_cond_rhs (stmt);
tree result;
if (TREE_CODE (op0) == SSA_NAME)
op0 = VN_INFO (op0)->valnum;
if (TREE_CODE (op1) == SSA_NAME)
op1 = VN_INFO (op1)->valnum;
result = fold_binary (gimple_cond_code (stmt), boolean_type_node,
op0, op1);
if (result && TREE_CODE (result) == INTEGER_CST)
bool can_make_abnormal_goto = stmt_can_make_abnormal_goto (stmt);
bool was_noreturn = (is_gimple_call (stmt)
&& gimple_call_noreturn_p (stmt));
tree vdef = gimple_vdef (stmt);
tree vuse = gimple_vuse (stmt);
/* If we didn't replace the whole stmt (or propagate the result
into all uses), replace all uses on this stmt with their
leaders. */
use_operand_p use_p;
ssa_op_iter iter;
FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE)
{
if (integer_zerop (result))
gimple_cond_make_false (stmt);
else
gimple_cond_make_true (stmt);
update_stmt (stmt);
el_todo = TODO_cleanup_cfg;
tree use = USE_FROM_PTR (use_p);
/* ??? The call code above leaves stmt operands un-updated. */
if (TREE_CODE (use) != SSA_NAME)
continue;
tree sprime = eliminate_avail (use);
if (sprime && sprime != use
&& may_propagate_copy (use, sprime)
/* We substitute into debug stmts to avoid excessive
debug temporaries created by removed stmts, but we need
to avoid doing so for inserted sprimes as we never want
to create debug temporaries for them. */
&& (!inserted_exprs
|| TREE_CODE (sprime) != SSA_NAME
|| !is_gimple_debug (stmt)
|| !bitmap_bit_p (inserted_exprs, SSA_NAME_VERSION (sprime))))
{
propagate_value (use_p, sprime);
gimple_set_modified (stmt, true);
if (TREE_CODE (sprime) == SSA_NAME
&& !is_gimple_debug (stmt))
gimple_set_plf (SSA_NAME_DEF_STMT (sprime),
NECESSARY, true);
}
}
/* Visit indirect calls and turn them into direct calls if
possible. */
possible using the devirtualization machinery. */
if (is_gimple_call (stmt))
{
tree orig_fn = gimple_call_fn (stmt);
tree fn;
if (!orig_fn)
continue;
if (TREE_CODE (orig_fn) == SSA_NAME)
fn = VN_INFO (orig_fn)->valnum;
else if (TREE_CODE (orig_fn) == OBJ_TYPE_REF
&& TREE_CODE (OBJ_TYPE_REF_EXPR (orig_fn)) == SSA_NAME)
{
fn = VN_INFO (OBJ_TYPE_REF_EXPR (orig_fn))->valnum;
if (!gimple_call_addr_fndecl (fn))
tree fn = gimple_call_fn (stmt);
if (fn
&& TREE_CODE (fn) == OBJ_TYPE_REF
&& TREE_CODE (OBJ_TYPE_REF_EXPR (fn)) == SSA_NAME)
{
fn = ipa_intraprocedural_devirtualization (stmt);
if (fn)
fn = build_fold_addr_expr (fn);
}
}
else
continue;
if (gimple_call_addr_fndecl (fn) != NULL_TREE
&& useless_type_conversion_p (TREE_TYPE (orig_fn),
TREE_TYPE (fn))
&& dbg_cnt (devirt))
if (fn && dbg_cnt (devirt))
{
bool can_make_abnormal_goto
= stmt_can_make_abnormal_goto (stmt);
bool was_noreturn = gimple_call_noreturn_p (stmt);
if (dump_enabled_p ())
{
location_t loc = gimple_location (stmt);
dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
"converting indirect call to function %s\n",
cgraph_get_node (gimple_call_addr_fndecl (fn))->name ());
"converting indirect call to "
"function %s\n",
cgraph_get_node (fn)->name ());
}
gimple_call_set_fndecl (stmt, fn);
gimple_set_modified (stmt, true);
}
}
}
gimple_call_set_fn (stmt, fn);
tree vdef = gimple_vdef (stmt);
tree vuse = gimple_vuse (stmt);
update_stmt (stmt);
if (vdef != gimple_vdef (stmt))
VN_INFO (vdef)->valnum = vuse;
if (gimple_modified_p (stmt))
{
/* If a formerly non-invariant ADDR_EXPR is turned into an
invariant one it was on a separate stmt. */
if (gimple_assign_single_p (stmt)
&& TREE_CODE (gimple_assign_rhs1 (stmt)) == ADDR_EXPR)
recompute_tree_invariant_for_addr_expr (gimple_assign_rhs1 (stmt));
gimple old_stmt = stmt;
if (is_gimple_call (stmt))
{
/* ??? Only fold calls inplace for now, this may create new
SSA names which in turn will confuse free_scc_vn SSA name
release code. */
fold_stmt_inplace (&gsi);
/* When changing a call into a noreturn call, cfg cleanup
is needed to fix up the noreturn call. */
if (!was_noreturn && gimple_call_noreturn_p (stmt))
el_todo |= TODO_cleanup_cfg;
}
else
{
fold_stmt (&gsi);
stmt = gsi_stmt (gsi);
if ((gimple_code (stmt) == GIMPLE_COND
&& (gimple_cond_true_p (stmt)
|| gimple_cond_false_p (stmt)))
|| (gimple_code (stmt) == GIMPLE_SWITCH
&& TREE_CODE (gimple_switch_index (stmt)) == INTEGER_CST))
el_todo |= TODO_cleanup_cfg;
}
/* If we removed EH side-effects from the statement, clean
its EH information. */
if (maybe_clean_or_replace_eh_stmt (stmt, stmt))
if (maybe_clean_or_replace_eh_stmt (old_stmt, stmt))
{
bitmap_set_bit (need_eh_cleanup,
gimple_bb (stmt)->index);
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, " Removed EH side-effects.\n");
}
/* Likewise for AB side-effects. */
if (can_make_abnormal_goto
&& !stmt_can_make_abnormal_goto (stmt))
......@@ -4415,11 +4428,36 @@ eliminate_dom_walker::before_dom_children (basic_block b)
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, " Removed AB side-effects.\n");
}
update_stmt (stmt);
if (vdef != gimple_vdef (stmt))
VN_INFO (vdef)->valnum = vuse;
}
/* Make the new value available - for fully redundant LHS we
continue with the next stmt above. */
if (lhs && TREE_CODE (lhs) == SSA_NAME)
eliminate_push_avail (lhs);
}
/* Changing an indirect call to a direct call may
have exposed different semantics. This may
require an SSA update. */
el_todo |= TODO_update_ssa_only_virtuals;
/* Replace destination PHI arguments. */
edge_iterator ei;
edge e;
FOR_EACH_EDGE (e, ei, b->succs)
{
for (gsi = gsi_start_phis (e->dest); !gsi_end_p (gsi); gsi_next (&gsi))
{
gimple phi = gsi_stmt (gsi);
use_operand_p use_p = PHI_ARG_DEF_PTR_FROM_EDGE (phi, e);
tree arg = USE_FROM_PTR (use_p);
if (TREE_CODE (arg) != SSA_NAME
|| virtual_operand_p (arg))
continue;
tree sprime = eliminate_avail (arg);
if (sprime && may_propagate_copy (arg, sprime))
{
propagate_value (use_p, sprime);
if (TREE_CODE (sprime) == SSA_NAME)
gimple_set_plf (SSA_NAME_DEF_STMT (sprime), NECESSARY, true);
}
}
}
......@@ -4442,7 +4480,6 @@ eliminate (bool do_pre)
{
gimple_stmt_iterator gsi;
gimple stmt;
unsigned i;
need_eh_cleanup = BITMAP_ALLOC (NULL);
need_ab_cleanup = BITMAP_ALLOC (NULL);
......@@ -4460,41 +4497,37 @@ eliminate (bool do_pre)
/* We cannot remove stmts during BB walk, especially not release SSA
names there as this confuses the VN machinery. The stmts ending
up in el_to_remove are either stores or simple copies. */
FOR_EACH_VEC_ELT (el_to_remove, i, stmt)
up in el_to_remove are either stores or simple copies.
Remove stmts in reverse order to make debug stmt creation possible. */
while (!el_to_remove.is_empty ())
{
tree lhs = gimple_assign_lhs (stmt);
tree rhs = gimple_assign_rhs1 (stmt);
use_operand_p use_p;
gimple use_stmt;
stmt = el_to_remove.pop ();
/* If there is a single use only, propagate the equivalency
instead of keeping the copy. */
if (TREE_CODE (lhs) == SSA_NAME
&& TREE_CODE (rhs) == SSA_NAME
&& single_imm_use (lhs, &use_p, &use_stmt)
&& may_propagate_copy (USE_FROM_PTR (use_p), rhs))
if (dump_file && (dump_flags & TDF_DETAILS))
{
SET_USE (use_p, rhs);
update_stmt (use_stmt);
if (inserted_exprs
&& bitmap_bit_p (inserted_exprs, SSA_NAME_VERSION (lhs))
&& TREE_CODE (rhs) == SSA_NAME)
gimple_set_plf (SSA_NAME_DEF_STMT (rhs), NECESSARY, true);
fprintf (dump_file, "Removing dead stmt ");
print_gimple_stmt (dump_file, stmt, 0, 0);
}
/* If this is a store or a now unused copy, remove it. */
if (TREE_CODE (lhs) != SSA_NAME
|| has_zero_uses (lhs))
tree lhs;
if (gimple_code (stmt) == GIMPLE_PHI)
lhs = gimple_phi_result (stmt);
else
lhs = gimple_get_lhs (stmt);
if (inserted_exprs
&& TREE_CODE (lhs) == SSA_NAME)
bitmap_clear_bit (inserted_exprs, SSA_NAME_VERSION (lhs));
gsi = gsi_for_stmt (stmt);
if (gimple_code (stmt) == GIMPLE_PHI)
remove_phi_node (&gsi, true);
else
{
basic_block bb = gimple_bb (stmt);
gsi = gsi_for_stmt (stmt);
unlink_stmt_vdef (stmt);
if (gsi_remove (&gsi, true))
bitmap_set_bit (need_eh_cleanup, bb->index);
if (inserted_exprs
&& TREE_CODE (lhs) == SSA_NAME)
bitmap_clear_bit (inserted_exprs, SSA_NAME_VERSION (lhs));
release_defs (stmt);
}
}
......
......@@ -1410,11 +1410,6 @@ replace_exp (use_operand_p op_p, tree val)
void
propagate_tree_value (tree *op_p, tree val)
{
gcc_checking_assert (!(TREE_CODE (val) == SSA_NAME
&& *op_p
&& TREE_CODE (*op_p) == SSA_NAME
&& !may_propagate_copy (*op_p, val)));
if (TREE_CODE (val) == SSA_NAME)
*op_p = val;
else
......
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