tree-ssa-operands.h (create_ssa_artificial_load_stmt): Rename from create_ssa_artficial_load_stmt.

* tree-ssa-operands.h (create_ssa_artificial_load_stmt):
	Rename from create_ssa_artficial_load_stmt.  Update all users.
	* tree-into-ssa.c (register_new_def): Make static.
	* tree.c (is_global_var): Handle SSA_NAMEs.
	* tree.h (SSA_NAME_IS_DEFAULT_DEF): Define.  Update all users
	that used to call gimple_default_def.
	* tree-ssa-operands.c (push_stmt_changes): New.
	(pop_stmt_changes): New.  Update every pass that modifies
	statements to bracket modifications with
	push_stmt_changes/pop_stmt_changes.
	(discard_stmt_changes): New.
	* tree-ssa-dom.c (stmts_to_rescan): Change to stack of
	'tree *' instead of 'tree'.  Update all users.
	* tree-flow-inline.h (zero_imm_uses_p): New.
	(symbol_mem_tag): New.  Update every function that used
	to access the annotation directly.
	(set_symbol_mem_tag): Likewise.
	* tree-dfa.c (dump_variable): Always show the escape mask.
	(mark_symbols_for_renaming): Rename from
	mark_new_vars_to_rename.  Update all users.
	Only mark to rename naked symbols in real and virtual
	operands.

From-SVN: r119746
This commit is contained in:
Diego Novillo 2006-12-11 20:15:53 +00:00 committed by Diego Novillo
parent 7f46c638e6
commit cfaab3a924
24 changed files with 498 additions and 170 deletions

View File

@ -1,3 +1,28 @@
2006-12-11 Diego Novillo <dnovillo@redhat.com>
* tree-ssa-operands.h (create_ssa_artificial_load_stmt):
Rename from create_ssa_artficial_load_stmt. Update all users.
* tree-into-ssa.c (register_new_def): Make static.
* tree.c (is_global_var): Handle SSA_NAMEs.
* tree.h (SSA_NAME_IS_DEFAULT_DEF): Define. Update all users
that used to call gimple_default_def.
* tree-ssa-operands.c (push_stmt_changes): New.
(pop_stmt_changes): New. Update every pass that modifies
statements to bracket modifications with
push_stmt_changes/pop_stmt_changes.
(discard_stmt_changes): New.
* tree-ssa-dom.c (stmts_to_rescan): Change to stack of
'tree *' instead of 'tree'. Update all users.
* tree-flow-inline.h (zero_imm_uses_p): New.
(symbol_mem_tag): New. Update every function that used
to access the annotation directly.
(set_symbol_mem_tag): Likewise.
* tree-dfa.c (dump_variable): Always show the escape mask.
(mark_symbols_for_renaming): Rename from
mark_new_vars_to_rename. Update all users.
Only mark to rename naked symbols in real and virtual
operands.
2006-12-11 Andreas Schwab <schwab@suse.de>
* varasm.c (elf_record_gcc_switches): Cast second argument of

View File

@ -885,6 +885,7 @@ execute_one_pass (struct tree_opt_pass *pass)
free ((char *) dump_file_name);
dump_file_name = NULL;
}
if (dump_file)
{
dump_end (pass->static_pass_number, dump_file);

View File

@ -1248,6 +1248,9 @@ replace_uses_by (tree name, tree val)
FOR_EACH_IMM_USE_STMT (stmt, imm_iter, name)
{
if (TREE_CODE (stmt) != PHI_NODE)
push_stmt_changes (&stmt);
FOR_EACH_IMM_USE_ON_STMT (use, imm_iter)
{
replace_exp (use, val);
@ -1265,21 +1268,25 @@ replace_uses_by (tree name, tree val)
}
}
}
if (TREE_CODE (stmt) != PHI_NODE)
{
tree rhs;
fold_stmt_inplace (stmt);
/* FIXME. This should go in pop_stmt_changes. */
rhs = get_rhs (stmt);
if (TREE_CODE (rhs) == ADDR_EXPR)
recompute_tree_invariant_for_addr_expr (rhs);
maybe_clean_or_replace_eh_stmt (stmt, stmt);
mark_new_vars_to_rename (stmt);
pop_stmt_changes (&stmt);
}
}
gcc_assert (num_imm_uses (name) == 0);
gcc_assert (zero_imm_uses_p (name));
/* Also update the trees stored in loop structures. */
if (current_loops)
@ -3996,7 +4003,7 @@ tree_make_forwarder_block (edge fallthru)
if (single_pred_p (bb))
return;
/* If we redirected a branch we must create new phi nodes at the
/* If we redirected a branch we must create new PHI nodes at the
start of BB. */
for (phi = phi_nodes (dummy); phi; phi = PHI_CHAIN (phi))
{
@ -5684,7 +5691,7 @@ gimplify_val (block_stmt_iterator *bsi, tree type, tree exp)
bsi_insert_before (bsi, new_stmt, BSI_SAME_STMT);
if (gimple_in_ssa_p (cfun))
mark_new_vars_to_rename (new_stmt);
mark_symbols_for_renaming (new_stmt);
return t;
}

View File

@ -149,7 +149,7 @@ ptr_decl_may_alias_p (tree ptr, tree decl,
if (pi)
tag = pi->name_mem_tag;
if (!tag)
tag = get_var_ann (SSA_NAME_VAR (ptr))->symbol_mem_tag;
tag = symbol_mem_tag (SSA_NAME_VAR (ptr));
if (!tag)
tag = DR_MEMTAG (ptr_dr);
if (!tag)
@ -180,13 +180,13 @@ ptr_ptr_may_alias_p (tree ptr_a, tree ptr_b,
}
else
{
tag_a = get_var_ann (SSA_NAME_VAR (ptr_a))->symbol_mem_tag;
tag_a = symbol_mem_tag (SSA_NAME_VAR (ptr_a));
if (!tag_a)
tag_a = DR_MEMTAG (dra);
if (!tag_a)
return false;
tag_b = get_var_ann (SSA_NAME_VAR (ptr_b))->symbol_mem_tag;
tag_b = symbol_mem_tag (SSA_NAME_VAR (ptr_b));
if (!tag_b)
tag_b = DR_MEMTAG (drb);
if (!tag_b)
@ -1729,10 +1729,9 @@ object_analysis (tree memref, tree stmt, bool is_read,
switch (TREE_CODE (base_address))
{
case SSA_NAME:
*memtag = get_var_ann (SSA_NAME_VAR (base_address))->symbol_mem_tag;
*memtag = symbol_mem_tag (SSA_NAME_VAR (base_address));
if (!(*memtag) && TREE_CODE (TREE_OPERAND (memref, 0)) == SSA_NAME)
*memtag = get_var_ann (
SSA_NAME_VAR (TREE_OPERAND (memref, 0)))->symbol_mem_tag;
*memtag = symbol_mem_tag (SSA_NAME_VAR (TREE_OPERAND (memref, 0)));
break;
case ADDR_EXPR:
*memtag = TREE_OPERAND (base_address, 0);

View File

@ -334,33 +334,30 @@ dump_variable (FILE *file, tree var)
if (is_call_clobbered (var))
{
var_ann_t va = var_ann (var);
unsigned int escape_mask = va->escape_mask;
fprintf (file, ", call clobbered");
if (dump_flags & TDF_DETAILS)
{
var_ann_t va = var_ann (var);
unsigned int escape_mask = va->escape_mask;
fprintf (file, " (");
if (escape_mask & ESCAPE_STORED_IN_GLOBAL)
fprintf (file, ", stored in global");
if (escape_mask & ESCAPE_TO_ASM)
fprintf (file, ", goes through ASM");
if (escape_mask & ESCAPE_TO_CALL)
fprintf (file, ", passed to call");
if (escape_mask & ESCAPE_BAD_CAST)
fprintf (file, ", bad cast");
if (escape_mask & ESCAPE_TO_RETURN)
fprintf (file, ", returned from func");
if (escape_mask & ESCAPE_TO_PURE_CONST)
fprintf (file, ", passed to pure/const");
if (escape_mask & ESCAPE_IS_GLOBAL)
fprintf (file, ", is global var");
if (escape_mask & ESCAPE_IS_PARM)
fprintf (file, ", is incoming pointer");
if (escape_mask & ESCAPE_UNKNOWN)
fprintf (file, ", unknown escape");
fprintf (file, " )");
}
fprintf (file, " (");
if (escape_mask & ESCAPE_STORED_IN_GLOBAL)
fprintf (file, ", stored in global");
if (escape_mask & ESCAPE_TO_ASM)
fprintf (file, ", goes through ASM");
if (escape_mask & ESCAPE_TO_CALL)
fprintf (file, ", passed to call");
if (escape_mask & ESCAPE_BAD_CAST)
fprintf (file, ", bad cast");
if (escape_mask & ESCAPE_TO_RETURN)
fprintf (file, ", returned from func");
if (escape_mask & ESCAPE_TO_PURE_CONST)
fprintf (file, ", passed to pure/const");
if (escape_mask & ESCAPE_IS_GLOBAL)
fprintf (file, ", is global var");
if (escape_mask & ESCAPE_IS_PARM)
fprintf (file, ", is incoming pointer");
if (escape_mask & ESCAPE_UNKNOWN)
fprintf (file, ", unknown escape");
fprintf (file, " )");
}
if (gimple_default_def (cfun, var))
@ -688,8 +685,12 @@ set_default_def (tree var, tree def)
else
{
h = (struct int_tree_map *) *loc;
SSA_NAME_IS_DEFAULT_DEF (h->to) = false;
h->to = def;
}
/* Mark DEF as the default definition for VAR. */
SSA_NAME_IS_DEFAULT_DEF (def) = true;
}
/* Add VAR to the list of referenced variables if it isn't already there. */
@ -751,72 +752,27 @@ get_virtual_var (tree var)
return var;
}
/* Mark all the non-SSA variables found in STMT's operands to be
processed by update_ssa. */
/* Mark all the naked symbols in STMT for SSA renaming.
NOTE: This function should only be used for brand new statements.
If the caller is modifying an existing statement, it should use the
combination push_stmt_changes/pop_stmt_changes. */
void
mark_new_vars_to_rename (tree stmt)
mark_symbols_for_renaming (tree stmt)
{
tree op;
ssa_op_iter iter;
tree val;
bitmap vars_in_vops_to_rename;
bool found_exposed_symbol = false;
int v_may_defs_before, v_may_defs_after;
int v_must_defs_before, v_must_defs_after;
if (TREE_CODE (stmt) == PHI_NODE)
return;
get_stmt_ann (stmt);
vars_in_vops_to_rename = BITMAP_ALLOC (NULL);
/* Before re-scanning the statement for operands, mark the existing
virtual operands to be renamed again. We do this because when new
symbols are exposed, the virtual operands that were here before due to
aliasing will probably be removed by the call to get_stmt_operand.
Therefore, we need to flag them to be renamed beforehand.
We flag them in a separate bitmap because we don't really want to
rename them if there are not any newly exposed symbols in the
statement operands. */
v_may_defs_before = NUM_SSA_OPERANDS (stmt, SSA_OP_VMAYDEF);
v_must_defs_before = NUM_SSA_OPERANDS (stmt, SSA_OP_VMUSTDEF);
FOR_EACH_SSA_TREE_OPERAND (val, stmt, iter,
SSA_OP_VMAYDEF | SSA_OP_VUSE | SSA_OP_VMUSTDEF)
{
if (!DECL_P (val))
val = SSA_NAME_VAR (val);
bitmap_set_bit (vars_in_vops_to_rename, DECL_UID (val));
}
/* Now force an operand re-scan on the statement and mark any newly
exposed variables. */
update_stmt (stmt);
v_may_defs_after = NUM_SSA_OPERANDS (stmt, SSA_OP_VMAYDEF);
v_must_defs_after = NUM_SSA_OPERANDS (stmt, SSA_OP_VMUSTDEF);
FOR_EACH_SSA_TREE_OPERAND (val, stmt, iter, SSA_OP_ALL_OPERANDS)
if (DECL_P (val))
{
found_exposed_symbol = true;
mark_sym_for_renaming (val);
}
/* If we found any newly exposed symbols, or if there are fewer VDEF
operands in the statement, add the variables we had set in
VARS_IN_VOPS_TO_RENAME to VARS_TO_RENAME. We need to check for
vanishing VDEFs because in those cases, the names that were formerly
generated by this statement are not going to be available anymore. */
if (found_exposed_symbol
|| v_may_defs_before > v_may_defs_after
|| v_must_defs_before > v_must_defs_after)
mark_set_for_renaming (vars_in_vops_to_rename);
BITMAP_FREE (vars_in_vops_to_rename);
/* Mark all the operands for renaming. */
FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_ALL_OPERANDS)
if (DECL_P (op))
mark_sym_for_renaming (op);
}
/* Find all variables within the gimplified statement that were not previously
visible to the function and add them to the referenced variables list. */
@ -845,7 +801,7 @@ find_new_referenced_vars (tree *stmt_p)
}
/* If REF is a handled component reference for a structure, return the
/* If EXP is a handled component reference for a structure, return the
base variable. The access range is delimited by bit positions *POFFSET and
*POFFSET + *PMAX_SIZE. The access size is *PSIZE bits. If either
*PSIZE or *PMAX_SIZE is -1, they could not be determined. If *PSIZE

View File

@ -587,7 +587,14 @@ num_imm_uses (tree var)
return num;
}
/* Return true if VAR has no immediate uses. */
static inline bool
zero_imm_uses_p (tree var)
{
ssa_use_operand_t *ptr = &(SSA_NAME_IMM_USE_NODE (var));
return (ptr == ptr->next);
}
/* Return the tree pointer to by USE. */
static inline tree
get_use_from_ptr (use_operand_p use)
@ -1712,6 +1719,35 @@ overlap_subvar (unsigned HOST_WIDE_INT offset, unsigned HOST_WIDE_INT size,
}
/* Return the memory tag associated with symbol SYM. */
static inline tree
symbol_mem_tag (tree sym)
{
tree tag = get_var_ann (sym)->symbol_mem_tag;
#if defined ENABLE_CHECKING
if (tag)
gcc_assert (TREE_CODE (tag) == SYMBOL_MEMORY_TAG);
#endif
return tag;
}
/* Set the memory tag associated with symbol SYM. */
static inline void
set_symbol_mem_tag (tree sym, tree tag)
{
#if defined ENABLE_CHECKING
if (tag)
gcc_assert (TREE_CODE (tag) == SYMBOL_MEMORY_TAG);
#endif
get_var_ann (sym)->symbol_mem_tag = tag;
}
/* Get the value handle of EXPR. This is the only correct way to get
the value handle for a "thing". If EXPR does not have a value
handle associated, it returns NULL_TREE.

View File

@ -675,7 +675,7 @@ extern void dump_subvars_for (FILE *, tree);
extern void debug_subvars_for (tree);
extern tree get_virtual_var (tree);
extern void add_referenced_var (tree);
extern void mark_new_vars_to_rename (tree);
extern void mark_symbols_for_renaming (tree);
extern void find_new_referenced_vars (tree *);
extern tree make_rename_temp (tree, const char *);
@ -733,7 +733,6 @@ extern bool tree_ssa_useless_type_conversion (tree);
extern bool tree_ssa_useless_type_conversion_1 (tree, tree);
extern void verify_ssa (bool);
extern void delete_tree_ssa (void);
extern void register_new_def (tree, VEC(tree,heap) **);
extern void walk_use_def_chains (tree, walk_use_def_chains_fn, void *, bool);
extern bool stmt_references_memory_p (tree);
@ -746,7 +745,7 @@ bool need_ssa_update_p (void);
bool name_mappings_registered_p (void);
bool name_registered_for_update_p (tree);
bitmap ssa_names_to_replace (void);
void release_ssa_name_after_update_ssa (tree name);
void release_ssa_name_after_update_ssa (tree);
void compute_global_livein (bitmap, bitmap);
tree duplicate_ssa_name (tree, tree);
void mark_sym_for_renaming (tree);
@ -906,21 +905,22 @@ extern enum move_pos movement_possibility (tree);
/* The reasons a variable may escape a function. */
enum escape_type
{
NO_ESCAPE = 0, /* Doesn't escape. */
ESCAPE_STORED_IN_GLOBAL = 1 << 1,
ESCAPE_TO_ASM = 1 << 2, /* Passed by address to an assembly
statement. */
ESCAPE_TO_CALL = 1 << 3, /* Escapes to a function call. */
ESCAPE_BAD_CAST = 1 << 4, /* Cast from pointer to integer */
ESCAPE_TO_RETURN = 1 << 5, /* Returned from function. */
ESCAPE_TO_PURE_CONST = 1 << 6, /* Escapes to a pure or constant
function call. */
ESCAPE_IS_GLOBAL = 1 << 7, /* Is a global variable. */
ESCAPE_IS_PARM = 1 << 8, /* Is an incoming function parameter. */
ESCAPE_UNKNOWN = 1 << 9 /* We believe it escapes for some reason
not enumerated above. */
};
{
NO_ESCAPE = 0, /* Doesn't escape. */
ESCAPE_STORED_IN_GLOBAL = 1 << 1,
ESCAPE_TO_ASM = 1 << 2, /* Passed by address to an assembly
statement. */
ESCAPE_TO_CALL = 1 << 3, /* Escapes to a function call. */
ESCAPE_BAD_CAST = 1 << 4, /* Cast from pointer to integer */
ESCAPE_TO_RETURN = 1 << 5, /* Returned from function. */
ESCAPE_TO_PURE_CONST = 1 << 6, /* Escapes to a pure or constant
function call. */
ESCAPE_IS_GLOBAL = 1 << 7, /* Is a global variable. */
ESCAPE_IS_PARM = 1 << 8, /* Is an incoming function argument. */
ESCAPE_UNKNOWN = 1 << 9 /* We believe it escapes for
some reason not enumerated
above. */
};
/* In tree-flow-inline.h */
static inline bool is_call_clobbered (tree);

View File

@ -1225,7 +1225,7 @@ insert_phi_nodes (bitmap *dfs)
variable (SSA_NAME_VAR (DEF)) and push VAR's current reaching definition
into the stack pointed to by BLOCK_DEFS_P. */
void
static void
register_new_def (tree def, VEC(tree,heap) **block_defs_p)
{
tree var = SSA_NAME_VAR (def);

View File

@ -125,7 +125,7 @@ create_temp (tree t)
/* add_referenced_var will create the annotation and set up some
of the flags in the annotation. However, some flags we need to
inherit from our original variable. */
var_ann (tmp)->symbol_mem_tag = var_ann (t)->symbol_mem_tag;
set_symbol_mem_tag (tmp, symbol_mem_tag (t));
if (is_call_clobbered (t))
mark_call_clobbered (tmp, var_ann (t)->escape_mask);

View File

@ -1844,12 +1844,11 @@ pointer_used_p (tree ptr)
imm_use_iterator imm_iter;
tree stmt, rhs;
struct ptr_info_def *pi = get_ptr_info (ptr);
var_ann_t v_ann = var_ann (SSA_NAME_VAR (ptr));
/* Check whether the pointer has a memory tag; if it does, it is
(or at least used to be) dereferenced. */
if ((pi != NULL && pi->name_mem_tag != NULL)
|| v_ann->symbol_mem_tag)
|| symbol_mem_tag (SSA_NAME_VAR (ptr)))
return true;
FOR_EACH_IMM_USE_FAST (use_p, imm_iter, ptr)

View File

@ -1436,9 +1436,13 @@ struct tree_opt_pass pass_ccp =
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
TODO_cleanup_cfg | TODO_dump_func | TODO_update_ssa
| TODO_ggc_collect | TODO_verify_ssa
| TODO_verify_stmts | TODO_update_smt_usage, /* todo_flags_finish */
TODO_cleanup_cfg
| TODO_dump_func
| TODO_update_ssa
| TODO_ggc_collect
| TODO_verify_ssa
| TODO_verify_stmts
| TODO_update_smt_usage, /* todo_flags_finish */
0 /* letter */
};
@ -1474,10 +1478,13 @@ struct tree_opt_pass pass_store_ccp =
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
TODO_dump_func | TODO_update_ssa
| TODO_ggc_collect | TODO_verify_ssa
TODO_dump_func
| TODO_update_ssa
| TODO_ggc_collect
| TODO_verify_ssa
| TODO_cleanup_cfg
| TODO_verify_stmts | TODO_update_smt_usage, /* todo_flags_finish */
| TODO_verify_stmts
| TODO_update_smt_usage, /* todo_flags_finish */
0 /* letter */
};
@ -2512,7 +2519,7 @@ convert_to_gimple_builtin (block_stmt_iterator *si_p, tree expr, bool ignore)
tree new_stmt = tsi_stmt (ti);
find_new_referenced_vars (tsi_stmt_ptr (ti));
bsi_insert_before (si_p, new_stmt, BSI_NEW_STMT);
mark_new_vars_to_rename (bsi_stmt (*si_p));
mark_symbols_for_renaming (new_stmt);
bsi_next (si_p);
}
@ -2574,6 +2581,8 @@ execute_fold_all_builtins (void)
print_generic_stmt (dump_file, *stmtp, dump_flags);
}
push_stmt_changes (stmtp);
if (!set_rhs (stmtp, result))
{
result = convert_to_gimple_builtin (&i, result,
@ -2582,11 +2591,12 @@ execute_fold_all_builtins (void)
if (result)
{
bool ok = set_rhs (stmtp, result);
gcc_assert (ok);
}
}
mark_new_vars_to_rename (*stmtp);
pop_stmt_changes (stmtp);
if (maybe_clean_or_replace_eh_stmt (old_stmt, *stmtp)
&& tree_purge_dead_eh_edges (bb))
cfg_changed = true;

View File

@ -101,7 +101,11 @@ static VEC(tree,heap) *avail_exprs_stack;
expressions are removed from AVAIL_EXPRS. Else we may change the
hash code for an expression and be unable to find/remove it from
AVAIL_EXPRS. */
static VEC(tree,heap) *stmts_to_rescan;
typedef tree *tree_p;
DEF_VEC_P(tree_p);
DEF_VEC_ALLOC_P(tree_p,heap);
static VEC(tree_p,heap) *stmts_to_rescan;
/* Structure for entries in the expression hash table.
@ -247,7 +251,7 @@ tree_ssa_dominator_optimize (void)
avail_exprs = htab_create (1024, real_avail_expr_hash, avail_expr_eq, free);
avail_exprs_stack = VEC_alloc (tree, heap, 20);
const_and_copies_stack = VEC_alloc (tree, heap, 20);
stmts_to_rescan = VEC_alloc (tree, heap, 20);
stmts_to_rescan = VEC_alloc (tree_p, heap, 20);
need_eh_cleanup = BITMAP_ALLOC (NULL);
/* Setup callbacks for the generic dominator tree walker. */
@ -359,7 +363,7 @@ tree_ssa_dominator_optimize (void)
VEC_free (tree, heap, avail_exprs_stack);
VEC_free (tree, heap, const_and_copies_stack);
VEC_free (tree, heap, stmts_to_rescan);
VEC_free (tree_p, heap, stmts_to_rescan);
return 0;
}
@ -701,16 +705,17 @@ dom_opt_finalize_block (struct dom_walk_data *walk_data, basic_block bb)
/* If we queued any statements to rescan in this block, then
go ahead and rescan them now. */
while (VEC_length (tree, stmts_to_rescan) > 0)
while (VEC_length (tree_p, stmts_to_rescan) > 0)
{
tree stmt = VEC_last (tree, stmts_to_rescan);
tree *stmt_p = VEC_last (tree_p, stmts_to_rescan);
tree stmt = *stmt_p;
basic_block stmt_bb = bb_for_stmt (stmt);
if (stmt_bb != bb)
break;
VEC_pop (tree, stmts_to_rescan);
mark_new_vars_to_rename (stmt);
VEC_pop (tree_p, stmts_to_rescan);
pop_stmt_changes (stmt_p);
}
}
@ -1557,9 +1562,7 @@ eliminate_redundant_computations (tree stmt)
Detect and record those equivalences. */
static void
record_equivalences_from_stmt (tree stmt,
int may_optimize_p,
stmt_ann_t ann)
record_equivalences_from_stmt (tree stmt, int may_optimize_p, stmt_ann_t ann)
{
tree lhs = GIMPLE_STMT_OPERAND (stmt, 0);
enum tree_code lhs_code = TREE_CODE (lhs);
@ -1588,6 +1591,7 @@ record_equivalences_from_stmt (tree stmt,
vops and recording the result in the available expression table,
we may be able to expose more redundant loads. */
if (!ann->has_volatile_ops
&& stmt_references_memory_p (stmt)
&& (TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 1)) == SSA_NAME
|| is_gimple_min_invariant (GIMPLE_STMT_OPERAND (stmt, 1)))
&& !is_gimple_reg (lhs))
@ -1621,7 +1625,7 @@ record_equivalences_from_stmt (tree stmt,
/* Build a new statement with the RHS and LHS exchanged. */
new = build2_gimple (GIMPLE_MODIFY_STMT, rhs, lhs);
create_ssa_artficial_load_stmt (new, stmt);
create_ssa_artificial_load_stmt (new, stmt);
/* Finally enter the statement into the available expression
table. */
@ -1741,7 +1745,7 @@ cprop_operand (tree stmt, use_operand_p op_p)
known value for that SSA_NAME (or NULL if no value is known).
Propagate values from CONST_AND_COPIES into the uses, vuses and
v_may_def_ops of STMT. */
vdef_ops of STMT. */
static bool
cprop_into_stmt (tree stmt)
@ -1793,6 +1797,7 @@ optimize_stmt (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
ann = stmt_ann (stmt);
opt_stats.num_stmts++;
may_have_exposed_new_symbols = false;
push_stmt_changes (bsi_stmt_ptr (si));
if (dump_file && (dump_flags & TDF_DETAILS))
{
@ -1800,7 +1805,7 @@ optimize_stmt (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
print_generic_stmt (dump_file, stmt, TDF_SLIM);
}
/* Const/copy propagate into USES, VUSES and the RHS of V_MAY_DEFs. */
/* Const/copy propagate into USES, VUSES and the RHS of VDEFs. */
may_have_exposed_new_symbols = cprop_into_stmt (stmt);
/* If the statement has been modified with constant replacements,
@ -1856,9 +1861,7 @@ optimize_stmt (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
/* Record any additional equivalences created by this statement. */
if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT)
record_equivalences_from_stmt (stmt,
may_optimize_p,
ann);
record_equivalences_from_stmt (stmt, may_optimize_p, ann);
/* If STMT is a COND_EXPR and it was modified, then we may know
where it goes. If that is the case, then mark the CFG as altered.
@ -1885,7 +1888,6 @@ optimize_stmt (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
Ultimately I suspect we're going to need to change the interface
into the SSA_NAME manager. */
if (ann->modified)
{
tree val = NULL;
@ -1909,7 +1911,20 @@ optimize_stmt (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
}
if (may_have_exposed_new_symbols)
VEC_safe_push (tree, heap, stmts_to_rescan, bsi_stmt (si));
{
/* Queue the statement to be re-scanned after all the
AVAIL_EXPRS have been processed. The change buffer stack for
all the pushed statements will be processed when this queue
is emptied. */
VEC_safe_push (tree_p, heap, stmts_to_rescan, bsi_stmt_ptr (si));
}
else
{
/* Otherwise, just discard the recently pushed change buffer. If
not, the STMTS_TO_RESCAN queue will get out of synch with the
change buffer stack. */
discard_stmt_changes (bsi_stmt_ptr (si));
}
}
/* Search for an existing instance of STMT in the AVAIL_EXPRS table. If
@ -2185,6 +2200,8 @@ propagate_rhs_into_lhs (tree stmt, tree lhs, tree rhs, bitmap interesting_names)
fprintf (dump_file, "\n");
}
push_stmt_changes (&use_stmt);
/* Propagate the RHS into this use of the LHS. */
FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
propagate_value (use_p, rhs);
@ -2219,6 +2236,8 @@ propagate_rhs_into_lhs (tree stmt, tree lhs, tree rhs, bitmap interesting_names)
tree result = get_lhs_or_phi_result (use_stmt);
bitmap_set_bit (interesting_names, SSA_NAME_VERSION (result));
}
discard_stmt_changes (&use_stmt);
continue;
}
@ -2231,7 +2250,7 @@ propagate_rhs_into_lhs (tree stmt, tree lhs, tree rhs, bitmap interesting_names)
/* Sometimes propagation can expose new operands to the
renamer. Note this will call update_stmt at the
appropriate time. */
mark_new_vars_to_rename (use_stmt);
pop_stmt_changes (&use_stmt);
/* Dump details. */
if (dump_file && (dump_flags & TDF_DETAILS))

View File

@ -586,7 +586,7 @@ tidy_after_forward_propagate_addr (tree stmt)
if (TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 1)) == ADDR_EXPR)
recompute_tree_invariant_for_addr_expr (GIMPLE_STMT_OPERAND (stmt, 1));
mark_new_vars_to_rename (stmt);
mark_symbols_for_renaming (stmt);
}
/* STMT defines LHS which is contains the address of the 0th element
@ -856,9 +856,13 @@ forward_propagate_addr_expr (tree stmt, bool *some)
continue;
}
push_stmt_changes (&use_stmt);
result = forward_propagate_addr_expr_1 (stmt, use_stmt, some);
*some |= result;
all &= result;
pop_stmt_changes (&use_stmt);
}
return all;
@ -1051,8 +1055,9 @@ struct tree_opt_pass pass_forwprop = {
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
TODO_dump_func /* todo_flags_finish */
TODO_dump_func
| TODO_ggc_collect
| TODO_update_ssa | TODO_verify_ssa,
0 /* letter */
| TODO_update_ssa
| TODO_verify_ssa, /* todo_flags_finish */
0 /* letter */
};

View File

@ -5556,7 +5556,7 @@ get_ref_tag (tree ref, tree orig)
}
var = SSA_NAME_VAR (var);
tag = var_ann (var)->symbol_mem_tag;
tag = symbol_mem_tag (var);
gcc_assert (tag != NULL_TREE);
return tag;
}
@ -5565,7 +5565,7 @@ get_ref_tag (tree ref, tree orig)
if (!DECL_P (var))
return NULL_TREE;
tag = var_ann (var)->symbol_mem_tag;
tag = symbol_mem_tag (var);
if (tag)
return tag;
@ -5657,9 +5657,10 @@ rewrite_use_compare (struct ivopts_data *data,
/* Rewrites USE using candidate CAND. */
static void
rewrite_use (struct ivopts_data *data,
struct iv_use *use, struct iv_cand *cand)
rewrite_use (struct ivopts_data *data, struct iv_use *use, struct iv_cand *cand)
{
push_stmt_changes (&use->stmt);
switch (use->type)
{
case USE_NONLINEAR_EXPR:
@ -5677,7 +5678,8 @@ rewrite_use (struct ivopts_data *data,
default:
gcc_unreachable ();
}
mark_new_vars_to_rename (use->stmt);
pop_stmt_changes (&use->stmt);
}
/* Rewrite the uses using the selected induction variables. */

View File

@ -121,6 +121,49 @@ static void get_expr_operands (tree, tree *, int);
/* Number of functions with initialized ssa_operands. */
static int n_initialized = 0;
/* Statement change buffer. Data structure used to record state
information for statements. This is used to determine what needs
to be done in order to update the SSA web after a statement is
modified by a pass. If STMT is a statement that has just been
created, or needs to be folded via fold_stmt, or anything that
changes its physical structure then the pass should:
1- Call push_stmt_changes (&stmt) to record the current state of
STMT before any modifications are made.
2- Make all appropriate modifications to the statement.
3- Call pop_stmt_changes (&stmt) to find new symbols that
need to be put in SSA form, SSA name mappings for names that
have disappeared, recompute invariantness for address
expressions, cleanup EH information, etc.
If it is possible to determine that the statement was not modified,
instead of calling pop_stmt_changes it is quicker to call
discard_stmt_changes to avoid the expensive and unnecessary operand
re-scan and change comparison. */
struct scb_d
{
/* Pointer to the statement being modified. */
tree *stmt_p;
/* If the statement references memory these are the sets of symbols
loaded and stored by the statement. */
bitmap loads;
bitmap stores;
};
typedef struct scb_d *scb_t;
DEF_VEC_P(scb_t);
DEF_VEC_ALLOC_P(scb_t,heap);
/* Stack of statement change buffers (SCB). Every call to
push_stmt_changes pushes a new buffer onto the stack. Calls to
pop_stmt_changes pop a buffer off of the stack and compute the set
of changes for the popped statement. */
static VEC(scb_t,heap) *scb_stack;
/* Allocates operand OP of given TYPE from the appropriate free list,
or of the new value if the list is empty. */
@ -2277,7 +2320,7 @@ copy_virtual_operands (tree dest, tree src)
values stored. */
void
create_ssa_artficial_load_stmt (tree new_stmt, tree old_stmt)
create_ssa_artificial_load_stmt (tree new_stmt, tree old_stmt)
{
stmt_ann_t ann;
tree op;
@ -2567,3 +2610,206 @@ debug_immediate_uses_for (tree var)
{
dump_immediate_uses_for (stderr, var);
}
/* Create a new change buffer for the statement pointed by STMT_P and
push the buffer into SCB_STACK. Each change buffer
records state information needed to determine what changed in the
statement. Mainly, this keeps track of symbols that may need to be
put into SSA form, SSA name replacements and other information
needed to keep the SSA form up to date. */
void
push_stmt_changes (tree *stmt_p)
{
tree stmt;
scb_t buf;
stmt = *stmt_p;
/* It makes no sense to keep track of PHI nodes. */
if (TREE_CODE (stmt) == PHI_NODE)
return;
buf = xmalloc (sizeof *buf);
memset (buf, 0, sizeof *buf);
buf->stmt_p = stmt_p;
if (stmt_references_memory_p (stmt))
{
tree op;
ssa_op_iter i;
FOR_EACH_SSA_TREE_OPERAND (op, stmt, i, SSA_OP_VUSE)
{
tree sym = TREE_CODE (op) == SSA_NAME ? SSA_NAME_VAR (op) : op;
if (buf->loads == NULL)
buf->loads = BITMAP_ALLOC (NULL);
bitmap_set_bit (buf->loads, DECL_UID (sym));
}
FOR_EACH_SSA_TREE_OPERAND (op, stmt, i, SSA_OP_VIRTUAL_DEFS)
{
tree sym = TREE_CODE (op) == SSA_NAME ? SSA_NAME_VAR (op) : op;
if (buf->stores == NULL)
buf->stores = BITMAP_ALLOC (NULL);
bitmap_set_bit (buf->stores, DECL_UID (sym));
}
}
VEC_safe_push (scb_t, heap, scb_stack, buf);
}
/* Given two sets S1 and S2, mark the symbols that differ in S1 and S2
for renaming. The set to mark for renaming is (S1 & ~S2) | (S2 & ~S1). */
static void
mark_difference_for_renaming (bitmap s1, bitmap s2)
{
if (s1 == NULL && s2 == NULL)
return;
if (s1 && s2 == NULL)
mark_set_for_renaming (s1);
else if (s1 == NULL && s2)
mark_set_for_renaming (s2);
else if (!bitmap_equal_p (s1, s2))
{
bitmap t1 = BITMAP_ALLOC (NULL);
bitmap t2 = BITMAP_ALLOC (NULL);
bitmap_and_compl (t1, s1, s2);
bitmap_and_compl (t2, s2, s1);
bitmap_ior_into (t1, t2);
mark_set_for_renaming (t1);
BITMAP_FREE (t1);
BITMAP_FREE (t2);
}
}
/* Pop the top SCB from SCB_STACK and act on the differences between
what was recorded by push_stmt_changes and the current state of
the statement. */
void
pop_stmt_changes (tree *stmt_p)
{
tree op, stmt;
ssa_op_iter iter;
bitmap loads, stores;
scb_t buf;
stmt = *stmt_p;
/* It makes no sense to keep track of PHI nodes. */
if (TREE_CODE (stmt) == PHI_NODE)
return;
buf = VEC_pop (scb_t, scb_stack);
gcc_assert (stmt_p == buf->stmt_p);
/* Force an operand re-scan on the statement and mark any newly
exposed variables. */
update_stmt (stmt);
/* Determine whether any memory symbols need to be renamed. If the
sets of loads and stores are different after the statement is
modified, then the affected symbols need to be renamed.
Note that it may be possible for the statement to not reference
memory anymore, but we still need to act on the differences in
the sets of symbols. */
loads = stores = NULL;
if (stmt_references_memory_p (stmt))
{
tree op;
ssa_op_iter i;
FOR_EACH_SSA_TREE_OPERAND (op, stmt, i, SSA_OP_VUSE)
{
tree sym = TREE_CODE (op) == SSA_NAME ? SSA_NAME_VAR (op) : op;
if (loads == NULL)
loads = BITMAP_ALLOC (NULL);
bitmap_set_bit (loads, DECL_UID (sym));
}
FOR_EACH_SSA_TREE_OPERAND (op, stmt, i, SSA_OP_VIRTUAL_DEFS)
{
tree sym = TREE_CODE (op) == SSA_NAME ? SSA_NAME_VAR (op) : op;
if (stores == NULL)
stores = BITMAP_ALLOC (NULL);
bitmap_set_bit (stores, DECL_UID (sym));
/* If a V_MAY_DEF turned into a V_MUST_DEF, we will keep
referencing the same symbol, but we still need to mark it
for renaming since the operand scanner stripped its
SSA_NAME. */
if (op == sym)
mark_sym_for_renaming (sym);
}
}
/* If LOADS is different from BUF->LOADS, the affected
symbols need to be marked for renaming. */
mark_difference_for_renaming (loads, buf->loads);
/* Similarly for STORES and BUF->STORES. */
mark_difference_for_renaming (stores, buf->stores);
/* Mark all the naked GIMPLE register operands for renaming. */
FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_DEF|SSA_OP_USE)
if (DECL_P (op))
mark_sym_for_renaming (op);
/* FIXME, need to add more finalizers here. Cleanup EH info,
recompute invariants for address expressions, add
SSA replacement mappings, etc. For instance, given
testsuite/gcc.c-torture/compile/pr16808.c, we fold a statement of
the form:
# SMT.4_20 = VDEF <SMT.4_16>
D.1576_11 = 1.0e+0;
So, the VDEF will disappear, but instead of marking SMT.4 for
renaming it would be far more efficient to establish a
replacement mapping that would replace every reference of
SMT.4_20 with SMT.4_16. */
/* Free memory used by the buffer. */
BITMAP_FREE (buf->loads);
BITMAP_FREE (buf->stores);
BITMAP_FREE (loads);
BITMAP_FREE (stores);
buf->stmt_p = NULL;
free (buf);
}
/* Discard the topmost change buffer from SCB_STACK. This is useful
when the caller realized that it did not actually modified the
statement. It avoids the expensive operand re-scan. */
void
discard_stmt_changes (tree *stmt_p)
{
scb_t buf;
tree stmt;
/* It makes no sense to keep track of PHI nodes. */
stmt = *stmt_p;
if (TREE_CODE (stmt) == PHI_NODE)
return;
buf = VEC_pop (scb_t, scb_stack);
gcc_assert (stmt_p == buf->stmt_p);
/* Free memory used by the buffer. */
BITMAP_FREE (buf->loads);
BITMAP_FREE (buf->stores);
buf->stmt_p = NULL;
free (buf);
}

View File

@ -171,7 +171,7 @@ extern void update_stmt_operands (tree);
extern bool verify_imm_links (FILE *f, tree var);
extern void copy_virtual_operands (tree, tree);
extern void create_ssa_artficial_load_stmt (tree, tree);
extern void create_ssa_artificial_load_stmt (tree, tree);
extern void dump_immediate_uses (FILE *file);
extern void dump_immediate_uses_for (FILE *file, tree var);
@ -181,6 +181,9 @@ extern void debug_immediate_uses_for (tree var);
extern bool ssa_operands_active (void);
extern void add_to_addressable_set (tree, bitmap *);
extern void push_stmt_changes (tree *);
extern void pop_stmt_changes (tree *);
extern void discard_stmt_changes (tree *);
enum ssa_op_iter_type {
ssa_op_iter_none = 0,

View File

@ -2616,7 +2616,7 @@ create_expression_by_pieces (basic_block block, tree expr, tree stmts)
vn_add (forcedname, val);
bitmap_value_replace_in_set (NEW_SETS (block), forcedname);
bitmap_value_replace_in_set (AVAIL_OUT (block), forcedname);
mark_new_vars_to_rename (stmt);
mark_symbols_for_renaming (stmt);
}
tsi = tsi_last (stmts);
tsi_link_after (&tsi, forced_stmts, TSI_CONTINUE_LINKING);
@ -2644,7 +2644,9 @@ create_expression_by_pieces (basic_block block, tree expr, tree stmts)
tsi = tsi_last (stmts);
tsi_link_after (&tsi, newexpr, TSI_CONTINUE_LINKING);
VEC_safe_push (tree, heap, inserted_exprs, newexpr);
mark_new_vars_to_rename (newexpr);
/* All the symbols in NEWEXPR should be put into SSA form. */
mark_symbols_for_renaming (newexpr);
/* Add a value handle to the temporary.
The value may already exist in either NEW_SETS, or AVAIL_OUT, because
@ -3543,7 +3545,7 @@ insert_fake_stores (void)
lhs = make_ssa_name (storetemp, new);
GIMPLE_STMT_OPERAND (new, 0) = lhs;
create_ssa_artficial_load_stmt (new, stmt);
create_ssa_artificial_load_stmt (new, stmt);
NECESSARY (new) = 0;
VEC_safe_push (tree, heap, inserted_exprs, new);

View File

@ -1176,6 +1176,9 @@ substitute_and_fold (prop_value_t *prop_value, bool use_ranges_p)
&& TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 1)) == ASSERT_EXPR)
continue;
/* Record the state of the statement before replacements. */
push_stmt_changes (bsi_stmt_ptr (i));
/* Replace the statement with its folded version and mark it
folded. */
did_replace = false;
@ -1211,10 +1214,6 @@ substitute_and_fold (prop_value_t *prop_value, bool use_ranges_p)
fold_stmt (bsi_stmt_ptr (i));
stmt = bsi_stmt (i);
/* If we folded a builtin function, we'll likely
need to rename VDEFs. */
mark_new_vars_to_rename (stmt);
/* If we cleaned up EH information from the statement,
remove EH edges. */
if (maybe_clean_or_replace_eh_stmt (old_stmt, stmt))
@ -1232,6 +1231,14 @@ substitute_and_fold (prop_value_t *prop_value, bool use_ranges_p)
print_generic_stmt (dump_file, stmt, TDF_SLIM);
fprintf (dump_file, "\n");
}
/* Determine what needs to be done to update the SSA form. */
pop_stmt_changes (bsi_stmt_ptr (i));
}
else
{
/* The statement was not modified, discard the change buffer. */
discard_stmt_changes (bsi_stmt_ptr (i));
}
/* Some statements may be simplified using ranges. For
@ -1242,7 +1249,6 @@ substitute_and_fold (prop_value_t *prop_value, bool use_ranges_p)
statement. */
if (use_ranges_p)
simplify_stmt_using_ranges (stmt);
}
}

View File

@ -264,7 +264,7 @@ get_rank (tree e)
int i;
if (TREE_CODE (SSA_NAME_VAR (e)) == PARM_DECL
&& e == gimple_default_def (cfun, SSA_NAME_VAR (e)))
&& SSA_NAME_IS_DEFAULT_DEF (e))
return find_operand_rank (e)->rank;
stmt = SSA_NAME_DEF_STMT (e);

View File

@ -152,6 +152,7 @@ make_ssa_name (tree var, tree stmt)
SSA_NAME_DEF_STMT (t) = stmt;
SSA_NAME_PTR_INFO (t) = NULL;
SSA_NAME_IN_FREE_LIST (t) = 0;
SSA_NAME_IS_DEFAULT_DEF (t) = 0;
imm = &(SSA_NAME_IMM_USE_NODE (t));
imm->use = NULL;
imm->prev = imm;
@ -178,7 +179,7 @@ release_ssa_name (tree var)
/* Never release the default definition for a symbol. It's a
special SSA name that should always exist once it's created. */
if (var == gimple_default_def (cfun, SSA_NAME_VAR (var)))
if (SSA_NAME_IS_DEFAULT_DEF (var))
return;
/* If VAR has been registered for SSA updating, don't remove it.

View File

@ -3162,7 +3162,7 @@ vect_permute_load_chain (VEC(tree,heap) *dr_chain,
data_ref = make_ssa_name (perm_dest, perm_stmt);
GIMPLE_STMT_OPERAND (perm_stmt, 0) = data_ref;
vect_finish_stmt_generation (stmt, perm_stmt, bsi);
mark_new_vars_to_rename (perm_stmt);
mark_symbols_for_renaming (perm_stmt);
VEC_replace (tree, *result_chain, j/2, data_ref);
@ -3176,7 +3176,7 @@ vect_permute_load_chain (VEC(tree,heap) *dr_chain,
data_ref = make_ssa_name (perm_dest, perm_stmt);
GIMPLE_STMT_OPERAND (perm_stmt, 0) = data_ref;
vect_finish_stmt_generation (stmt, perm_stmt, bsi);
mark_new_vars_to_rename (perm_stmt);
mark_symbols_for_renaming (perm_stmt);
VEC_replace (tree, *result_chain, j/2+length/2, data_ref);
}
@ -3540,7 +3540,7 @@ vectorizable_load (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt)
GIMPLE_STMT_OPERAND (new_stmt, 0) = new_temp;
vect_finish_stmt_generation (stmt, new_stmt, bsi);
copy_virtual_operands (new_stmt, stmt);
mark_new_vars_to_rename (new_stmt);
mark_symbols_for_renaming (new_stmt);
/* 3. Handle explicit realignment if necessary/supported. */
if (alignment_support_cheme == dr_unaligned_software_pipeline)

View File

@ -273,7 +273,7 @@ get_value_range (tree var)
/* If VAR is a default definition, the variable can take any value
in VAR's type. */
sym = SSA_NAME_VAR (var);
if (var == gimple_default_def (cfun, sym))
if (SSA_NAME_IS_DEFAULT_DEF (var))
{
/* Try to use the "nonnull" attribute to create ~[0, 0]
anti-ranges for pointers. Note that this is only valid with

View File

@ -7306,6 +7306,9 @@ is_global_var (tree t)
bool
needs_to_live_in_memory (tree t)
{
if (TREE_CODE (t) == SSA_NAME)
t = SSA_NAME_VAR (t);
return (TREE_ADDRESSABLE (t)
|| is_global_var (t)
|| (TREE_CODE (t) == RESULT_DECL

View File

@ -1762,6 +1762,14 @@ struct tree_exp GTY(())
#define SSA_NAME_IN_FREE_LIST(NODE) \
SSA_NAME_CHECK (NODE)->base.nothrow_flag
/* Nonzero if this SSA_NAME is the default definition for the
underlying symbol. A default SSA name is created for symbol S if
the very first reference to S in the function is a read operation.
Default definitions are always created by an empty statement and
belong to no basic block. */
#define SSA_NAME_IS_DEFAULT_DEF(NODE) \
SSA_NAME_CHECK (NODE)->base.volatile_flag
/* Attributes for SSA_NAMEs for pointer-type variables. */
#define SSA_NAME_PTR_INFO(N) \
SSA_NAME_CHECK (N)->ssa_name.ptr_info