re PR tree-optimization/17133 (wrong code with -ftree-lim)
2004-10-27 Daniel Berlin <dberlin@dberlin.org> Fix PR tree-optimization/17133 * tree-cfg.c (rewrite_to_new_ssa_names_bb): Also rewrite must def kill operand. * tree-flow-inline.h: V_MUST_DEF_OP became V_MUST_DEF_RESULT. (get_v_must_def_result_ptr): Modify for new structure of v_must_defs array. (get_v_must_def_kill_ptr): New. (op_iter_next_use): Add support for the kill that occurs in V_MUST_DEFs. (op_iter_next_tree): Ditto. Also V_MAY_DEF_OP became V_MAY_DEF_RESULT. (op_iter_next_def): V_MAY_DEF_OP became V_MAY_DEF_RESULT. (op_iter_init): Initialize new mustu members. (op_iter_next_mustdef): New function. (op_iter_init_mustdef): Ditto. * tree-flow.h (rewrite_def_def_chains): New function. * tree-into-ssa.c (mark_def_sites): Handle mustdefkill operands. (ssa_mark_def_sites): Ditto. (rewrite_stmt): Ditto. (ssa_rewrite_stmt): Ditto. (rewrite_blocks): Factor out from rewrite_into_ssa. (mark_def_block_sites): Ditto. (rewrite_def_def_chains): New function, just rewrites def-def chains without phi node insertion. * tree-pass.h (TODO_fix_def_def_chains): New todo flag. * tree-optimize.c (execute_todo): Handle TODO_fix_def_def_chains. * tree-pretty-print.c (dump_vops): Print out MUST_DEF's so that they include the rhs now. * tree-ssa-ccp.c (visit_assignment): V_MUST_DEF_OP became V_MUST_DEF_RESULT. * tree-ssa-dce.c (mark_operand_necessary): Add phionly argument. Update callers. (mark_really_necessary_kill_operand_phis): New function. (perform_tree_ssa_dce): Call it. (pass_dce): Add TODO_fix_def_def_chains. (pass_cd_dce): Ditto. * tree-ssa-loop-im.c (determine_max_movement): Look at kills as well. (rewrite_mem_refs): Ditto. * tree-ssa-loop-manip.c (find_uses_to_rename_stmt): Look at kills as well. * tree-ssa-operands.c (allocate_v_may_def_optype): v_may_def_operand_type_t became v_def_use_operand_type_t. (allocate_v_must_def_optype) Ditto. (finalize_ssa_v_must_defs): Update for new operand type, as well as setting the use portion as well. (copy_virtual_operands): Copy the kill operand as well. (create_ssa_artficial_load_stmt): V_MUST_DEF_OP became V_MUST_DEF_RESULT. * tree-ssa-operands.h (v_may_def_operand_type): Renamed to v_def_use_operand_type. (v_must_def_optype_d): Use v_def_use_operand_type. (V_MUST_DEF_OP_*): Renamed to V_MUST_DEF_RESULT_* (V_MUST_DEF_KILL_*): New macros. (struct ssa_operand_iterator_d): Add num_v_mustu and v_mustu_i members. Rename existing must_i and num_v_must members to mustd_i and num_v_mustd. (SSA_OP_VMUSTDEFKILL): New flag. (SSA_OP_VIRTUAL_KILLS): New flag. (SSA_OP_ALL_OPERANDS): Add in SSA_OP_ALL_KILLS. (SSA_OP_ALL_KILLS): New flag. (FOR_EACH_SSA_MUSTDEF_OPERAND): New macro. * tree-ssa.c (verify_ssa): Verify virtual kills as well. * tree-vectorizer.c (vect_create_data_ref_ptr): V_MUST_DEF_OP became V_MUST_DEF_RESULT. (rename_variables_in_bb): Rename kill pointer as well. * tree-dfa.c (compute_immediate_uses_for_stmt): Add kills into the immediate uses. From-SVN: r89695
This commit is contained in:
parent
47a3c2dcc6
commit
52328bf6c8
@ -1,3 +1,89 @@
|
||||
2004-10-27 Daniel Berlin <dberlin@dberlin.org>
|
||||
|
||||
Fix PR tree-optimization/17133
|
||||
|
||||
* tree-cfg.c (rewrite_to_new_ssa_names_bb): Also rewrite must
|
||||
def kill operand.
|
||||
|
||||
* tree-flow-inline.h: V_MUST_DEF_OP became V_MUST_DEF_RESULT.
|
||||
(get_v_must_def_result_ptr): Modify for new structure of
|
||||
v_must_defs array.
|
||||
(get_v_must_def_kill_ptr): New.
|
||||
(op_iter_next_use): Add support for the kill that occurs in V_MUST_DEFs.
|
||||
(op_iter_next_tree): Ditto. Also V_MAY_DEF_OP became V_MAY_DEF_RESULT.
|
||||
(op_iter_next_def): V_MAY_DEF_OP became V_MAY_DEF_RESULT.
|
||||
(op_iter_init): Initialize new mustu members.
|
||||
(op_iter_next_mustdef): New function.
|
||||
(op_iter_init_mustdef): Ditto.
|
||||
|
||||
* tree-flow.h (rewrite_def_def_chains): New function.
|
||||
|
||||
* tree-into-ssa.c (mark_def_sites): Handle mustdefkill operands.
|
||||
(ssa_mark_def_sites): Ditto.
|
||||
(rewrite_stmt): Ditto.
|
||||
(ssa_rewrite_stmt): Ditto.
|
||||
(rewrite_blocks): Factor out from rewrite_into_ssa.
|
||||
(mark_def_block_sites): Ditto.
|
||||
(rewrite_def_def_chains): New function, just rewrites def-def
|
||||
chains without phi node insertion.
|
||||
|
||||
* tree-pass.h (TODO_fix_def_def_chains): New todo flag.
|
||||
|
||||
* tree-optimize.c (execute_todo): Handle TODO_fix_def_def_chains.
|
||||
|
||||
* tree-pretty-print.c (dump_vops): Print out MUST_DEF's so that
|
||||
they include the rhs now.
|
||||
|
||||
* tree-ssa-ccp.c (visit_assignment): V_MUST_DEF_OP became
|
||||
V_MUST_DEF_RESULT.
|
||||
|
||||
* tree-ssa-dce.c (mark_operand_necessary): Add phionly argument.
|
||||
Update callers.
|
||||
(mark_really_necessary_kill_operand_phis): New function.
|
||||
(perform_tree_ssa_dce): Call it.
|
||||
(pass_dce): Add TODO_fix_def_def_chains.
|
||||
(pass_cd_dce): Ditto.
|
||||
|
||||
* tree-ssa-loop-im.c (determine_max_movement): Look at kills as
|
||||
well.
|
||||
(rewrite_mem_refs): Ditto.
|
||||
|
||||
* tree-ssa-loop-manip.c (find_uses_to_rename_stmt): Look at kills
|
||||
as well.
|
||||
|
||||
* tree-ssa-operands.c (allocate_v_may_def_optype):
|
||||
v_may_def_operand_type_t became v_def_use_operand_type_t.
|
||||
(allocate_v_must_def_optype) Ditto.
|
||||
(finalize_ssa_v_must_defs): Update for new operand type, as well
|
||||
as setting the use portion as well.
|
||||
(copy_virtual_operands): Copy the kill operand as well.
|
||||
(create_ssa_artficial_load_stmt): V_MUST_DEF_OP became
|
||||
V_MUST_DEF_RESULT.
|
||||
|
||||
* tree-ssa-operands.h (v_may_def_operand_type): Renamed to
|
||||
v_def_use_operand_type.
|
||||
(v_must_def_optype_d): Use v_def_use_operand_type.
|
||||
(V_MUST_DEF_OP_*): Renamed to V_MUST_DEF_RESULT_*
|
||||
(V_MUST_DEF_KILL_*): New macros.
|
||||
(struct ssa_operand_iterator_d): Add num_v_mustu and v_mustu_i
|
||||
members.
|
||||
Rename existing must_i and num_v_must members to mustd_i and
|
||||
num_v_mustd.
|
||||
(SSA_OP_VMUSTDEFKILL): New flag.
|
||||
(SSA_OP_VIRTUAL_KILLS): New flag.
|
||||
(SSA_OP_ALL_OPERANDS): Add in SSA_OP_ALL_KILLS.
|
||||
(SSA_OP_ALL_KILLS): New flag.
|
||||
(FOR_EACH_SSA_MUSTDEF_OPERAND): New macro.
|
||||
|
||||
* tree-ssa.c (verify_ssa): Verify virtual kills as well.
|
||||
|
||||
* tree-vectorizer.c (vect_create_data_ref_ptr): V_MUST_DEF_OP
|
||||
became V_MUST_DEF_RESULT.
|
||||
(rename_variables_in_bb): Rename kill pointer as well.
|
||||
|
||||
* tree-dfa.c (compute_immediate_uses_for_stmt): Add kills into the
|
||||
immediate uses.
|
||||
|
||||
2004-10-27 Richard Sandiford <rsandifo@redhat.com>
|
||||
|
||||
* dbxout.c (dbxout_source_line): Move declaration of begin_label to
|
||||
|
@ -4542,8 +4542,12 @@ rewrite_to_new_ssa_names_bb (basic_block bb, htab_t map)
|
||||
|
||||
v_must_defs = V_MUST_DEF_OPS (ann);
|
||||
for (i = 0; i < NUM_V_MUST_DEFS (v_must_defs); i++)
|
||||
rewrite_to_new_ssa_names_def
|
||||
(V_MUST_DEF_OP_PTR (v_must_defs, i), stmt, map);
|
||||
{
|
||||
rewrite_to_new_ssa_names_def
|
||||
(V_MUST_DEF_RESULT_PTR (v_must_defs, i), stmt, map);
|
||||
rewrite_to_new_ssa_names_use
|
||||
(V_MUST_DEF_KILL_PTR (v_must_defs, i), map);
|
||||
}
|
||||
}
|
||||
|
||||
FOR_EACH_EDGE (e, ei, bb->succs)
|
||||
|
@ -312,7 +312,14 @@ compute_immediate_uses_for_stmt (tree stmt, int flags, bool (*calc_for)(tree))
|
||||
if (!IS_EMPTY_STMT (imm_rdef_stmt) && (!calc_for || calc_for (use)))
|
||||
add_immediate_use (imm_rdef_stmt, stmt);
|
||||
}
|
||||
}
|
||||
|
||||
FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_ALL_KILLS)
|
||||
{
|
||||
tree imm_rdef_stmt = SSA_NAME_DEF_STMT (use);
|
||||
if (!IS_EMPTY_STMT (imm_rdef_stmt) && (!calc_for || calc_for (use)))
|
||||
add_immediate_use (imm_rdef_stmt, stmt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -267,14 +267,25 @@ get_vuse_op_ptr(vuse_optype vuses, unsigned int index)
|
||||
return op;
|
||||
}
|
||||
|
||||
/* Return a def_operand_p that is the V_MUST_DEF_OP for the
|
||||
/* Return a def_operand_p that is the V_MUST_DEF_RESULT for the
|
||||
V_MUST_DEF at INDEX in the V_MUST_DEFS array. */
|
||||
static inline def_operand_p
|
||||
get_v_must_def_op_ptr (v_must_def_optype v_must_defs, unsigned int index)
|
||||
get_v_must_def_result_ptr (v_must_def_optype v_must_defs, unsigned int index)
|
||||
{
|
||||
def_operand_p op;
|
||||
gcc_assert (index < v_must_defs->num_v_must_defs);
|
||||
op.def = &(v_must_defs->v_must_defs[index]);
|
||||
op.def = &(v_must_defs->v_must_defs[index].def);
|
||||
return op;
|
||||
}
|
||||
|
||||
/* Return a use_operand_p that is the V_MUST_DEF_KILL for the
|
||||
V_MUST_DEF at INDEX in the V_MUST_DEFS array. */
|
||||
static inline use_operand_p
|
||||
get_v_must_def_kill_ptr (v_must_def_optype v_must_defs, unsigned int index)
|
||||
{
|
||||
use_operand_p op;
|
||||
gcc_assert (index < v_must_defs->num_v_must_defs);
|
||||
op.use = &(v_must_defs->v_must_defs[index].use);
|
||||
return op;
|
||||
}
|
||||
|
||||
@ -670,7 +681,12 @@ op_iter_next_use (ssa_op_iter *ptr)
|
||||
if (ptr->v_mayu_i < ptr->num_v_mayu)
|
||||
{
|
||||
return V_MAY_DEF_OP_PTR (ptr->ops->v_may_def_ops,
|
||||
(ptr->v_mayu_i)++);
|
||||
(ptr->v_mayu_i)++);
|
||||
}
|
||||
if (ptr->v_mustu_i < ptr->num_v_mustu)
|
||||
{
|
||||
return V_MUST_DEF_KILL_PTR (ptr->ops->v_must_def_ops,
|
||||
(ptr->v_mustu_i)++);
|
||||
}
|
||||
ptr->done = true;
|
||||
return NULL_USE_OPERAND_P;
|
||||
@ -684,10 +700,10 @@ op_iter_next_def (ssa_op_iter *ptr)
|
||||
{
|
||||
return DEF_OP_PTR (ptr->ops->def_ops, (ptr->def_i)++);
|
||||
}
|
||||
if (ptr->v_must_i < ptr->num_v_must)
|
||||
if (ptr->v_mustd_i < ptr->num_v_mustd)
|
||||
{
|
||||
return V_MUST_DEF_OP_PTR (ptr->ops->v_must_def_ops,
|
||||
(ptr->v_must_i)++);
|
||||
return V_MUST_DEF_RESULT_PTR (ptr->ops->v_must_def_ops,
|
||||
(ptr->v_mustd_i)++);
|
||||
}
|
||||
if (ptr->v_mayd_i < ptr->num_v_mayd)
|
||||
{
|
||||
@ -714,14 +730,18 @@ op_iter_next_tree (ssa_op_iter *ptr)
|
||||
{
|
||||
return V_MAY_DEF_OP (ptr->ops->v_may_def_ops, (ptr->v_mayu_i)++);
|
||||
}
|
||||
if (ptr->v_mustu_i < ptr->num_v_mustu)
|
||||
{
|
||||
return V_MUST_DEF_KILL (ptr->ops->v_must_def_ops, (ptr->v_mustu_i)++);
|
||||
}
|
||||
if (ptr->def_i < ptr->num_def)
|
||||
{
|
||||
return DEF_OP (ptr->ops->def_ops, (ptr->def_i)++);
|
||||
}
|
||||
if (ptr->v_must_i < ptr->num_v_must)
|
||||
if (ptr->v_mustd_i < ptr->num_v_mustd)
|
||||
{
|
||||
return V_MUST_DEF_OP (ptr->ops->v_must_def_ops,
|
||||
(ptr->v_must_i)++);
|
||||
return V_MUST_DEF_RESULT (ptr->ops->v_must_def_ops,
|
||||
(ptr->v_mustd_i)++);
|
||||
}
|
||||
if (ptr->v_mayd_i < ptr->num_v_mayd)
|
||||
{
|
||||
@ -749,14 +769,17 @@ op_iter_init (ssa_op_iter *ptr, tree stmt, int flags)
|
||||
? NUM_V_MAY_DEFS (ops->v_may_def_ops) : 0;
|
||||
ptr->num_v_mayd = (flags & SSA_OP_VMAYDEF)
|
||||
? NUM_V_MAY_DEFS (ops->v_may_def_ops) : 0;
|
||||
ptr->num_v_must = (flags & SSA_OP_VMUSTDEF)
|
||||
ptr->num_v_mustu = (flags & SSA_OP_VMUSTDEFKILL)
|
||||
? NUM_V_MUST_DEFS (ops->v_must_def_ops) : 0;
|
||||
ptr->num_v_mustd = (flags & SSA_OP_VMUSTDEF)
|
||||
? NUM_V_MUST_DEFS (ops->v_must_def_ops) : 0;
|
||||
ptr->def_i = 0;
|
||||
ptr->use_i = 0;
|
||||
ptr->vuse_i = 0;
|
||||
ptr->v_mayu_i = 0;
|
||||
ptr->v_mayd_i = 0;
|
||||
ptr->v_must_i = 0;
|
||||
ptr->v_mustu_i = 0;
|
||||
ptr->v_mustd_i = 0;
|
||||
}
|
||||
|
||||
/* Initialize iterator PTR to the use operands in STMT based on FLAGS. Return
|
||||
@ -786,6 +809,25 @@ op_iter_init_tree (ssa_op_iter *ptr, tree stmt, int flags)
|
||||
return op_iter_next_tree (ptr);
|
||||
}
|
||||
|
||||
/* Get the next iterator mustdef value for PTR, returning the mustdef values in
|
||||
KILL and DEF. */
|
||||
static inline void
|
||||
op_iter_next_mustdef (use_operand_p *kill, def_operand_p *def, ssa_op_iter *ptr)
|
||||
{
|
||||
if (ptr->v_mustu_i < ptr->num_v_mustu)
|
||||
{
|
||||
*def = V_MUST_DEF_RESULT_PTR (ptr->ops->v_must_def_ops, ptr->v_mustu_i);
|
||||
*kill = V_MUST_DEF_KILL_PTR (ptr->ops->v_must_def_ops, (ptr->v_mustu_i)++);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
*def = NULL_DEF_OPERAND_P;
|
||||
*kill = NULL_USE_OPERAND_P;
|
||||
}
|
||||
ptr->done = true;
|
||||
return;
|
||||
}
|
||||
/* Get the next iterator maydef value for PTR, returning the maydef values in
|
||||
USE and DEF. */
|
||||
static inline void
|
||||
@ -815,4 +857,14 @@ op_iter_init_maydef (ssa_op_iter *ptr, tree stmt, use_operand_p *use,
|
||||
op_iter_init (ptr, stmt, SSA_OP_VMAYUSE);
|
||||
op_iter_next_maydef (use, def, ptr);
|
||||
}
|
||||
|
||||
/* Initialize iterator PTR to the operands in STMT. Return the first operands
|
||||
in KILL and DEF. */
|
||||
static inline void
|
||||
op_iter_init_mustdef (ssa_op_iter *ptr, tree stmt, use_operand_p *kill,
|
||||
def_operand_p *def)
|
||||
{
|
||||
op_iter_init (ptr, stmt, SSA_OP_VMUSTDEFKILL);
|
||||
op_iter_next_mustdef (kill, def, ptr);
|
||||
}
|
||||
#endif /* _TREE_FLOW_INLINE_H */
|
||||
|
@ -583,6 +583,7 @@ extern void kill_redundant_phi_nodes (void);
|
||||
/* In tree-into-ssa.c */
|
||||
extern void rewrite_into_ssa (bool);
|
||||
extern void rewrite_ssa_into_ssa (void);
|
||||
extern void rewrite_def_def_chains (void);
|
||||
|
||||
void compute_global_livein (bitmap, bitmap);
|
||||
tree duplicate_ssa_name (tree, tree);
|
||||
|
@ -379,13 +379,13 @@ mark_def_sites (struct dom_walk_data *walk_data,
|
||||
/* If a variable is used before being set, then the variable is live
|
||||
across a block boundary, so mark it live-on-entry to BB. */
|
||||
|
||||
FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE | SSA_OP_VUSE)
|
||||
FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE | SSA_OP_VUSE | SSA_OP_VMUSTDEFKILL)
|
||||
{
|
||||
if (prepare_use_operand_for_rename (use_p, &uid)
|
||||
&& !TEST_BIT (kills, uid))
|
||||
set_livein_block (USE_FROM_PTR (use_p), bb);
|
||||
}
|
||||
|
||||
|
||||
/* Note that virtual definitions are irrelevant for computing KILLS
|
||||
because a V_MAY_DEF does not constitute a killing definition of the
|
||||
variable. However, the operand of a virtual definitions is a use
|
||||
@ -438,7 +438,7 @@ ssa_mark_def_sites (struct dom_walk_data *walk_data,
|
||||
|
||||
/* If a variable is used before being set, then the variable is live
|
||||
across a block boundary, so mark it live-on-entry to BB. */
|
||||
FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_ALL_USES)
|
||||
FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_ALL_USES | SSA_OP_ALL_KILLS)
|
||||
{
|
||||
uid = SSA_NAME_VERSION (use);
|
||||
|
||||
@ -1077,7 +1077,7 @@ rewrite_stmt (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
|
||||
gcc_assert (!ann->modified);
|
||||
|
||||
/* Step 1. Rewrite USES and VUSES in the statement. */
|
||||
FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_ALL_USES)
|
||||
FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_ALL_USES | SSA_OP_ALL_KILLS)
|
||||
rewrite_operand (use_p);
|
||||
|
||||
/* Step 2. Register the statement's DEF and VDEF operands. */
|
||||
@ -1121,7 +1121,7 @@ ssa_rewrite_stmt (struct dom_walk_data *walk_data,
|
||||
gcc_assert (!ann->modified);
|
||||
|
||||
/* Step 1. Rewrite USES and VUSES in the statement. */
|
||||
FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_ALL_USES)
|
||||
FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_ALL_USES | SSA_OP_ALL_KILLS)
|
||||
{
|
||||
if (TEST_BIT (names_to_rename, SSA_NAME_VERSION (USE_FROM_PTR (use_p))))
|
||||
SET_USE (use_p, get_reaching_def (USE_FROM_PTR (use_p)));
|
||||
@ -1382,84 +1382,70 @@ invalidate_name_tags (bitmap vars_to_rename)
|
||||
}
|
||||
}
|
||||
|
||||
/* Rewrite the actual blocks, statements, and phi arguments, to be in SSA
|
||||
form. ADD_PHI_ARGS is true if we should be adding arguments to phi nodes,
|
||||
because they may have been just inserted. */
|
||||
|
||||
/* Main entry point into the SSA builder. The renaming process
|
||||
proceeds in five main phases:
|
||||
|
||||
1- If VARS_TO_RENAME has any entries, any existing PHI nodes for
|
||||
those variables are removed from the flow graph so that they can
|
||||
be computed again.
|
||||
|
||||
2- Compute dominance frontier and immediate dominators, needed to
|
||||
insert PHI nodes and rename the function in dominator tree
|
||||
order.
|
||||
|
||||
3- Find and mark all the blocks that define variables
|
||||
(mark_def_sites).
|
||||
|
||||
4- Insert PHI nodes at dominance frontiers (insert_phi_nodes).
|
||||
|
||||
5- Rename all the blocks (rewrite_initialize_block,
|
||||
rewrite_add_phi_arguments) and statements in the program
|
||||
(rewrite_stmt).
|
||||
|
||||
Steps 3 and 5 are done using the dominator tree walker
|
||||
(walk_dominator_tree).
|
||||
|
||||
ALL is true if all variables should be renamed (otherwise just those
|
||||
mentioned in vars_to_rename are taken into account). */
|
||||
|
||||
void
|
||||
rewrite_into_ssa (bool all)
|
||||
static void
|
||||
rewrite_blocks (bool add_phi_args)
|
||||
{
|
||||
bitmap *dfs;
|
||||
basic_block bb;
|
||||
struct dom_walk_data walk_data;
|
||||
|
||||
/* Rewrite all the basic blocks in the program. */
|
||||
timevar_push (TV_TREE_SSA_REWRITE_BLOCKS);
|
||||
|
||||
/* Setup callbacks for the generic dominator tree walker. */
|
||||
walk_data.walk_stmts_backward = false;
|
||||
walk_data.dom_direction = CDI_DOMINATORS;
|
||||
walk_data.initialize_block_local_data = NULL;
|
||||
walk_data.before_dom_children_before_stmts = rewrite_initialize_block;
|
||||
walk_data.before_dom_children_walk_stmts = rewrite_stmt;
|
||||
walk_data.before_dom_children_after_stmts = NULL;
|
||||
if (add_phi_args)
|
||||
walk_data.before_dom_children_after_stmts = rewrite_add_phi_arguments;
|
||||
walk_data.after_dom_children_before_stmts = NULL;
|
||||
walk_data.after_dom_children_walk_stmts = NULL;
|
||||
walk_data.after_dom_children_after_stmts = rewrite_finalize_block;
|
||||
walk_data.global_data = NULL;
|
||||
walk_data.block_local_data_size = 0;
|
||||
|
||||
VARRAY_TREE_INIT (block_defs_stack, 10, "Block DEFS Stack");
|
||||
|
||||
/* Initialize the dominator walker. */
|
||||
init_walk_dominator_tree (&walk_data);
|
||||
|
||||
/* Recursively walk the dominator tree rewriting each statement in
|
||||
each basic block. */
|
||||
walk_dominator_tree (&walk_data, ENTRY_BLOCK_PTR);
|
||||
|
||||
/* Finalize the dominator walker. */
|
||||
fini_walk_dominator_tree (&walk_data);
|
||||
|
||||
htab_delete (def_blocks);
|
||||
|
||||
timevar_pop (TV_TREE_SSA_REWRITE_BLOCKS);
|
||||
}
|
||||
|
||||
/* Mark the definition site blocks for each variable, so that we know where
|
||||
the variable is actually live. */
|
||||
|
||||
static void
|
||||
mark_def_site_blocks (void)
|
||||
{
|
||||
size_t i;
|
||||
struct dom_walk_data walk_data;
|
||||
struct mark_def_sites_global_data mark_def_sites_global_data;
|
||||
bitmap old_vars_to_rename = vars_to_rename;
|
||||
unsigned i;
|
||||
|
||||
timevar_push (TV_TREE_SSA_OTHER);
|
||||
|
||||
if (all)
|
||||
vars_to_rename = NULL;
|
||||
else
|
||||
{
|
||||
/* Initialize the array of variables to rename. */
|
||||
gcc_assert (vars_to_rename);
|
||||
|
||||
if (bitmap_first_set_bit (vars_to_rename) < 0)
|
||||
{
|
||||
timevar_pop (TV_TREE_SSA_OTHER);
|
||||
return;
|
||||
}
|
||||
|
||||
invalidate_name_tags (vars_to_rename);
|
||||
|
||||
/* Now remove all the existing PHI nodes (if any) for the variables
|
||||
that we are about to rename into SSA. */
|
||||
remove_all_phi_nodes_for (vars_to_rename);
|
||||
}
|
||||
|
||||
/* Allocate memory for the DEF_BLOCKS hash table. */
|
||||
def_blocks = htab_create (VARRAY_ACTIVE_SIZE (referenced_vars),
|
||||
def_blocks_hash, def_blocks_eq, def_blocks_free);
|
||||
|
||||
/* Initialize dominance frontier and immediate dominator bitmaps.
|
||||
Also count the number of predecessors for each block. Doing so
|
||||
can save significant time during PHI insertion for large graphs. */
|
||||
dfs = (bitmap *) xmalloc (last_basic_block * sizeof (bitmap *));
|
||||
FOR_EACH_BB (bb)
|
||||
dfs[bb->index] = BITMAP_XMALLOC ();
|
||||
|
||||
for (i = 0; i < num_referenced_vars; i++)
|
||||
set_current_def (referenced_var (i), NULL_TREE);
|
||||
|
||||
/* Ensure that the dominance information is OK. */
|
||||
calculate_dominance_info (CDI_DOMINATORS);
|
||||
|
||||
/* Compute dominance frontiers. */
|
||||
compute_dominance_frontiers (dfs);
|
||||
|
||||
/* Setup callbacks for the generic dominator tree walker to find and
|
||||
mark definition sites. */
|
||||
@ -1494,38 +1480,76 @@ rewrite_into_ssa (bool all)
|
||||
/* We no longer need this bitmap, clear and free it. */
|
||||
sbitmap_free (mark_def_sites_global_data.kills);
|
||||
|
||||
}
|
||||
/* Main entry point into the SSA builder. The renaming process
|
||||
proceeds in five main phases:
|
||||
|
||||
1- If VARS_TO_RENAME has any entries, any existing PHI nodes for
|
||||
those variables are removed from the flow graph so that they can
|
||||
be computed again.
|
||||
|
||||
2- Compute dominance frontier and immediate dominators, needed to
|
||||
insert PHI nodes and rename the function in dominator tree
|
||||
order.
|
||||
|
||||
3- Find and mark all the blocks that define variables
|
||||
(mark_def_site_blocks).
|
||||
|
||||
4- Insert PHI nodes at dominance frontiers (insert_phi_nodes).
|
||||
|
||||
5- Rename all the blocks (rewrite_blocks) and statements in the program.
|
||||
|
||||
Steps 3 and 5 are done using the dominator tree walker
|
||||
(walk_dominator_tree).
|
||||
|
||||
ALL is true if all variables should be renamed (otherwise just those
|
||||
mentioned in vars_to_rename are taken into account). */
|
||||
|
||||
void
|
||||
rewrite_into_ssa (bool all)
|
||||
{
|
||||
bitmap *dfs;
|
||||
basic_block bb;
|
||||
bitmap old_vars_to_rename = vars_to_rename;
|
||||
|
||||
timevar_push (TV_TREE_SSA_OTHER);
|
||||
|
||||
if (all)
|
||||
vars_to_rename = NULL;
|
||||
else
|
||||
{
|
||||
/* Initialize the array of variables to rename. */
|
||||
gcc_assert (vars_to_rename);
|
||||
|
||||
if (bitmap_first_set_bit (vars_to_rename) < 0)
|
||||
{
|
||||
timevar_pop (TV_TREE_SSA_OTHER);
|
||||
return;
|
||||
}
|
||||
|
||||
invalidate_name_tags (vars_to_rename);
|
||||
|
||||
/* Now remove all the existing PHI nodes (if any) for the variables
|
||||
that we are about to rename into SSA. */
|
||||
remove_all_phi_nodes_for (vars_to_rename);
|
||||
}
|
||||
|
||||
mark_def_site_blocks ();
|
||||
|
||||
/* Initialize dominance frontier and immediate dominator bitmaps.
|
||||
Also count the number of predecessors for each block. Doing so
|
||||
can save significant time during PHI insertion for large graphs. */
|
||||
dfs = (bitmap *) xmalloc (last_basic_block * sizeof (bitmap *));
|
||||
FOR_EACH_BB (bb)
|
||||
dfs[bb->index] = BITMAP_XMALLOC ();
|
||||
|
||||
/* Compute dominance frontiers. */
|
||||
compute_dominance_frontiers (dfs);
|
||||
|
||||
/* Insert PHI nodes at dominance frontiers of definition blocks. */
|
||||
insert_phi_nodes (dfs, NULL);
|
||||
|
||||
/* Rewrite all the basic blocks in the program. */
|
||||
timevar_push (TV_TREE_SSA_REWRITE_BLOCKS);
|
||||
|
||||
/* Setup callbacks for the generic dominator tree walker. */
|
||||
walk_data.walk_stmts_backward = false;
|
||||
walk_data.dom_direction = CDI_DOMINATORS;
|
||||
walk_data.initialize_block_local_data = NULL;
|
||||
walk_data.before_dom_children_before_stmts = rewrite_initialize_block;
|
||||
walk_data.before_dom_children_walk_stmts = rewrite_stmt;
|
||||
walk_data.before_dom_children_after_stmts = rewrite_add_phi_arguments;
|
||||
walk_data.after_dom_children_before_stmts = NULL;
|
||||
walk_data.after_dom_children_walk_stmts = NULL;
|
||||
walk_data.after_dom_children_after_stmts = rewrite_finalize_block;
|
||||
walk_data.global_data = NULL;
|
||||
walk_data.block_local_data_size = 0;
|
||||
|
||||
VARRAY_TREE_INIT (block_defs_stack, 10, "Block DEFS Stack");
|
||||
|
||||
/* Initialize the dominator walker. */
|
||||
init_walk_dominator_tree (&walk_data);
|
||||
|
||||
/* Recursively walk the dominator tree rewriting each statement in
|
||||
each basic block. */
|
||||
walk_dominator_tree (&walk_data, ENTRY_BLOCK_PTR);
|
||||
|
||||
/* Finalize the dominator walker. */
|
||||
fini_walk_dominator_tree (&walk_data);
|
||||
|
||||
timevar_pop (TV_TREE_SSA_REWRITE_BLOCKS);
|
||||
rewrite_blocks (true);
|
||||
|
||||
/* Debugging dumps. */
|
||||
if (dump_file && (dump_flags & TDF_STATS))
|
||||
@ -1539,12 +1563,22 @@ rewrite_into_ssa (bool all)
|
||||
BITMAP_XFREE (dfs[bb->index]);
|
||||
free (dfs);
|
||||
|
||||
htab_delete (def_blocks);
|
||||
|
||||
vars_to_rename = old_vars_to_rename;
|
||||
timevar_pop (TV_TREE_SSA_OTHER);
|
||||
}
|
||||
|
||||
/* Rewrite the def-def chains so that they have the correct reaching
|
||||
definitions. */
|
||||
|
||||
void
|
||||
rewrite_def_def_chains (void)
|
||||
{
|
||||
/* Ensure that the dominance information is OK. */
|
||||
calculate_dominance_info (CDI_DOMINATORS);
|
||||
mark_def_site_blocks ();
|
||||
rewrite_blocks (false);
|
||||
|
||||
}
|
||||
/* The marked ssa names may have more than one definition;
|
||||
add phi nodes and rewrite them to fix this. */
|
||||
|
||||
|
@ -420,6 +420,11 @@ execute_todo (int properties, unsigned int flags)
|
||||
rewrite_into_ssa (false);
|
||||
bitmap_clear (vars_to_rename);
|
||||
}
|
||||
if (flags & TODO_fix_def_def_chains)
|
||||
{
|
||||
rewrite_def_def_chains ();
|
||||
bitmap_clear (vars_to_rename);
|
||||
}
|
||||
|
||||
if ((flags & TODO_dump_func) && dump_file)
|
||||
{
|
||||
|
@ -106,6 +106,7 @@ struct dump_file_info
|
||||
#define TODO_verify_ssa (1 << 3)
|
||||
#define TODO_verify_flow (1 << 4)
|
||||
#define TODO_verify_stmts (1 << 5)
|
||||
#define TODO_fix_def_def_chains (1 << 6) /* rewrite def-def chains */
|
||||
|
||||
#define TODO_verify_all \
|
||||
(TODO_verify_ssa | TODO_verify_flow | TODO_verify_stmts)
|
||||
|
@ -2131,9 +2131,10 @@ newline_and_indent (pretty_printer *buffer, int spc)
|
||||
static void
|
||||
dump_vops (pretty_printer *buffer, tree stmt, int spc, int flags)
|
||||
{
|
||||
tree use, def;
|
||||
tree use;
|
||||
use_operand_p use_p;
|
||||
def_operand_p def_p;
|
||||
use_operand_p kill_p;
|
||||
ssa_op_iter iter;
|
||||
|
||||
FOR_EACH_SSA_MAYDEF_OPERAND (def_p, use_p, stmt, iter)
|
||||
@ -2148,10 +2149,14 @@ dump_vops (pretty_printer *buffer, tree stmt, int spc, int flags)
|
||||
newline_and_indent (buffer, spc);
|
||||
}
|
||||
|
||||
FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_VMUSTDEF)
|
||||
FOR_EACH_SSA_MUSTDEF_OPERAND (def_p, kill_p, stmt, iter)
|
||||
{
|
||||
pp_string (buffer, "# V_MUST_DEF <");
|
||||
dump_generic_node (buffer, def, spc + 2, flags, false);
|
||||
pp_string (buffer, "# ");
|
||||
dump_generic_node (buffer, DEF_FROM_PTR (def_p),
|
||||
spc + 2, flags, false);
|
||||
pp_string (buffer, " = V_MUST_DEF <");
|
||||
dump_generic_node (buffer, USE_FROM_PTR (kill_p),
|
||||
spc + 2, flags, false);
|
||||
pp_string (buffer, ">;");
|
||||
newline_and_indent (buffer, spc);
|
||||
}
|
||||
|
@ -1041,7 +1041,7 @@ visit_assignment (tree stmt, tree *output_p)
|
||||
{
|
||||
/* If we make it here, then stmt only has one definition:
|
||||
a V_MUST_DEF. */
|
||||
lhs = V_MUST_DEF_OP (v_must_defs, 0);
|
||||
lhs = V_MUST_DEF_RESULT (v_must_defs, 0);
|
||||
}
|
||||
|
||||
if (TREE_CODE (rhs) == SSA_NAME)
|
||||
|
@ -112,7 +112,7 @@ static void find_control_dependence (struct edge_list *, int);
|
||||
static inline basic_block find_pdom (basic_block);
|
||||
|
||||
static inline void mark_stmt_necessary (tree, bool);
|
||||
static inline void mark_operand_necessary (tree);
|
||||
static inline void mark_operand_necessary (tree, bool);
|
||||
|
||||
static void mark_stmt_if_obviously_necessary (tree, bool);
|
||||
static void find_obviously_necessary_stmts (struct edge_list *);
|
||||
@ -234,10 +234,11 @@ mark_stmt_necessary (tree stmt, bool add_to_worklist)
|
||||
VARRAY_PUSH_TREE (worklist, stmt);
|
||||
}
|
||||
|
||||
/* Mark the statement defining operand OP as necessary. */
|
||||
/* Mark the statement defining operand OP as necessary. PHIONLY is true
|
||||
if we should only mark it necessary if it is a phi node. */
|
||||
|
||||
static inline void
|
||||
mark_operand_necessary (tree op)
|
||||
mark_operand_necessary (tree op, bool phionly)
|
||||
{
|
||||
tree stmt;
|
||||
int ver;
|
||||
@ -253,7 +254,8 @@ mark_operand_necessary (tree op)
|
||||
gcc_assert (stmt);
|
||||
|
||||
if (NECESSARY (stmt)
|
||||
|| IS_EMPTY_STMT (stmt))
|
||||
|| IS_EMPTY_STMT (stmt)
|
||||
|| (phionly && TREE_CODE (stmt) != PHI_NODE))
|
||||
return;
|
||||
|
||||
NECESSARY (stmt) = 1;
|
||||
@ -592,7 +594,7 @@ propagate_necessity (struct edge_list *el)
|
||||
{
|
||||
tree arg = PHI_ARG_DEF (i, k);
|
||||
if (TREE_CODE (arg) == SSA_NAME)
|
||||
mark_operand_necessary (arg);
|
||||
mark_operand_necessary (arg, false);
|
||||
}
|
||||
|
||||
if (aggressive)
|
||||
@ -624,11 +626,79 @@ propagate_necessity (struct edge_list *el)
|
||||
links). */
|
||||
|
||||
FOR_EACH_SSA_TREE_OPERAND (use, i, iter, SSA_OP_ALL_USES)
|
||||
mark_operand_necessary (use);
|
||||
mark_operand_necessary (use, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Propagate necessity around virtual phi nodes used in kill operands.
|
||||
The reason this isn't done during propagate_necessity is because we don't
|
||||
want to keep phis around that are just there for must-defs, unless we
|
||||
absolutely have to. After we've rewritten the reaching definitions to be
|
||||
correct in the previous part of the fixup routine, we can simply propagate
|
||||
around the information about which of these virtual phi nodes are really
|
||||
used, and set the NECESSARY flag accordingly.
|
||||
Note that we do the minimum here to ensure that we keep alive the phis that
|
||||
are actually used in the corrected SSA form. In particular, some of these
|
||||
phis may now have all of the same operand, and will be deleted by some
|
||||
other pass. */
|
||||
|
||||
static void
|
||||
mark_really_necessary_kill_operand_phis (void)
|
||||
{
|
||||
basic_block bb;
|
||||
int i;
|
||||
|
||||
/* Seed the worklist with the new virtual phi arguments and virtual
|
||||
uses */
|
||||
FOR_EACH_BB (bb)
|
||||
{
|
||||
block_stmt_iterator bsi;
|
||||
tree phi;
|
||||
|
||||
for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
|
||||
{
|
||||
if (!is_gimple_reg (PHI_RESULT (phi)) && NECESSARY (phi))
|
||||
{
|
||||
for (i = 0; i < PHI_NUM_ARGS (phi); i++)
|
||||
mark_operand_necessary (PHI_ARG_DEF (phi, i), true);
|
||||
}
|
||||
}
|
||||
|
||||
for (bsi = bsi_last (bb); !bsi_end_p (bsi); bsi_prev (&bsi))
|
||||
{
|
||||
tree stmt = bsi_stmt (bsi);
|
||||
|
||||
if (NECESSARY (stmt))
|
||||
{
|
||||
use_operand_p use_p;
|
||||
ssa_op_iter iter;
|
||||
FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter,
|
||||
SSA_OP_VIRTUAL_USES | SSA_OP_VIRTUAL_KILLS)
|
||||
{
|
||||
tree use = USE_FROM_PTR (use_p);
|
||||
mark_operand_necessary (use, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Mark all virtual phis still in use as necessary, and all of their
|
||||
arguments that are phis as necessary. */
|
||||
while (VARRAY_ACTIVE_SIZE (worklist) > 0)
|
||||
{
|
||||
tree use = VARRAY_TOP_TREE (worklist);
|
||||
VARRAY_POP (worklist);
|
||||
|
||||
for (i = 0; i < PHI_NUM_ARGS (use); i++)
|
||||
mark_operand_necessary (PHI_ARG_DEF (use, i), true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Eliminate unnecessary statements. Any instruction not marked as necessary
|
||||
contributes nothing to the program, and can be deleted. */
|
||||
|
||||
@ -640,7 +710,7 @@ eliminate_unnecessary_stmts (void)
|
||||
|
||||
if (dump_file && (dump_flags & TDF_DETAILS))
|
||||
fprintf (dump_file, "\nEliminating unnecessary statements:\n");
|
||||
|
||||
|
||||
clear_special_calls ();
|
||||
FOR_EACH_BB (bb)
|
||||
{
|
||||
@ -650,23 +720,23 @@ eliminate_unnecessary_stmts (void)
|
||||
/* Remove dead statements. */
|
||||
for (i = bsi_start (bb); ! bsi_end_p (i) ; )
|
||||
{
|
||||
tree t = bsi_stmt (i);
|
||||
tree t = bsi_stmt (i);
|
||||
|
||||
stats.total++;
|
||||
stats.total++;
|
||||
|
||||
/* If `i' is not necessary then remove it. */
|
||||
if (! NECESSARY (t))
|
||||
remove_dead_stmt (&i, bb);
|
||||
else
|
||||
{
|
||||
tree call = get_call_expr_in (t);
|
||||
if (call)
|
||||
notice_special_calls (call);
|
||||
bsi_next (&i);
|
||||
}
|
||||
/* If `i' is not necessary then remove it. */
|
||||
if (! NECESSARY (t))
|
||||
remove_dead_stmt (&i, bb);
|
||||
else
|
||||
{
|
||||
tree call = get_call_expr_in (t);
|
||||
if (call)
|
||||
notice_special_calls (call);
|
||||
bsi_next (&i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove dead PHI nodes from block BB. */
|
||||
|
||||
@ -711,6 +781,9 @@ static void
|
||||
remove_dead_stmt (block_stmt_iterator *i, basic_block bb)
|
||||
{
|
||||
tree t = bsi_stmt (*i);
|
||||
def_operand_p def_p;
|
||||
|
||||
ssa_op_iter iter;
|
||||
|
||||
if (dump_file && (dump_flags & TDF_DETAILS))
|
||||
{
|
||||
@ -765,9 +838,16 @@ remove_dead_stmt (block_stmt_iterator *i, basic_block bb)
|
||||
while (EDGE_COUNT (bb->succs) != 1)
|
||||
remove_edge (EDGE_SUCC (bb, 1));
|
||||
}
|
||||
|
||||
bsi_remove (i);
|
||||
release_defs (t);
|
||||
|
||||
FOR_EACH_SSA_DEF_OPERAND (def_p, t, iter,
|
||||
SSA_OP_VIRTUAL_DEFS | SSA_OP_VIRTUAL_KILLS)
|
||||
{
|
||||
tree def = DEF_FROM_PTR (def_p);
|
||||
bitmap_set_bit (vars_to_rename,
|
||||
var_ann (SSA_NAME_VAR (def))->uid);
|
||||
}
|
||||
bsi_remove (i);
|
||||
release_defs (t);
|
||||
}
|
||||
|
||||
/* Print out removed statement statistics. */
|
||||
@ -875,6 +955,7 @@ perform_tree_ssa_dce (bool aggressive)
|
||||
|
||||
propagate_necessity (el);
|
||||
|
||||
mark_really_necessary_kill_operand_phis ();
|
||||
eliminate_unnecessary_stmts ();
|
||||
|
||||
if (aggressive)
|
||||
@ -926,7 +1007,7 @@ struct tree_opt_pass pass_dce =
|
||||
0, /* properties_provided */
|
||||
0, /* properties_destroyed */
|
||||
0, /* todo_flags_start */
|
||||
TODO_ggc_collect | TODO_verify_ssa, /* todo_flags_finish */
|
||||
TODO_fix_def_def_chains |TODO_ggc_collect | TODO_verify_ssa, /* todo_flags_finish */
|
||||
0 /* letter */
|
||||
};
|
||||
|
||||
@ -943,7 +1024,7 @@ struct tree_opt_pass pass_cd_dce =
|
||||
0, /* properties_provided */
|
||||
0, /* properties_destroyed */
|
||||
0, /* todo_flags_start */
|
||||
TODO_ggc_collect | TODO_verify_ssa | TODO_verify_flow,
|
||||
TODO_fix_def_def_chains | TODO_ggc_collect | TODO_verify_ssa | TODO_verify_flow,
|
||||
/* todo_flags_finish */
|
||||
0 /* letter */
|
||||
};
|
||||
|
@ -436,7 +436,7 @@ determine_max_movement (tree stmt, bool must_preserve_exec)
|
||||
if (!add_dependency (val, lim_data, loop, true))
|
||||
return false;
|
||||
|
||||
FOR_EACH_SSA_TREE_OPERAND (val, stmt, iter, SSA_OP_VIRTUAL_USES)
|
||||
FOR_EACH_SSA_TREE_OPERAND (val, stmt, iter, SSA_OP_VIRTUAL_USES | SSA_OP_VIRTUAL_KILLS)
|
||||
if (!add_dependency (val, lim_data, loop, false))
|
||||
return false;
|
||||
|
||||
@ -1034,8 +1034,7 @@ rewrite_mem_refs (tree tmp_var, struct mem_ref *mem_refs)
|
||||
|
||||
for (; mem_refs; mem_refs = mem_refs->next)
|
||||
{
|
||||
FOR_EACH_SSA_TREE_OPERAND (var, mem_refs->stmt, iter,
|
||||
(SSA_OP_VIRTUAL_DEFS | SSA_OP_VUSE))
|
||||
FOR_EACH_SSA_TREE_OPERAND (var, mem_refs->stmt, iter, SSA_OP_ALL_VIRTUALS)
|
||||
{
|
||||
var = SSA_NAME_VAR (var);
|
||||
bitmap_set_bit (vars_to_rename, var_ann (var)->uid);
|
||||
|
@ -254,7 +254,7 @@ find_uses_to_rename_stmt (tree stmt, bitmap *use_blocks)
|
||||
|
||||
get_stmt_operands (stmt);
|
||||
|
||||
FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_ALL_USES)
|
||||
FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_ALL_USES | SSA_OP_ALL_KILLS)
|
||||
find_uses_to_rename_use (bb, var, use_blocks);
|
||||
}
|
||||
|
||||
|
@ -174,7 +174,7 @@ allocate_v_may_def_optype (unsigned num)
|
||||
v_may_def_optype v_may_def_ops;
|
||||
unsigned size;
|
||||
size = sizeof (struct v_may_def_optype_d)
|
||||
+ sizeof (v_may_def_operand_type_t) * (num - 1);
|
||||
+ sizeof (v_def_use_operand_type_t) * (num - 1);
|
||||
v_may_def_ops = ggc_alloc (size);
|
||||
v_may_def_ops->num_v_may_defs = num;
|
||||
return v_may_def_ops;
|
||||
@ -202,7 +202,7 @@ allocate_v_must_def_optype (unsigned num)
|
||||
{
|
||||
v_must_def_optype v_must_def_ops;
|
||||
unsigned size;
|
||||
size = sizeof (struct v_must_def_optype_d) + sizeof (tree) * (num - 1);
|
||||
size = sizeof (struct v_must_def_optype_d) + sizeof (v_def_use_operand_type_t) * (num - 1);
|
||||
v_must_def_ops = ggc_alloc (size);
|
||||
v_must_def_ops->num_v_must_defs = num;
|
||||
return v_must_def_ops;
|
||||
@ -650,7 +650,7 @@ finalize_ssa_v_must_defs (v_must_def_optype *old_ops_p,
|
||||
build_diff = false;
|
||||
for (x = 0; x < num; x++)
|
||||
{
|
||||
tree var = old_ops->v_must_defs[x];
|
||||
tree var = old_ops->v_must_defs[x].def;
|
||||
if (TREE_CODE (var) == SSA_NAME)
|
||||
var = SSA_NAME_VAR (var);
|
||||
if (var != VARRAY_TREE (build_v_must_defs, x))
|
||||
@ -677,17 +677,21 @@ finalize_ssa_v_must_defs (v_must_def_optype *old_ops_p,
|
||||
/* Look for VAR in the original vector. */
|
||||
for (i = 0; i < old_num; i++)
|
||||
{
|
||||
result = old_ops->v_must_defs[i];
|
||||
result = old_ops->v_must_defs[i].def;
|
||||
if (TREE_CODE (result) == SSA_NAME)
|
||||
result = SSA_NAME_VAR (result);
|
||||
if (result == var)
|
||||
{
|
||||
v_must_def_ops->v_must_defs[x] = old_ops->v_must_defs[i];
|
||||
v_must_def_ops->v_must_defs[x].def = old_ops->v_must_defs[i].def;
|
||||
v_must_def_ops->v_must_defs[x].use = old_ops->v_must_defs[i].use;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == old_num)
|
||||
v_must_def_ops->v_must_defs[x] = var;
|
||||
{
|
||||
v_must_def_ops->v_must_defs[x].def = var;
|
||||
v_must_def_ops->v_must_defs[x].use = var;
|
||||
}
|
||||
}
|
||||
}
|
||||
VARRAY_POP_ALL (build_v_must_defs);
|
||||
@ -1672,7 +1676,10 @@ copy_virtual_operands (tree dst, tree src)
|
||||
{
|
||||
*v_must_defs_new = allocate_v_must_def_optype (NUM_V_MUST_DEFS (v_must_defs));
|
||||
for (i = 0; i < NUM_V_MUST_DEFS (v_must_defs); i++)
|
||||
SET_V_MUST_DEF_OP (*v_must_defs_new, i, V_MUST_DEF_OP (v_must_defs, i));
|
||||
{
|
||||
SET_V_MUST_DEF_RESULT (*v_must_defs_new, i, V_MUST_DEF_RESULT (v_must_defs, i));
|
||||
SET_V_MUST_DEF_KILL (*v_must_defs_new, i, V_MUST_DEF_KILL (v_must_defs, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1701,7 +1708,7 @@ create_ssa_artficial_load_stmt (stmt_operands_p old_ops, tree new_stmt)
|
||||
free_vuses (&(ann->operands.vuse_ops));
|
||||
free_v_may_defs (&(ann->operands.v_may_def_ops));
|
||||
free_v_must_defs (&(ann->operands.v_must_def_ops));
|
||||
|
||||
|
||||
/* For each VDEF on the original statement, we want to create a
|
||||
VUSE of the V_MAY_DEF result or V_MUST_DEF op on the new
|
||||
statement. */
|
||||
@ -1713,7 +1720,7 @@ create_ssa_artficial_load_stmt (stmt_operands_p old_ops, tree new_stmt)
|
||||
|
||||
for (j = 0; j < NUM_V_MUST_DEFS (old_ops->v_must_def_ops); j++)
|
||||
{
|
||||
op = V_MUST_DEF_OP (old_ops->v_must_def_ops, j);
|
||||
op = V_MUST_DEF_RESULT (old_ops->v_must_def_ops, j);
|
||||
append_vuse (op);
|
||||
}
|
||||
|
||||
|
@ -58,17 +58,17 @@ typedef struct use_optype_d GTY(())
|
||||
typedef use_optype_t *use_optype;
|
||||
|
||||
/* Operand type which stores a def and a use tree. */
|
||||
typedef struct v_may_def_operand_type GTY(())
|
||||
typedef struct v_def_use_operand_type GTY(())
|
||||
{
|
||||
tree def;
|
||||
tree use;
|
||||
} v_may_def_operand_type_t;
|
||||
} v_def_use_operand_type_t;
|
||||
|
||||
/* This represents the MAY_DEFS for a stmt. */
|
||||
typedef struct v_may_def_optype_d GTY(())
|
||||
{
|
||||
unsigned num_v_may_defs;
|
||||
struct v_may_def_operand_type GTY((length ("%h.num_v_may_defs")))
|
||||
struct v_def_use_operand_type GTY((length ("%h.num_v_may_defs")))
|
||||
v_may_defs[1];
|
||||
} v_may_def_optype_t;
|
||||
|
||||
@ -87,7 +87,7 @@ typedef vuse_optype_t *vuse_optype;
|
||||
typedef struct v_must_def_optype_d GTY(())
|
||||
{
|
||||
unsigned num_v_must_defs;
|
||||
tree GTY((length("%h.num_v_must_defs"))) v_must_defs[1];
|
||||
v_def_use_operand_type_t GTY((length("%h.num_v_must_defs"))) v_must_defs[1];
|
||||
} v_must_def_optype_t;
|
||||
|
||||
typedef v_must_def_optype_t *v_must_def_optype;
|
||||
@ -157,12 +157,14 @@ typedef stmt_operands_t *stmt_operands_p;
|
||||
#define V_MUST_DEF_OPS(ANN) get_v_must_def_ops (ANN)
|
||||
#define STMT_V_MUST_DEF_OPS(STMT) get_v_must_def_ops (stmt_ann (STMT))
|
||||
#define NUM_V_MUST_DEFS(OPS) ((OPS) ? (OPS)->num_v_must_defs : 0)
|
||||
#define V_MUST_DEF_OP_PTR(OPS, I) get_v_must_def_op_ptr ((OPS), (I))
|
||||
#define V_MUST_DEF_OP(OPS, I) \
|
||||
(DEF_FROM_PTR (V_MUST_DEF_OP_PTR ((OPS), (I))))
|
||||
#define SET_V_MUST_DEF_OP(OPS, I, V) \
|
||||
(SET_DEF (V_MUST_DEF_OP_PTR ((OPS), (I)), (V)))
|
||||
|
||||
#define V_MUST_DEF_RESULT_PTR(OPS, I) get_v_must_def_result_ptr ((OPS), (I))
|
||||
#define V_MUST_DEF_RESULT(OPS, I) \
|
||||
(DEF_FROM_PTR (V_MUST_DEF_RESULT_PTR ((OPS), (I))))
|
||||
#define SET_V_MUST_DEF_RESULT(OPS, I, V) \
|
||||
(SET_DEF (V_MUST_DEF_RESULT_PTR ((OPS), (I)), (V)))
|
||||
#define V_MUST_DEF_KILL_PTR(OPS, I) get_v_must_def_kill_ptr ((OPS), (I))
|
||||
#define V_MUST_DEF_KILL(OPS, I) (USE_FROM_PTR (V_MUST_DEF_KILL_PTR ((OPS), (I))))
|
||||
#define SET_V_MUST_DEF_KILL(OPS, I, V) (SET_USE (V_MUST_DEF_KILL_PTR ((OPS), (I)), (V)))
|
||||
|
||||
#define PHI_RESULT_PTR(PHI) get_phi_result_ptr (PHI)
|
||||
#define PHI_RESULT(PHI) DEF_FROM_PTR (PHI_RESULT_PTR (PHI))
|
||||
@ -199,13 +201,15 @@ typedef struct ssa_operand_iterator_d
|
||||
int num_vuse;
|
||||
int num_v_mayu;
|
||||
int num_v_mayd;
|
||||
int num_v_must;
|
||||
int num_v_mustu;
|
||||
int num_v_mustd;
|
||||
int use_i;
|
||||
int def_i;
|
||||
int vuse_i;
|
||||
int v_mayu_i;
|
||||
int v_mayd_i;
|
||||
int v_must_i;
|
||||
int v_mustu_i;
|
||||
int v_mustd_i;
|
||||
stmt_operands_p ops;
|
||||
bool done;
|
||||
} ssa_op_iter;
|
||||
@ -218,13 +222,17 @@ typedef struct ssa_operand_iterator_d
|
||||
#define SSA_OP_VMAYUSE 0x08 /* USE portion of V_MAY_DEFS. */
|
||||
#define SSA_OP_VMAYDEF 0x10 /* DEF portion of V_MAY_DEFS. */
|
||||
#define SSA_OP_VMUSTDEF 0x20 /* V_MUST_DEF definitions. */
|
||||
#define SSA_OP_VMUSTDEFKILL 0x40 /* V_MUST_DEF kills. */
|
||||
|
||||
/* These are commonly grouped operand flags. */
|
||||
#define SSA_OP_VIRTUAL_USES (SSA_OP_VUSE | SSA_OP_VMAYUSE)
|
||||
#define SSA_OP_VIRTUAL_DEFS (SSA_OP_VMAYDEF | SSA_OP_VMUSTDEF)
|
||||
#define SSA_OP_VIRTUAL_KILLS (SSA_OP_VMUSTDEFKILL)
|
||||
#define SSA_OP_ALL_VIRTUALS (SSA_OP_VIRTUAL_USES | SSA_OP_VIRTUAL_KILLS | SSA_OP_VIRTUAL_DEFS)
|
||||
#define SSA_OP_ALL_USES (SSA_OP_VIRTUAL_USES | SSA_OP_USE)
|
||||
#define SSA_OP_ALL_DEFS (SSA_OP_VIRTUAL_DEFS | SSA_OP_DEF)
|
||||
#define SSA_OP_ALL_OPERANDS (SSA_OP_ALL_USES | SSA_OP_ALL_DEFS)
|
||||
#define SSA_OP_ALL_KILLS (SSA_OP_VIRTUAL_KILLS)
|
||||
#define SSA_OP_ALL_OPERANDS (SSA_OP_ALL_USES | SSA_OP_ALL_DEFS | SSA_OP_ALL_KILLS)
|
||||
|
||||
/* This macro executes a loop over the operands of STMT specified in FLAG,
|
||||
returning each operand as a 'tree' in the variable TREEVAR. ITER is an
|
||||
@ -258,4 +266,12 @@ typedef struct ssa_operand_iterator_d
|
||||
!op_iter_done (&(ITER)); \
|
||||
op_iter_next_maydef (&(USEVAR), &(DEFVAR), &(ITER)))
|
||||
|
||||
/* This macro executes a loop over the V_MUST_DEF operands of STMT. The def
|
||||
and kill for each V_MUST_DEF is returned in DEFVAR and KILLVAR.
|
||||
ITER is an ssa_op_iter structure used to control the loop. */
|
||||
#define FOR_EACH_SSA_MUSTDEF_OPERAND(DEFVAR, KILLVAR, STMT, ITER) \
|
||||
for (op_iter_init_mustdef (&(ITER), STMT, &(KILLVAR), &(DEFVAR)); \
|
||||
!op_iter_done (&(ITER)); \
|
||||
op_iter_next_mustdef (&(KILLVAR), &(DEFVAR), &(ITER)))
|
||||
|
||||
#endif /* GCC_TREE_SSA_OPERANDS_H */
|
||||
|
@ -672,7 +672,7 @@ verify_ssa (void)
|
||||
{
|
||||
tree stmt = bsi_stmt (bsi);
|
||||
|
||||
FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_VIRTUAL_USES)
|
||||
FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_VIRTUAL_USES | SSA_OP_VIRTUAL_KILLS)
|
||||
{
|
||||
if (verify_use (bb, definition_block[SSA_NAME_VERSION (op)],
|
||||
op, stmt, false, true,
|
||||
@ -1082,7 +1082,8 @@ replace_immediate_uses (tree var, tree repl)
|
||||
}
|
||||
else
|
||||
{
|
||||
FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_VIRTUAL_USES)
|
||||
FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter,
|
||||
SSA_OP_VIRTUAL_USES | SSA_OP_VIRTUAL_KILLS)
|
||||
if (USE_FROM_PTR (use_p) == var)
|
||||
propagate_value (use_p, repl);
|
||||
}
|
||||
@ -1464,3 +1465,4 @@ struct tree_opt_pass pass_late_warn_uninitialized =
|
||||
0, /* todo_flags_finish */
|
||||
0 /* letter */
|
||||
};
|
||||
|
||||
|
@ -381,7 +381,10 @@ rename_variables_in_bb (basic_block bb)
|
||||
|
||||
v_must_defs = V_MUST_DEF_OPS (ann);
|
||||
for (i = 0; i < NUM_V_MUST_DEFS (v_must_defs); i++)
|
||||
rename_def_op (V_MUST_DEF_OP_PTR (v_must_defs, i), stmt);
|
||||
{
|
||||
rename_use_op (V_MUST_DEF_KILL_PTR (v_must_defs, i));
|
||||
rename_def_op (V_MUST_DEF_RESULT_PTR (v_must_defs, i), stmt);
|
||||
}
|
||||
}
|
||||
|
||||
FOR_EACH_EDGE (e, ei, bb->succs)
|
||||
@ -1853,7 +1856,7 @@ vect_create_data_ref_ptr (tree stmt, block_stmt_iterator *bsi, tree offset,
|
||||
}
|
||||
for (i = 0; i < nv_must_defs; i++)
|
||||
{
|
||||
tree def = V_MUST_DEF_OP (v_must_defs, i);
|
||||
tree def = V_MUST_DEF_RESULT (v_must_defs, i);
|
||||
if (TREE_CODE (def) == SSA_NAME)
|
||||
bitmap_set_bit (vars_to_rename, var_ann (SSA_NAME_VAR (def))->uid);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user