/* Generic SSA value propagation engine.
- Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
Contributed by Diego Novillo <dnovillo@redhat.com>
This file is part of GCC.
simulate_stmt (stmt);
}
- /* We can not predict when abnormal edges will be executed, so
+ /* We can not predict when abnormal and EH edges will be executed, so
once a block is considered executable, we consider any
outgoing abnormal edges as executable.
+ TODO: This is not exactly true. Simplifying statement might
+ prove it non-throwing and also computed goto can be handled
+ when destination is known.
+
At the same time, if this block has only one successor that is
reached by non-abnormal edges, then add that successor to the
worklist. */
normal_edge = NULL;
FOR_EACH_EDGE (e, ei, block->succs)
{
- if (e->flags & EDGE_ABNORMAL)
+ if (e->flags & (EDGE_ABNORMAL | EDGE_EH))
add_control_edge (e);
else
{
edge e;
edge_iterator ei;
basic_block bb;
- size_t i;
/* Worklists of SSA edges. */
interesting_ssa_edges = VEC_alloc (gimple, gc, 20);
cfg_blocks = VEC_alloc (basic_block, heap, 20);
VEC_safe_grow (basic_block, heap, cfg_blocks, 20);
- /* Initialize the values for every SSA_NAME. */
- for (i = 1; i < num_ssa_names; i++)
- if (ssa_name (i))
- SSA_NAME_VALUE (ssa_name (i)) = NULL_TREE;
-
/* Initially assume that every edge in the CFG is not executable.
(including the edges coming out of ENTRY_BLOCK_PTR). */
FOR_ALL_BB (bb)
new_stmt = gimple_build_call_vec (fn, args);
gimple_call_set_lhs (new_stmt, lhs);
- copy_virtual_operands (new_stmt, stmt);
move_ssa_defining_stmt_for_defs (new_stmt, stmt);
+ gimple_set_vuse (new_stmt, gimple_vuse (stmt));
+ gimple_set_vdef (new_stmt, gimple_vdef (stmt));
gimple_set_location (new_stmt, gimple_location (stmt));
gsi_replace (si_p, new_stmt, false);
VEC_free (tree, heap, args);
Introduce a new GIMPLE_ASSIGN statement. */
STRIP_USELESS_TYPE_CONVERSION (expr);
new_stmt = gimple_build_assign (lhs, expr);
- copy_virtual_operands (new_stmt, stmt);
move_ssa_defining_stmt_for_defs (new_stmt, stmt);
+ gimple_set_vuse (new_stmt, gimple_vuse (stmt));
+ gimple_set_vdef (new_stmt, gimple_vdef (stmt));
}
else if (!TREE_SIDE_EFFECTS (expr))
{
/* No value is expected, and EXPR has no effect.
Replace it with an empty statement. */
new_stmt = gimple_build_nop ();
+ unlink_stmt_vdef (stmt);
+ release_defs (stmt);
}
else
{
add_referenced_var (lhs);
lhs = make_ssa_name (lhs, new_stmt);
gimple_assign_set_lhs (new_stmt, lhs);
- copy_virtual_operands (new_stmt, stmt);
+ gimple_set_vuse (new_stmt, gimple_vuse (stmt));
+ gimple_set_vdef (new_stmt, gimple_vdef (stmt));
move_ssa_defining_stmt_for_defs (new_stmt, stmt);
}
gimple_set_location (new_stmt, gimple_location (stmt));
}
-/* Return true if STMT is of the form 'LHS = mem_ref', where 'mem_ref'
- is a non-volatile pointer dereference, a structure reference or a
- reference to a single _DECL. Ignore volatile memory references
- because they are not interesting for the optimizers. */
-
-bool
-stmt_makes_single_load (gimple stmt)
-{
- tree rhs;
-
- if (gimple_code (stmt) != GIMPLE_ASSIGN)
- return false;
-
- /* Only a GIMPLE_SINGLE_RHS assignment may have a
- declaration or reference as its RHS. */
- if (get_gimple_rhs_class (gimple_assign_rhs_code (stmt))
- != GIMPLE_SINGLE_RHS)
- return false;
-
- if (ZERO_SSA_OPERANDS (stmt, SSA_OP_VDEF|SSA_OP_VUSE))
- return false;
-
- rhs = gimple_assign_rhs1 (stmt);
-
- return (!TREE_THIS_VOLATILE (rhs)
- && (DECL_P (rhs)
- || REFERENCE_CLASS_P (rhs)));
-}
-
-
/* Return true if STMT is of the form 'mem_ref = RHS', where 'mem_ref'
is a non-volatile pointer dereference, a structure reference or a
reference to a single _DECL. Ignore volatile memory references
&& gimple_code (stmt) != GIMPLE_CALL)
return false;
- if (ZERO_SSA_OPERANDS (stmt, SSA_OP_VDEF))
+ if (!gimple_vdef (stmt))
return false;
lhs = gimple_get_lhs (stmt);
{
bool did_replace;
gimple stmt = gsi_stmt (i);
+ gimple old_stmt;
enum gimple_code code = gimple_code (stmt);
/* Ignore ASSERT_EXPRs. They are used by VRP to generate
continue;
}
- /* Record the state of the statement before replacements. */
- push_stmt_changes (gsi_stmt_ptr (&i));
-
/* Replace the statement with its folded version and mark it
folded. */
did_replace = false;
&& !did_replace)
did_replace |= replace_uses_in (stmt, prop_value);
- /* If we made a replacement, fold and cleanup the statement. */
+ /* If we made a replacement, fold the statement. */
+
+ old_stmt = stmt;
if (did_replace)
- {
- gimple old_stmt = stmt;
+ fold_stmt (&i);
- fold_stmt (&i);
+ /* Some statements may be simplified using ranges. For
+ example, division may be replaced by shifts, modulo
+ replaced with bitwise and, etc. Do this after
+ substituting constants, folding, etc so that we're
+ presented with a fully propagated, canonicalized
+ statement. */
+ if (use_ranges_p)
+ did_replace |= simplify_stmt_using_ranges (&i);
+
+ /* Now cleanup. */
+ if (did_replace)
+ {
stmt = gsi_stmt (i);
/* If we cleaned up EH information from the statement,
}
/* Determine what needs to be done to update the SSA form. */
- pop_stmt_changes (gsi_stmt_ptr (&i));
+ update_stmt (stmt);
something_changed = true;
}
- else
- {
- /* The statement was not modified, discard the change buffer. */
- discard_stmt_changes (gsi_stmt_ptr (&i));
- }
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "Not folded\n");
}
- /* Some statements may be simplified using ranges. For
- example, division may be replaced by shifts, modulo
- replaced with bitwise and, etc. Do this after
- substituting constants, folding, etc so that we're
- presented with a fully propagated, canonicalized
- statement. */
- if (use_ranges_p)
- simplify_stmt_using_ranges (stmt);
-
gsi_prev (&i);
}
}