+/* If the operand pointed to by DEF_P is an SSA name in NEW_SSA_NAMES
+ or OLD_SSA_NAMES, or if it is a symbol marked for renaming,
+ register it as the current definition for the names replaced by
+ DEF_P. */
+
+static inline void
+maybe_register_def (def_operand_p def_p, tree stmt)
+{
+ tree def = DEF_FROM_PTR (def_p);
+ tree sym = DECL_P (def) ? def : SSA_NAME_VAR (def);
+
+ /* If DEF is a naked symbol that needs renaming, create a new
+ name for it. */
+ if (symbol_marked_for_renaming (sym))
+ {
+ if (DECL_P (def))
+ {
+ def = make_ssa_name (def, stmt);
+ SET_DEF (def_p, def);
+ }
+
+ register_new_update_single (def, sym);
+ }
+ else
+ {
+ /* If DEF is a new name, register it as a new definition
+ for all the names replaced by DEF. */
+ if (is_new_name (def))
+ register_new_update_set (def, names_replaced_by (def));
+
+ /* If DEF is an old name, register DEF as a new
+ definition for itself. */
+ if (is_old_name (def))
+ register_new_update_single (def, def);
+ }
+}
+
+
+/* Update every variable used in the statement pointed-to by SI. The
+ statement is assumed to be in SSA form already. Names in
+ OLD_SSA_NAMES used by SI will be updated to their current reaching
+ definition. Names in OLD_SSA_NAMES or NEW_SSA_NAMES defined by SI
+ will be registered as a new definition for their corresponding name
+ in OLD_SSA_NAMES. */
+
+static void
+rewrite_update_stmt (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
+ basic_block bb ATTRIBUTE_UNUSED,
+ block_stmt_iterator si)
+{
+ stmt_ann_t ann;
+ tree stmt;
+ use_operand_p use_p;
+ def_operand_p def_p;
+ ssa_op_iter iter;
+
+ stmt = bsi_stmt (si);
+ ann = stmt_ann (stmt);
+
+ gcc_assert (bitmap_bit_p (blocks_to_update, bb->index));
+
+ /* Only update marked statements. */
+ if (!REWRITE_THIS_STMT (stmt) && !REGISTER_DEFS_IN_THIS_STMT (stmt))
+ return;
+
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "Updating SSA information for statement ");
+ print_generic_stmt (dump_file, stmt, TDF_SLIM);
+ fprintf (dump_file, "\n");
+ }
+
+ /* Rewrite USES included in OLD_SSA_NAMES and USES whose underlying
+ symbol is marked for renaming. */
+ if (REWRITE_THIS_STMT (stmt))
+ {
+ FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE)
+ maybe_replace_use (use_p);
+
+ if (need_to_update_vops_p)
+ FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_VIRTUAL_USES)
+ maybe_replace_use (use_p);
+ }
+
+ /* Register definitions of names in NEW_SSA_NAMES and OLD_SSA_NAMES.
+ Also register definitions for names whose underlying symbol is
+ marked for renaming. */
+ if (REGISTER_DEFS_IN_THIS_STMT (stmt))
+ {
+ FOR_EACH_SSA_DEF_OPERAND (def_p, stmt, iter, SSA_OP_DEF)
+ maybe_register_def (def_p, stmt);
+
+ if (need_to_update_vops_p)
+ FOR_EACH_SSA_DEF_OPERAND (def_p, stmt, iter, SSA_OP_VIRTUAL_DEFS)
+ maybe_register_def (def_p, stmt);
+ }
+}
+
+
+/* Visit all the successor blocks of BB looking for PHI nodes. For
+ every PHI node found, check if any of its arguments is in
+ OLD_SSA_NAMES. If so, and if the argument has a current reaching
+ definition, replace it. */
+
+static void
+rewrite_update_phi_arguments (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
+ basic_block bb)
+{
+ edge e;
+ edge_iterator ei;
+ unsigned i;
+
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ {
+ tree phi;
+ tree_vec phis;
+
+ if (!bitmap_bit_p (blocks_with_phis_to_rewrite, e->dest->index))
+ continue;
+
+ phis = VEC_index (tree_vec, phis_to_rewrite, e->dest->index);
+ for (i = 0; VEC_iterate (tree, phis, i, phi); i++)
+ {
+ tree arg, lhs_sym;
+ use_operand_p arg_p;
+
+ gcc_assert (REWRITE_THIS_STMT (phi));
+
+ arg_p = PHI_ARG_DEF_PTR_FROM_EDGE (phi, e);
+ arg = USE_FROM_PTR (arg_p);
+
+ if (arg && !DECL_P (arg) && TREE_CODE (arg) != SSA_NAME)
+ continue;
+
+ lhs_sym = SSA_NAME_VAR (PHI_RESULT (phi));
+
+ if (arg == NULL_TREE)
+ {
+ /* When updating a PHI node for a recently introduced
+ symbol we may find NULL arguments. That's why we
+ take the symbol from the LHS of the PHI node. */
+ SET_USE (arg_p, get_reaching_def (lhs_sym));
+ }
+ else
+ {
+ tree sym = DECL_P (arg) ? arg : SSA_NAME_VAR (arg);
+
+ if (symbol_marked_for_renaming (sym))
+ SET_USE (arg_p, get_reaching_def (sym));
+ else if (is_old_name (arg))
+ SET_USE (arg_p, get_reaching_def (arg));
+ }
+
+ if (e->flags & EDGE_ABNORMAL)
+ SSA_NAME_OCCURS_IN_ABNORMAL_PHI (USE_FROM_PTR (arg_p)) = 1;
+ }
+ }
+}
+
+
+/* Rewrite the actual blocks, statements, and PHI arguments, to be in SSA
+ form.
+
+ ENTRY indicates the block where to start. Every block dominated by
+ ENTRY will be rewritten.
+
+ WHAT indicates what actions will be taken by the renamer (see enum
+ rewrite_mode).
+
+ BLOCKS are the set of interesting blocks for the dominator walker
+ to process. If this set is NULL, then all the nodes dominated
+ by ENTRY are walked. Otherwise, blocks dominated by ENTRY that
+ are not present in BLOCKS are ignored. */
+
+static void
+rewrite_blocks (basic_block entry, enum rewrite_mode what, sbitmap blocks)
+{
+ struct dom_walk_data walk_data;
+
+ /* Rewrite all the basic blocks in the program. */
+ timevar_push (TV_TREE_SSA_REWRITE_BLOCKS);
+
+ /* Setup callbacks for the generic dominator tree walker. */
+ memset (&walk_data, 0, sizeof (walk_data));
+
+ walk_data.dom_direction = CDI_DOMINATORS;
+ walk_data.interesting_blocks = blocks;
+
+ if (what == REWRITE_ALL)
+ walk_data.before_dom_children_before_stmts = rewrite_initialize_block;
+ else
+ walk_data.before_dom_children_before_stmts = rewrite_update_init_block;
+
+ if (what == REWRITE_ALL)
+ walk_data.before_dom_children_walk_stmts = rewrite_stmt;
+ else if (what == REWRITE_UPDATE)
+ walk_data.before_dom_children_walk_stmts = rewrite_update_stmt;
+ else
+ gcc_unreachable ();
+
+ if (what == REWRITE_ALL)
+ walk_data.before_dom_children_after_stmts = rewrite_add_phi_arguments;
+ else if (what == REWRITE_UPDATE)
+ walk_data.before_dom_children_after_stmts = rewrite_update_phi_arguments;
+ else
+ gcc_unreachable ();
+
+ if (what == REWRITE_ALL)
+ walk_data.after_dom_children_after_stmts = rewrite_finalize_block;
+ else if (what == REWRITE_UPDATE)
+ walk_data.after_dom_children_after_stmts = rewrite_update_fini_block;
+ else
+ gcc_unreachable ();
+
+ block_defs_stack = VEC_alloc (tree, heap, 10);
+
+ /* Initialize the dominator walker. */
+ init_walk_dominator_tree (&walk_data);
+
+ /* Recursively walk the dominator tree rewriting each statement in
+ each basic block. */
+ walk_dominator_tree (&walk_data, entry);
+
+ /* Finalize the dominator walker. */
+ fini_walk_dominator_tree (&walk_data);
+
+ /* Debugging dumps. */
+ if (dump_file && (dump_flags & TDF_STATS))
+ {
+ dump_dfa_stats (dump_file);
+ if (def_blocks)
+ dump_tree_ssa_stats (dump_file);
+ }
+
+ VEC_free (tree, heap, block_defs_stack);
+
+ timevar_pop (TV_TREE_SSA_REWRITE_BLOCKS);
+}
+
+
+/* Block initialization routine for mark_def_sites. Clear the
+ KILLS bitmap at the start of each block. */
+
+static void
+mark_def_sites_initialize_block (struct dom_walk_data *walk_data,
+ basic_block bb ATTRIBUTE_UNUSED)
+{
+ struct mark_def_sites_global_data *gd;
+ gd = (struct mark_def_sites_global_data *) walk_data->global_data;
+ bitmap_clear (gd->kills);
+}
+
+
+/* Mark the definition site blocks for each variable, so that we know
+ where the variable is actually live.
+
+ INTERESTING_BLOCKS will be filled in with all the blocks that
+ should be processed by the renamer. It is assumed to be
+ initialized and zeroed by the caller. */
+
+static void
+mark_def_site_blocks (sbitmap interesting_blocks)
+{
+ struct dom_walk_data walk_data;
+ struct mark_def_sites_global_data mark_def_sites_global_data;
+
+ /* Setup callbacks for the generic dominator tree walker to find and
+ mark definition sites. */
+ walk_data.walk_stmts_backward = false;
+ walk_data.dom_direction = CDI_DOMINATORS;
+ walk_data.initialize_block_local_data = NULL;
+ walk_data.before_dom_children_before_stmts = mark_def_sites_initialize_block;
+ walk_data.before_dom_children_walk_stmts = mark_def_sites;
+ walk_data.before_dom_children_after_stmts = NULL;
+ walk_data.after_dom_children_before_stmts = NULL;
+ walk_data.after_dom_children_walk_stmts = NULL;