set_livein_block (sym, bb);
set_rewrite_uses (stmt, true);
}
-
+
/* Now process the defs. Mark BB as the definition block and add
each def to the set of killed symbols. */
FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_DEF)
then for each of them find the nearest def that dominates them. If this
def is a phi node, we mark it live, and if it was not live before, we
add the predecessors of its basic block to the worklist.
-
+
To quickly locate the nearest def that dominates use, we use dfs numbering
of the dominance tree (that is already available in order to speed up
queries). For each def, we have the interval given by the dfs number on
else
{
tree tracked_var;
+
gcc_assert (DECL_P (var));
phi = create_phi_node (var, bb);
- if (!update_p && (tracked_var = target_for_debug_bind (var)))
+
+ tracked_var = target_for_debug_bind (var);
+ if (tracked_var)
{
gimple note = gimple_build_debug_bind (tracked_var,
PHI_RESULT (phi),
tree var;
timevar_push (TV_TREE_INSERT_PHI_NODES);
-
+
FOR_EACH_REFERENCED_VAR (var, rvi)
{
struct def_blocks_d *def_map;
register_new_def (tree def, tree sym)
{
tree currdef;
-
+
/* If this variable is set in a single basic block and all uses are
dominated by the set(s) in that single basic block, then there is
no reason to record anything for this variable in the block local
2- Every statement in BB is rewritten. USE and VUSE operands are
rewritten with their corresponding reaching definition. DEF and
VDEF targets are registered as new definitions.
-
+
3- All the PHI nodes in successor blocks of BB are visited. The
argument corresponding to BB is replaced with its current reaching
definition.
get_reaching_def (tree var)
{
tree currdef;
-
+
/* Lookup the current reaching definition for VAR. */
currdef = get_current_def (var);
saved_def = NULL;
var = tmp;
}
-
+
set_current_def (var, saved_def);
}
}
for (j = (int) VEC_length (tree, block_defs_stack) - 1; j >= 0; j--)
{
tree name, var;
-
+
name = VEC_index (tree, block_defs_stack, j);
if (name == NULL_TREE)
{
{
FILE *file = (FILE *) data;
struct def_blocks_d *db_p = (struct def_blocks_d *) *slot;
-
+
fprintf (file, "VAR: ");
print_generic_expr (file, db_p->var, dump_flags);
bitmap_print (file, db_p->def_blocks, ", DEF_BLOCKS: { ", "}");
DEF_P. */
static inline void
-maybe_register_def (def_operand_p def_p, gimple stmt)
+maybe_register_def (def_operand_p def_p, gimple stmt,
+ gimple_stmt_iterator gsi)
{
tree def = DEF_FROM_PTR (def_p);
tree sym = DECL_P (def) ? def : SSA_NAME_VAR (def);
{
if (DECL_P (def))
{
+ tree tracked_var;
+
def = make_ssa_name (def, stmt);
SET_DEF (def_p, def);
+
+ tracked_var = target_for_debug_bind (sym);
+ if (tracked_var)
+ {
+ gimple note = gimple_build_debug_bind (tracked_var, def, stmt);
+ gsi_insert_after (&gsi, note, GSI_SAME_STMT);
+ }
}
register_new_update_single (def, sym);
in OLD_SSA_NAMES. */
static void
-rewrite_update_stmt (gimple stmt)
+rewrite_update_stmt (gimple stmt, gimple_stmt_iterator gsi)
{
use_operand_p use_p;
def_operand_p def_p;
marked for renaming. */
if (register_defs_p (stmt))
FOR_EACH_SSA_DEF_OPERAND (def_p, stmt, iter, SSA_OP_ALL_DEFS)
- maybe_register_def (def_p, stmt);
+ maybe_register_def (def_p, stmt, gsi);
}
if (!bitmap_bit_p (blocks_with_phis_to_rewrite, e->dest->index))
continue;
-
+
phis = VEC_index (gimple_vec, phis_to_rewrite, e->dest->index);
for (i = 0; VEC_iterate (gimple, phis, i, phi); i++)
{
SET_USE (arg_p, reaching_def);
stmt = SSA_NAME_DEF_STMT (reaching_def);
- /* Single element PHI nodes behave like copies, so get the
+ /* Single element PHI nodes behave like copies, so get the
location from the phi argument. */
- if (gimple_code (stmt) == GIMPLE_PHI &&
+ if (gimple_code (stmt) == GIMPLE_PHI &&
gimple_phi_num_args (stmt) == 1)
locus = gimple_phi_arg_location (stmt, 0);
else
if (!register_defs_p (phi))
continue;
-
+
lhs = gimple_phi_result (phi);
lhs_sym = SSA_NAME_VAR (lhs);
the names replaced by LHS. */
if (is_new_name (lhs))
register_new_update_set (lhs, names_replaced_by (lhs));
-
+
/* If LHS is an OLD name, register it as a new definition
for itself. */
if (is_old_name (lhs))
/* Step 2. Rewrite every variable used in each statement in the block. */
if (TEST_BIT (interesting_blocks, bb->index))
- {
- gcc_assert (bitmap_bit_p (blocks_to_update, bb->index));
+ {
+ gcc_assert (bitmap_bit_p (blocks_to_update, bb->index));
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
- rewrite_update_stmt (gsi_stmt (gsi));
- }
+ rewrite_update_stmt (gsi_stmt (gsi), gsi);
+ }
/* Step 3. Update PHI nodes. */
rewrite_update_phi_arguments (bb);
{
tree var = VEC_pop (tree, block_defs_stack);
tree saved_def;
-
+
/* NULL indicates the unwind stop point for this block (see
rewrite_update_enter_block). */
if (var == NULL)
/* Rewrite the actual blocks, statements, and PHI arguments, to be in SSA
- form.
+ form.
ENTRY indicates the block where to start. Every block dominated by
ENTRY will be rewritten.
rewrite_blocks (basic_block entry, enum rewrite_mode what)
{
struct dom_walk_data walk_data;
-
+
/* Rewrite all the basic blocks in the program. */
timevar_push (TV_TREE_SSA_REWRITE_BLOCKS);
if (def_blocks)
dump_tree_ssa_stats (dump_file);
}
-
+
VEC_free (tree, heap, block_defs_stack);
timevar_pop (TV_TREE_SSA_REWRITE_BLOCKS);
{
bitmap *dfs;
basic_block bb;
-
+
timevar_push (TV_TREE_SSA_OTHER);
/* Initialize operand data structures. */
BITMAP_FREE (dfs[bb->index]);
free (dfs);
+ sbitmap_free (interesting_blocks);
+
fini_ssa_renamer ();
timevar_pop (TV_TREE_SSA_OTHER);
}
-struct gimple_opt_pass pass_build_ssa =
+struct gimple_opt_pass pass_build_ssa =
{
{
GIMPLE_PASS,
ssa_op_iter i;
use_operand_p use_p;
def_operand_p def_p;
-
+
stmt = gsi_stmt (si);
FOR_EACH_SSA_USE_OPERAND (use_p, stmt, i, SSA_OP_ALL_USES)
unsigned i = 0;
bitmap ret;
sbitmap_iterator sbi;
-
+
gcc_assert (update_ssa_initialized_fn == NULL
|| update_ssa_initialized_fn == cfun);
This is slightly different than the regular PHI insertion
algorithm. The value of UPDATE_FLAGS controls how PHI nodes for
real names (i.e., GIMPLE registers) are inserted:
-
+
- If UPDATE_FLAGS == TODO_update_ssa, we are only interested in PHI
nodes inside the region affected by the block that defines VAR
and the blocks that define all its replacements. All these