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:
parent
7f46c638e6
commit
cfaab3a924
24 changed files with 498 additions and 170 deletions
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
124
gcc/tree-dfa.c
124
gcc/tree-dfa.c
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue