/* Rewrite a program in Normal form into SSA.
- Copyright (C) 2001-2015 Free Software Foundation, Inc.
+ Copyright (C) 2001-2019 Free Software Foundation, Inc.
Contributed by Diego Novillo <dnovillo@redhat.com>
This file is part of GCC.
#include "system.h"
#include "coretypes.h"
#include "backend.h"
+#include "rtl.h"
#include "tree.h"
#include "gimple.h"
-#include "rtl.h"
+#include "tree-pass.h"
#include "ssa.h"
-#include "alias.h"
-#include "fold-const.h"
-#include "flags.h"
-#include "tm_p.h"
+#include "gimple-pretty-print.h"
+#include "diagnostic-core.h"
#include "langhooks.h"
#include "cfganal.h"
-#include "gimple-pretty-print.h"
-#include "internal-fn.h"
#include "gimple-iterator.h"
#include "tree-cfg.h"
#include "tree-into-ssa.h"
-#include "insn-config.h"
-#include "expmed.h"
-#include "dojump.h"
-#include "explow.h"
-#include "calls.h"
-#include "emit-rtl.h"
-#include "varasm.h"
-#include "stmt.h"
-#include "expr.h"
#include "tree-dfa.h"
#include "tree-ssa.h"
-#include "tree-inline.h"
-#include "tree-pass.h"
-#include "cfgloop.h"
#include "domwalk.h"
-#include "params.h"
-#include "diagnostic-core.h"
+#include "statistics.h"
+#include "stringpool.h"
+#include "attribs.h"
+#include "asan.h"
#define PERCENT(x,y) ((float)(x) * 100.0 / (float)(y))
/* Structure to map a variable VAR to the set of blocks that contain
definitions for VAR. */
-struct def_blocks_d
+struct def_blocks
{
/* Blocks that contain definitions of VAR. Bit I will be set if the
Ith block contains a definition of VAR. */
bitmap livein_blocks;
};
-typedef struct def_blocks_d *def_blocks_p;
-
-
/* Stack of trees used to restore the global currdefs to its original
state after completing rewriting of a block and its dominator
children. Its elements have the following properties:
/* Set of SSA names that have been marked to be released after they
were registered in the replacement table. They will be finally
released after we finish updating the SSA web. */
-static bitmap names_to_release;
+bitmap names_to_release;
/* vec of vec of PHIs to rewrite in a basic block. Element I corresponds
the to basic block with index I. Allocated once per compilation, *not*
};
/* Information stored for both SSA names and decls. */
-struct common_info_d
+struct common_info
{
/* This field indicates whether or not the variable may need PHI nodes.
See the enum's definition for more detailed information about the
tree current_def;
/* Definitions for this var. */
- struct def_blocks_d def_blocks;
+ struct def_blocks def_blocks;
};
-/* The information associated with decls and SSA names. */
-typedef struct common_info_d *common_info_p;
-
/* Information stored for decls. */
-struct var_info_d
+struct var_info
{
/* The variable. */
tree var;
/* Information stored for both SSA names and decls. */
- struct common_info_d info;
+ common_info info;
};
-/* The information associated with decls. */
-typedef struct var_info_d *var_info_p;
-
/* VAR_INFOS hashtable helpers. */
-struct var_info_hasher : free_ptr_hash <var_info_d>
+struct var_info_hasher : free_ptr_hash <var_info>
{
static inline hashval_t hash (const value_type &);
static inline bool equal (const value_type &, const compare_type &);
bitmap repl_set;
/* Information stored for both SSA names and decls. */
- struct common_info_d info;
+ common_info info;
};
-/* The information associated with names. */
-typedef struct ssa_name_info *ssa_name_info_p;
-
-static vec<ssa_name_info_p> info_for_ssa_name;
+static vec<ssa_name_info *> info_for_ssa_name;
static unsigned current_info_for_ssa_name_age;
static bitmap_obstack update_ssa_obstack;
/* Get the information associated with NAME. */
-static inline ssa_name_info_p
+static inline ssa_name_info *
get_ssa_name_ann (tree name)
{
unsigned ver = SSA_NAME_VERSION (name);
/* Return and allocate the auxiliar information for DECL. */
-static inline var_info_p
+static inline var_info *
get_var_info (tree decl)
{
- struct var_info_d vi;
- var_info_d **slot;
+ var_info vi;
+ var_info **slot;
vi.var = decl;
slot = var_infos->find_slot_with_hash (&vi, DECL_UID (decl), INSERT);
if (*slot == NULL)
{
- var_info_p v = XCNEW (struct var_info_d);
+ var_info *v = XCNEW (var_info);
v->var = decl;
*slot = v;
return v;
/* Get access to the auxiliar information stored per SSA name or decl. */
-static inline common_info_p
+static inline common_info *
get_common_info (tree var)
{
if (TREE_CODE (var) == SSA_NAME)
where VAR is live on entry (livein). If no entry is found in
DEF_BLOCKS, a new one is created and returned. */
-static inline struct def_blocks_d *
-get_def_blocks_for (common_info_p info)
+static inline def_blocks *
+get_def_blocks_for (common_info *info)
{
- struct def_blocks_d *db_p = &info->def_blocks;
+ def_blocks *db_p = &info->def_blocks;
if (!db_p->def_blocks)
{
db_p->def_blocks = BITMAP_ALLOC (&update_ssa_obstack);
static void
set_def_block (tree var, basic_block bb, bool phi_p)
{
- struct def_blocks_d *db_p;
- common_info_p info;
+ def_blocks *db_p;
+ common_info *info;
info = get_common_info (var);
db_p = get_def_blocks_for (info);
static void
set_livein_block (tree var, basic_block bb)
{
- common_info_p info;
- struct def_blocks_d *db_p;
+ common_info *info;
+ def_blocks *db_p;
info = get_common_info (var);
db_p = get_def_blocks_for (info);
FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_ALL_USES)
{
tree sym = USE_FROM_PTR (use_p);
+ if (TREE_CODE (sym) == SSA_NAME)
+ continue;
gcc_checking_assert (DECL_P (sym));
if (!bitmap_bit_p (kills, DECL_UID (sym)))
set_livein_block (sym, bb);
each def to the set of killed symbols. */
FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_ALL_DEFS)
{
+ if (TREE_CODE (def) == SSA_NAME)
+ continue;
gcc_checking_assert (DECL_P (def));
set_def_block (def, bb, false);
bitmap_set_bit (kills, DECL_UID (def));
where VAR is live on entry (livein). Return NULL, if no entry is
found in DEF_BLOCKS. */
-static inline struct def_blocks_d *
+static inline def_blocks *
find_def_blocks_for (tree var)
{
- def_blocks_p p = &get_common_info (var)->def_blocks;
+ def_blocks *p = &get_common_info (var)->def_blocks;
if (!p->def_blocks)
return NULL;
return p;
gphi *phi;
basic_block bb;
bitmap_iterator bi;
- struct def_blocks_d *def_map = find_def_blocks_for (var);
+ def_blocks *def_map = find_def_blocks_for (var);
/* Remove the blocks where we already have PHI nodes for VAR. */
bitmap_and_compl_into (phi_insertion_points, def_map->phi_blocks);
static int
insert_phi_nodes_compare_var_infos (const void *a, const void *b)
{
- const struct var_info_d *defa = *(struct var_info_d * const *)a;
- const struct var_info_d *defb = *(struct var_info_d * const *)b;
+ const var_info *defa = *(var_info * const *)a;
+ const var_info *defb = *(var_info * const *)b;
if (DECL_UID (defa->var) < DECL_UID (defb->var))
return -1;
else
{
hash_table<var_info_hasher>::iterator hi;
unsigned i;
- var_info_p info;
+ var_info *info;
timevar_push (TV_TREE_INSERT_PHI_NODES);
- auto_vec<var_info_p> vars (var_infos->elements ());
+ /* When the gimplifier introduces SSA names it cannot easily avoid
+ situations where abnormal edges added by CFG construction break
+ the use-def dominance requirement. For this case rewrite SSA
+ names with broken use-def dominance out-of-SSA and register them
+ for PHI insertion. We only need to do this if abnormal edges
+ can appear in the function. */
+ tree name;
+ if (cfun->calls_setjmp
+ || cfun->has_nonlocal_label)
+ FOR_EACH_SSA_NAME (i, name, cfun)
+ {
+ gimple *def_stmt = SSA_NAME_DEF_STMT (name);
+ if (SSA_NAME_IS_DEFAULT_DEF (name))
+ continue;
+
+ basic_block def_bb = gimple_bb (def_stmt);
+ imm_use_iterator it;
+ gimple *use_stmt;
+ bool need_phis = false;
+ FOR_EACH_IMM_USE_STMT (use_stmt, it, name)
+ {
+ basic_block use_bb = gimple_bb (use_stmt);
+ if (use_bb != def_bb
+ && ! dominated_by_p (CDI_DOMINATORS, use_bb, def_bb))
+ need_phis = true;
+ }
+ if (need_phis)
+ {
+ tree var = create_tmp_reg (TREE_TYPE (name));
+ use_operand_p use_p;
+ FOR_EACH_IMM_USE_STMT (use_stmt, it, name)
+ {
+ basic_block use_bb = gimple_bb (use_stmt);
+ FOR_EACH_IMM_USE_ON_STMT (use_p, it)
+ SET_USE (use_p, var);
+ update_stmt (use_stmt);
+ set_livein_block (var, use_bb);
+ set_rewrite_uses (use_stmt, true);
+ bitmap_set_bit (interesting_blocks, use_bb->index);
+ }
+ def_operand_p def_p;
+ ssa_op_iter dit;
+ FOR_EACH_SSA_DEF_OPERAND (def_p, def_stmt, dit, SSA_OP_DEF)
+ if (DEF_FROM_PTR (def_p) == name)
+ SET_DEF (def_p, var);
+ update_stmt (def_stmt);
+ set_def_block (var, def_bb, false);
+ set_register_defs (def_stmt, true);
+ bitmap_set_bit (interesting_blocks, def_bb->index);
+ release_ssa_name (name);
+ }
+ }
+
+ auto_vec<var_info *> vars (var_infos->elements ());
FOR_EACH_HASH_TABLE_ELEMENT (*var_infos, info, var_info_p, hi)
if (info->info.need_phi_state != NEED_PHI_STATE_NO)
vars.quick_push (info);
static void
register_new_def (tree def, tree sym)
{
- common_info_p info = get_common_info (sym);
+ common_info *info = get_common_info (sym);
tree currdef;
/* If this variable is set in a single basic block and all uses are
static tree
get_reaching_def (tree var)
{
- common_info_p info = get_common_info (var);
+ common_info *info = get_common_info (var);
tree currdef;
/* Lookup the current reaching definition for VAR. */
if (currdef == NULL_TREE)
{
tree sym = DECL_P (var) ? var : SSA_NAME_VAR (var);
+ if (! sym)
+ sym = create_tmp_reg (TREE_TYPE (var));
currdef = get_or_create_ssa_default_def (cfun, sym);
}
FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE)
{
tree var = USE_FROM_PTR (use_p), def;
- common_info_p info = get_common_info (var);
+ common_info *info = get_common_info (var);
gcc_checking_assert (DECL_P (var));
def = info->current_def;
if (!def)
def_temp = gimple_build_debug_source_bind (def, var, NULL);
DECL_ARTIFICIAL (def) = 1;
TREE_TYPE (def) = TREE_TYPE (var);
- DECL_MODE (def) = DECL_MODE (var);
+ SET_DECL_MODE (def, DECL_MODE (var));
gsi =
gsi_after_labels (single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun)));
gsi_insert_before (&gsi, def_temp, GSI_SAME_STMT);
;
else
{
- struct def_blocks_d *db_p = get_def_blocks_for (info);
+ def_blocks *db_p = get_def_blocks_for (info);
/* If there are some non-debug uses in the current bb,
it is fine. */
FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_ALL_USES)
{
tree var = USE_FROM_PTR (use_p);
+ if (TREE_CODE (var) == SSA_NAME)
+ continue;
gcc_checking_assert (DECL_P (var));
SET_USE (use_p, get_reaching_def (var));
}
tree name;
tree tracked_var;
+ if (TREE_CODE (var) == SSA_NAME)
+ continue;
gcc_checking_assert (DECL_P (var));
if (gimple_clobber_p (stmt)
{
/* If we rewrite a DECL into SSA form then drop its
clobber stmts and replace uses with a new default def. */
- gcc_checking_assert (TREE_CODE (var) == VAR_DECL
- && !gimple_vdef (stmt));
+ gcc_checking_assert (VAR_P (var) && !gimple_vdef (stmt));
gsi_replace (si, gimple_build_nop (), true);
register_new_def (get_or_create_ssa_default_def (cfun, var), var);
break;
class rewrite_dom_walker : public dom_walker
{
public:
- rewrite_dom_walker (cdi_direction direction) : dom_walker (direction) {}
+ rewrite_dom_walker (cdi_direction direction)
+ : dom_walker (direction, ALL_BLOCKS, NULL) {}
- virtual void before_dom_children (basic_block);
+ virtual edge before_dom_children (basic_block);
virtual void after_dom_children (basic_block);
};
(BLOCK_DEFS). Register new definitions for every PHI node in the
block. */
-void
+edge
rewrite_dom_walker::before_dom_children (basic_block bb)
{
if (dump_file && (dump_flags & TDF_DETAILS))
reaching definition for the variable and the edge through which that
definition is reaching the PHI node. */
rewrite_add_phi_arguments (bb);
+
+ return NULL;
}
}
fprintf (file, " Previous CURRDEF (");
- print_generic_expr (file, var, 0);
+ print_generic_expr (file, var);
fprintf (file, ") = ");
if (name)
- print_generic_expr (file, name, 0);
+ print_generic_expr (file, name);
else
fprintf (file, "<NIL>");
fprintf (file, "\n");
fprintf (file, "\n\nCurrent reaching definitions\n\n");
FOR_EACH_VEC_ELT (symbols_to_rename, i, var)
{
- common_info_p info = get_common_info (var);
+ common_info *info = get_common_info (var);
fprintf (file, "CURRDEF (");
- print_generic_expr (file, var, 0);
+ print_generic_expr (file, var);
fprintf (file, ") = ");
if (info->current_def)
- print_generic_expr (file, info->current_def, 0);
+ print_generic_expr (file, info->current_def);
else
fprintf (file, "<NIL>");
fprintf (file, "\n");
/* Callback for htab_traverse to dump the VAR_INFOS hash table. */
int
-debug_var_infos_r (var_info_d **slot, FILE *file)
+debug_var_infos_r (var_info **slot, FILE *file)
{
- struct var_info_d *info = *slot;
+ var_info *info = *slot;
fprintf (file, "VAR: ");
print_generic_expr (file, info->var, dump_flags);
static inline void
register_new_update_single (tree new_name, tree old_name)
{
- common_info_p info = get_common_info (old_name);
+ common_info *info = get_common_info (old_name);
tree currdef = info->current_def;
/* Push the current reaching definition into BLOCK_DEFS_STACK.
}
+/* If DEF has x_5 = ASAN_POISON () as its current def, add
+ ASAN_POISON_USE (x_5) stmt before GSI to denote the stmt writes into
+ a poisoned (out of scope) variable. */
+
+static void
+maybe_add_asan_poison_write (tree def, gimple_stmt_iterator *gsi)
+{
+ tree cdef = get_current_def (def);
+ if (cdef != NULL
+ && TREE_CODE (cdef) == SSA_NAME
+ && gimple_call_internal_p (SSA_NAME_DEF_STMT (cdef), IFN_ASAN_POISON))
+ {
+ gcall *call
+ = gimple_build_call_internal (IFN_ASAN_POISON_USE, 1, cdef);
+ gimple_set_location (call, gimple_location (gsi_stmt (*gsi)));
+ gsi_insert_before (gsi, call, GSI_SAME_STMT);
+ }
+}
+
+
/* 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
{
if (gimple_clobber_p (stmt) && is_gimple_reg (sym))
{
- gcc_checking_assert (TREE_CODE (sym) == VAR_DECL);
+ gcc_checking_assert (VAR_P (sym));
/* Replace clobber stmts with a default def. This new use of a
default definition may make it look like SSA_NAMEs have
conflicting lifetimes, so we need special code to let them
def = get_or_create_ssa_default_def (cfun, sym);
}
else
- def = make_ssa_name (def, stmt);
+ {
+ if (asan_sanitize_use_after_scope ())
+ maybe_add_asan_poison_write (def, &gsi);
+ def = make_ssa_name (def, stmt);
+ }
SET_DEF (def_p, def);
tree tracked_var = target_for_debug_bind (sym);
/* Update the argument if there is a reaching def. */
if (reaching_def)
{
- source_location locus;
+ location_t locus;
int arg_i = PHI_ARG_INDEX_FROM_USE (arg_p);
SET_USE (arg_p, reaching_def);
class rewrite_update_dom_walker : public dom_walker
{
public:
- rewrite_update_dom_walker (cdi_direction direction) : dom_walker (direction) {}
+ rewrite_update_dom_walker (cdi_direction direction)
+ : dom_walker (direction, ALL_BLOCKS, NULL) {}
- virtual void before_dom_children (basic_block);
+ virtual edge before_dom_children (basic_block);
virtual void after_dom_children (basic_block);
};
for new SSA names produced in this block (BLOCK_DEFS). Register
new definitions for every PHI node in the block. */
-void
+edge
rewrite_update_dom_walker::before_dom_children (basic_block bb)
{
bool is_abnormal_phi;
block_defs_stack.safe_push (NULL_TREE);
if (!bitmap_bit_p (blocks_to_update, bb->index))
- return;
+ return NULL;
/* Mark the LHS if any of the arguments flows through an abnormal
edge. */
/* Step 3. Update PHI nodes. */
rewrite_update_phi_arguments (bb);
+
+ return NULL;
}
/* Called after visiting block BB. Unwind BLOCK_DEFS_STACK to restore
mark_def_dom_walker (cdi_direction direction);
~mark_def_dom_walker ();
- virtual void before_dom_children (basic_block);
+ virtual edge before_dom_children (basic_block);
private:
/* Notice that this bitmap is indexed using variable UIDs, so it must be
};
mark_def_dom_walker::mark_def_dom_walker (cdi_direction direction)
- : dom_walker (direction), m_kills (BITMAP_ALLOC (NULL))
+ : dom_walker (direction, ALL_BLOCKS, NULL), m_kills (BITMAP_ALLOC (NULL))
{
}
/* Block processing routine for mark_def_sites. Clear the KILLS bitmap
at the start of each block, and call mark_def_sites for each statement. */
-void
+edge
mark_def_dom_walker::before_dom_children (basic_block bb)
{
gimple_stmt_iterator gsi;
bitmap_clear (m_kills);
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
mark_def_sites (bb, gsi_stmt (gsi), m_kills);
+ return NULL;
}
/* Initialize internal data needed during renaming. */
{
bitmap_head *dfs;
basic_block bb;
- unsigned i;
+
+ /* Increase the set of variables we can rewrite into SSA form
+ by clearing TREE_ADDRESSABLE and setting DECL_GIMPLE_REG_P
+ and transform the IL to support this. */
+ if (optimize)
+ execute_update_addresses_taken ();
/* Initialize operand data structures. */
init_ssa_operands (fun);
/* Try to get rid of all gimplifier generated temporaries by making
its SSA names anonymous. This way we can garbage collect them
all after removing unused locals which we do in our TODO. */
- for (i = 1; i < num_ssa_names; ++i)
+ unsigned i;
+ tree name;
+
+ FOR_EACH_SSA_NAME (i, name, cfun)
{
- tree decl, name = ssa_name (i);
- if (!name
- || SSA_NAME_IS_DEFAULT_DEF (name))
+ if (SSA_NAME_IS_DEFAULT_DEF (name))
continue;
- decl = SSA_NAME_VAR (name);
+ tree decl = SSA_NAME_VAR (name);
if (decl
- && TREE_CODE (decl) == VAR_DECL
+ && VAR_P (decl)
&& !VAR_DECL_IS_VIRTUAL_OPERAND (decl)
&& DECL_IGNORED_P (decl))
SET_SSA_NAME_VAR_OR_IDENTIFIER (name, DECL_NAME (decl));
}
+ /* Initialize SSA_NAME_POINTS_TO_READONLY_MEMORY. */
+ tree fnspec = lookup_attribute ("fn spec",
+ TYPE_ATTRIBUTES (TREE_TYPE (fun->decl)));
+ if (fnspec)
+ {
+ fnspec = TREE_VALUE (TREE_VALUE (fnspec));
+ unsigned i = 1;
+ for (tree arg = DECL_ARGUMENTS (cfun->decl);
+ arg; arg = DECL_CHAIN (arg), ++i)
+ {
+ if (i >= (unsigned) TREE_STRING_LENGTH (fnspec))
+ break;
+ if (TREE_STRING_POINTER (fnspec)[i] == 'R'
+ || TREE_STRING_POINTER (fnspec)[i] == 'r')
+ {
+ tree name = ssa_default_def (fun, arg);
+ if (name)
+ SSA_NAME_POINTS_TO_READONLY_MEMORY (name) = 1;
+ }
+ }
+ }
+
return 0;
}
replace it). */
if (insert_phi_p)
{
- struct def_blocks_d *db_p = get_def_blocks_for (get_common_info (var));
+ def_blocks *db_p = get_def_blocks_for (get_common_info (var));
if (!bitmap_bit_p (db_p->def_blocks, bb->index))
set_livein_block (var, bb);
}
use_operand_p use_p;
imm_use_iterator iter;
+ /* If we rename virtual operands do not update them. */
+ if (virtual_operand_p (name)
+ && cfun->gimple_df->rename_vops)
+ return;
+
FOR_EACH_IMM_USE_FAST (use_p, iter, name)
{
gimple *stmt = USE_STMT (use_p);
|| !bitmap_bit_p (names_to_release,
SSA_NAME_VERSION (name)));
+ /* If we rename virtual operands do not update them. */
+ if (virtual_operand_p (name)
+ && cfun->gimple_df->rename_vops)
+ return;
+
stmt = SSA_NAME_DEF_STMT (name);
bb = gimple_bb (stmt);
if (bb)
bitmap old_set;
bitmap_iterator bi;
- print_generic_expr (file, name, 0);
+ print_generic_expr (file, name);
fprintf (file, " -> { ");
old_set = names_replaced_by (name);
EXECUTE_IF_SET_IN_BITMAP (old_set, 0, i, bi)
{
- print_generic_expr (file, ssa_name (i), 0);
+ print_generic_expr (file, ssa_name (i));
fprintf (file, " ");
}
fprintf (file, "\nSSA names to release after updating the SSA web\n\n");
EXECUTE_IF_SET_IN_BITMAP (names_to_release, 0, i, bi)
{
- print_generic_expr (file, ssa_name (i), 0);
+ print_generic_expr (file, ssa_name (i));
fprintf (file, " ");
}
fprintf (file, "\n");
unsigned update_flags)
{
basic_block entry;
- struct def_blocks_d *db;
+ def_blocks *db;
bitmap idf, pruned_idf;
bitmap_iterator bi;
unsigned i;
if (!need_ssa_update_p (cfun))
return;
-#ifdef ENABLE_CHECKING
- timevar_push (TV_TREE_STMT_VERIFY);
+ if (flag_checking)
+ {
+ timevar_push (TV_TREE_STMT_VERIFY);
- bool err = false;
+ bool err = false;
- FOR_EACH_BB_FN (bb, cfun)
- {
- gimple_stmt_iterator gsi;
- for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ FOR_EACH_BB_FN (bb, cfun)
{
- gimple *stmt = gsi_stmt (gsi);
-
- ssa_op_iter i;
- use_operand_p use_p;
- FOR_EACH_SSA_USE_OPERAND (use_p, stmt, i, SSA_OP_ALL_USES)
+ gimple_stmt_iterator gsi;
+ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
{
- tree use = USE_FROM_PTR (use_p);
- if (TREE_CODE (use) != SSA_NAME)
- continue;
+ gimple *stmt = gsi_stmt (gsi);
- if (SSA_NAME_IN_FREE_LIST (use))
+ ssa_op_iter i;
+ use_operand_p use_p;
+ FOR_EACH_SSA_USE_OPERAND (use_p, stmt, i, SSA_OP_ALL_USES)
{
- error ("statement uses released SSA name:");
- debug_gimple_stmt (stmt);
- fprintf (stderr, "The use of ");
- print_generic_expr (stderr, use, 0);
- fprintf (stderr," should have been replaced\n");
- err = true;
+ tree use = USE_FROM_PTR (use_p);
+ if (TREE_CODE (use) != SSA_NAME)
+ continue;
+
+ if (SSA_NAME_IN_FREE_LIST (use))
+ {
+ error ("statement uses released SSA name");
+ debug_gimple_stmt (stmt);
+ fprintf (stderr, "The use of ");
+ print_generic_expr (stderr, use);
+ fprintf (stderr," should have been replaced\n");
+ err = true;
+ }
}
}
}
- }
- if (err)
- internal_error ("cannot update SSA form");
+ if (err)
+ internal_error ("cannot update SSA form");
- timevar_pop (TV_TREE_STMT_VERIFY);
-#endif
+ timevar_pop (TV_TREE_STMT_VERIFY);
+ }
timevar_push (TV_TREE_SSA_INCREMENTAL);
OLD_SSA_NAMES. */
if (bitmap_first_set_bit (new_ssa_names) >= 0)
{
+ statistics_counter_event (cfun, "Incremental SSA update", 1);
+
prepare_names_to_update (insert_phi_p);
/* If all the names in NEW_SSA_NAMES had been marked for
/* Next, determine the block at which to start the renaming process. */
if (cfun->gimple_df->ssa_renaming_needed)
{
+ statistics_counter_event (cfun, "Symbol to SSA rewrite", 1);
+
/* If we rename bare symbols initialize the mapping to
auxiliar info we need to keep track of. */
var_infos = new hash_table<var_info_hasher> (47);
placement heuristics. */
prepare_block_for_update (start_bb, insert_phi_p);
-#ifdef ENABLE_CHECKING
- for (i = 1; i < num_ssa_names; ++i)
- {
- tree name = ssa_name (i);
- if (!name
- || virtual_operand_p (name))
- continue;
+ tree name;
- /* For all but virtual operands, which do not have SSA names
- with overlapping life ranges, ensure that symbols marked
- for renaming do not have existing SSA names associated with
- them as we do not re-write them out-of-SSA before going
- into SSA for the remaining symbol uses. */
- if (marked_for_renaming (SSA_NAME_VAR (name)))
- {
- fprintf (stderr, "Existing SSA name for symbol marked for "
- "renaming: ");
- print_generic_expr (stderr, name, TDF_SLIM);
- fprintf (stderr, "\n");
- internal_error ("SSA corruption");
- }
- }
-#endif
+ if (flag_checking)
+ FOR_EACH_SSA_NAME (i, name, cfun)
+ {
+ if (virtual_operand_p (name))
+ continue;
+
+ /* For all but virtual operands, which do not have SSA names
+ with overlapping life ranges, ensure that symbols marked
+ for renaming do not have existing SSA names associated with
+ them as we do not re-write them out-of-SSA before going
+ into SSA for the remaining symbol uses. */
+ if (marked_for_renaming (SSA_NAME_VAR (name)))
+ {
+ fprintf (stderr, "Existing SSA name for symbol marked for "
+ "renaming: ");
+ print_generic_expr (stderr, name, TDF_SLIM);
+ fprintf (stderr, "\n");
+ internal_error ("SSA corruption");
+ }
+ }
}
else
{
will grow while we are traversing it (but it will not
gain any new members). Copy OLD_SSA_NAMES to a temporary
for traversal. */
- sbitmap tmp = sbitmap_alloc (SBITMAP_SIZE (old_ssa_names));
+ auto_sbitmap tmp (SBITMAP_SIZE (old_ssa_names));
bitmap_copy (tmp, old_ssa_names);
EXECUTE_IF_SET_IN_BITMAP (tmp, 0, i, sbi)
insert_updated_phi_nodes_for (ssa_name (i), dfs, blocks_to_update,
update_flags);
- sbitmap_free (tmp);
}
symbols_to_rename.qsort (insert_updated_phi_nodes_compare_uids);