Commit 52328bf6 by Daniel Berlin Committed by Daniel Berlin

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
parent 47a3c2dc
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> 2004-10-27 Richard Sandiford <rsandifo@redhat.com>
* dbxout.c (dbxout_source_line): Move declaration of begin_label to * 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) ...@@ -4542,8 +4542,12 @@ rewrite_to_new_ssa_names_bb (basic_block bb, htab_t map)
v_must_defs = V_MUST_DEF_OPS (ann); v_must_defs = V_MUST_DEF_OPS (ann);
for (i = 0; i < NUM_V_MUST_DEFS (v_must_defs); i++) 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) FOR_EACH_EDGE (e, ei, bb->succs)
......
...@@ -312,7 +312,14 @@ compute_immediate_uses_for_stmt (tree stmt, int flags, bool (*calc_for)(tree)) ...@@ -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))) if (!IS_EMPTY_STMT (imm_rdef_stmt) && (!calc_for || calc_for (use)))
add_immediate_use (imm_rdef_stmt, stmt); 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) ...@@ -267,14 +267,25 @@ get_vuse_op_ptr(vuse_optype vuses, unsigned int index)
return op; 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. */ V_MUST_DEF at INDEX in the V_MUST_DEFS array. */
static inline def_operand_p 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; def_operand_p op;
gcc_assert (index < v_must_defs->num_v_must_defs); 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; return op;
} }
...@@ -670,7 +681,12 @@ op_iter_next_use (ssa_op_iter *ptr) ...@@ -670,7 +681,12 @@ op_iter_next_use (ssa_op_iter *ptr)
if (ptr->v_mayu_i < ptr->num_v_mayu) if (ptr->v_mayu_i < ptr->num_v_mayu)
{ {
return V_MAY_DEF_OP_PTR (ptr->ops->v_may_def_ops, 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; ptr->done = true;
return NULL_USE_OPERAND_P; return NULL_USE_OPERAND_P;
...@@ -684,10 +700,10 @@ op_iter_next_def (ssa_op_iter *ptr) ...@@ -684,10 +700,10 @@ op_iter_next_def (ssa_op_iter *ptr)
{ {
return DEF_OP_PTR (ptr->ops->def_ops, (ptr->def_i)++); 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, return V_MUST_DEF_RESULT_PTR (ptr->ops->v_must_def_ops,
(ptr->v_must_i)++); (ptr->v_mustd_i)++);
} }
if (ptr->v_mayd_i < ptr->num_v_mayd) if (ptr->v_mayd_i < ptr->num_v_mayd)
{ {
...@@ -714,14 +730,18 @@ op_iter_next_tree (ssa_op_iter *ptr) ...@@ -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)++); 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) if (ptr->def_i < ptr->num_def)
{ {
return DEF_OP (ptr->ops->def_ops, (ptr->def_i)++); 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, return V_MUST_DEF_RESULT (ptr->ops->v_must_def_ops,
(ptr->v_must_i)++); (ptr->v_mustd_i)++);
} }
if (ptr->v_mayd_i < ptr->num_v_mayd) if (ptr->v_mayd_i < ptr->num_v_mayd)
{ {
...@@ -749,14 +769,17 @@ op_iter_init (ssa_op_iter *ptr, tree stmt, int flags) ...@@ -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; ? NUM_V_MAY_DEFS (ops->v_may_def_ops) : 0;
ptr->num_v_mayd = (flags & SSA_OP_VMAYDEF) ptr->num_v_mayd = (flags & SSA_OP_VMAYDEF)
? NUM_V_MAY_DEFS (ops->v_may_def_ops) : 0; ? 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; ? NUM_V_MUST_DEFS (ops->v_must_def_ops) : 0;
ptr->def_i = 0; ptr->def_i = 0;
ptr->use_i = 0; ptr->use_i = 0;
ptr->vuse_i = 0; ptr->vuse_i = 0;
ptr->v_mayu_i = 0; ptr->v_mayu_i = 0;
ptr->v_mayd_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 /* 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) ...@@ -786,6 +809,25 @@ op_iter_init_tree (ssa_op_iter *ptr, tree stmt, int flags)
return op_iter_next_tree (ptr); 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 /* Get the next iterator maydef value for PTR, returning the maydef values in
USE and DEF. */ USE and DEF. */
static inline void static inline void
...@@ -815,4 +857,14 @@ op_iter_init_maydef (ssa_op_iter *ptr, tree stmt, use_operand_p *use, ...@@ -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_init (ptr, stmt, SSA_OP_VMAYUSE);
op_iter_next_maydef (use, def, ptr); 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 */ #endif /* _TREE_FLOW_INLINE_H */
...@@ -583,6 +583,7 @@ extern void kill_redundant_phi_nodes (void); ...@@ -583,6 +583,7 @@ extern void kill_redundant_phi_nodes (void);
/* In tree-into-ssa.c */ /* In tree-into-ssa.c */
extern void rewrite_into_ssa (bool); extern void rewrite_into_ssa (bool);
extern void rewrite_ssa_into_ssa (void); extern void rewrite_ssa_into_ssa (void);
extern void rewrite_def_def_chains (void);
void compute_global_livein (bitmap, bitmap); void compute_global_livein (bitmap, bitmap);
tree duplicate_ssa_name (tree, tree); tree duplicate_ssa_name (tree, tree);
......
...@@ -379,13 +379,13 @@ mark_def_sites (struct dom_walk_data *walk_data, ...@@ -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 /* 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. */ 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) if (prepare_use_operand_for_rename (use_p, &uid)
&& !TEST_BIT (kills, uid)) && !TEST_BIT (kills, uid))
set_livein_block (USE_FROM_PTR (use_p), bb); set_livein_block (USE_FROM_PTR (use_p), bb);
} }
/* Note that virtual definitions are irrelevant for computing KILLS /* Note that virtual definitions are irrelevant for computing KILLS
because a V_MAY_DEF does not constitute a killing definition of the because a V_MAY_DEF does not constitute a killing definition of the
variable. However, the operand of a virtual definitions is a use 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, ...@@ -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 /* 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. */ 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); uid = SSA_NAME_VERSION (use);
...@@ -1077,7 +1077,7 @@ rewrite_stmt (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED, ...@@ -1077,7 +1077,7 @@ rewrite_stmt (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
gcc_assert (!ann->modified); gcc_assert (!ann->modified);
/* Step 1. Rewrite USES and VUSES in the statement. */ /* 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); rewrite_operand (use_p);
/* Step 2. Register the statement's DEF and VDEF operands. */ /* Step 2. Register the statement's DEF and VDEF operands. */
...@@ -1121,7 +1121,7 @@ ssa_rewrite_stmt (struct dom_walk_data *walk_data, ...@@ -1121,7 +1121,7 @@ ssa_rewrite_stmt (struct dom_walk_data *walk_data,
gcc_assert (!ann->modified); gcc_assert (!ann->modified);
/* Step 1. Rewrite USES and VUSES in the statement. */ /* 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)))) 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))); SET_USE (use_p, get_reaching_def (USE_FROM_PTR (use_p)));
...@@ -1382,7 +1382,105 @@ invalidate_name_tags (bitmap vars_to_rename) ...@@ -1382,7 +1382,105 @@ 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. */
static void
rewrite_blocks (bool add_phi_args)
{
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;
/* 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);
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);
/* Setup callbacks for the generic dominator tree walker to find and
mark definition sites. */
walk_data.walk_stmts_backward = false;
walk_data.dom_direction = CDI_DOMINATORS;
walk_data.initialize_block_local_data = NULL;
walk_data.before_dom_children_before_stmts = mark_def_sites_initialize_block;
walk_data.before_dom_children_walk_stmts = mark_def_sites;
walk_data.before_dom_children_after_stmts = NULL;
walk_data.after_dom_children_before_stmts = NULL;
walk_data.after_dom_children_walk_stmts = NULL;
walk_data.after_dom_children_after_stmts = NULL;
/* Notice that this bitmap is indexed using variable UIDs, so it must be
large enough to accommodate all the variables referenced in the
function, not just the ones we are renaming. */
mark_def_sites_global_data.kills = sbitmap_alloc (num_referenced_vars);
walk_data.global_data = &mark_def_sites_global_data;
/* We do not have any local data. */
walk_data.block_local_data_size = 0;
/* Initialize the dominator walker. */
init_walk_dominator_tree (&walk_data);
/* Recursively walk the dominator tree. */
walk_dominator_tree (&walk_data, ENTRY_BLOCK_PTR);
/* Finalize the dominator walker. */
fini_walk_dominator_tree (&walk_data);
/* 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 /* Main entry point into the SSA builder. The renaming process
proceeds in five main phases: proceeds in five main phases:
...@@ -1395,13 +1493,11 @@ invalidate_name_tags (bitmap vars_to_rename) ...@@ -1395,13 +1493,11 @@ invalidate_name_tags (bitmap vars_to_rename)
order. order.
3- Find and mark all the blocks that define variables 3- Find and mark all the blocks that define variables
(mark_def_sites). (mark_def_site_blocks).
4- Insert PHI nodes at dominance frontiers (insert_phi_nodes). 4- Insert PHI nodes at dominance frontiers (insert_phi_nodes).
5- Rename all the blocks (rewrite_initialize_block, 5- Rename all the blocks (rewrite_blocks) and statements in the program.
rewrite_add_phi_arguments) and statements in the program
(rewrite_stmt).
Steps 3 and 5 are done using the dominator tree walker Steps 3 and 5 are done using the dominator tree walker
(walk_dominator_tree). (walk_dominator_tree).
...@@ -1414,10 +1510,7 @@ rewrite_into_ssa (bool all) ...@@ -1414,10 +1510,7 @@ rewrite_into_ssa (bool all)
{ {
bitmap *dfs; bitmap *dfs;
basic_block bb; basic_block bb;
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; bitmap old_vars_to_rename = vars_to_rename;
unsigned i;
timevar_push (TV_TREE_SSA_OTHER); timevar_push (TV_TREE_SSA_OTHER);
...@@ -1441,9 +1534,7 @@ rewrite_into_ssa (bool all) ...@@ -1441,9 +1534,7 @@ rewrite_into_ssa (bool all)
remove_all_phi_nodes_for (vars_to_rename); remove_all_phi_nodes_for (vars_to_rename);
} }
/* Allocate memory for the DEF_BLOCKS hash table. */ mark_def_site_blocks ();
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. /* Initialize dominance frontier and immediate dominator bitmaps.
Also count the number of predecessors for each block. Doing so Also count the number of predecessors for each block. Doing so
...@@ -1452,80 +1543,13 @@ rewrite_into_ssa (bool all) ...@@ -1452,80 +1543,13 @@ rewrite_into_ssa (bool all)
FOR_EACH_BB (bb) FOR_EACH_BB (bb)
dfs[bb->index] = BITMAP_XMALLOC (); 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. */
compute_dominance_frontiers (dfs); compute_dominance_frontiers (dfs);
/* Setup callbacks for the generic dominator tree walker to find and
mark definition sites. */
walk_data.walk_stmts_backward = false;
walk_data.dom_direction = CDI_DOMINATORS;
walk_data.initialize_block_local_data = NULL;
walk_data.before_dom_children_before_stmts = mark_def_sites_initialize_block;
walk_data.before_dom_children_walk_stmts = mark_def_sites;
walk_data.before_dom_children_after_stmts = NULL;
walk_data.after_dom_children_before_stmts = NULL;
walk_data.after_dom_children_walk_stmts = NULL;
walk_data.after_dom_children_after_stmts = NULL;
/* Notice that this bitmap is indexed using variable UIDs, so it must be
large enough to accommodate all the variables referenced in the
function, not just the ones we are renaming. */
mark_def_sites_global_data.kills = sbitmap_alloc (num_referenced_vars);
walk_data.global_data = &mark_def_sites_global_data;
/* We do not have any local data. */
walk_data.block_local_data_size = 0;
/* Initialize the dominator walker. */
init_walk_dominator_tree (&walk_data);
/* Recursively walk the dominator tree. */
walk_dominator_tree (&walk_data, ENTRY_BLOCK_PTR);
/* Finalize the dominator walker. */
fini_walk_dominator_tree (&walk_data);
/* We no longer need this bitmap, clear and free it. */
sbitmap_free (mark_def_sites_global_data.kills);
/* Insert PHI nodes at dominance frontiers of definition blocks. */ /* Insert PHI nodes at dominance frontiers of definition blocks. */
insert_phi_nodes (dfs, NULL); insert_phi_nodes (dfs, NULL);
/* Rewrite all the basic blocks in the program. */ rewrite_blocks (true);
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);
/* Debugging dumps. */ /* Debugging dumps. */
if (dump_file && (dump_flags & TDF_STATS)) if (dump_file && (dump_flags & TDF_STATS))
...@@ -1539,12 +1563,22 @@ rewrite_into_ssa (bool all) ...@@ -1539,12 +1563,22 @@ rewrite_into_ssa (bool all)
BITMAP_XFREE (dfs[bb->index]); BITMAP_XFREE (dfs[bb->index]);
free (dfs); free (dfs);
htab_delete (def_blocks);
vars_to_rename = old_vars_to_rename; vars_to_rename = old_vars_to_rename;
timevar_pop (TV_TREE_SSA_OTHER); 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; /* The marked ssa names may have more than one definition;
add phi nodes and rewrite them to fix this. */ add phi nodes and rewrite them to fix this. */
......
...@@ -420,6 +420,11 @@ execute_todo (int properties, unsigned int flags) ...@@ -420,6 +420,11 @@ execute_todo (int properties, unsigned int flags)
rewrite_into_ssa (false); rewrite_into_ssa (false);
bitmap_clear (vars_to_rename); 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) if ((flags & TODO_dump_func) && dump_file)
{ {
......
...@@ -106,6 +106,7 @@ struct dump_file_info ...@@ -106,6 +106,7 @@ struct dump_file_info
#define TODO_verify_ssa (1 << 3) #define TODO_verify_ssa (1 << 3)
#define TODO_verify_flow (1 << 4) #define TODO_verify_flow (1 << 4)
#define TODO_verify_stmts (1 << 5) #define TODO_verify_stmts (1 << 5)
#define TODO_fix_def_def_chains (1 << 6) /* rewrite def-def chains */
#define TODO_verify_all \ #define TODO_verify_all \
(TODO_verify_ssa | TODO_verify_flow | TODO_verify_stmts) (TODO_verify_ssa | TODO_verify_flow | TODO_verify_stmts)
......
...@@ -2131,9 +2131,10 @@ newline_and_indent (pretty_printer *buffer, int spc) ...@@ -2131,9 +2131,10 @@ newline_and_indent (pretty_printer *buffer, int spc)
static void static void
dump_vops (pretty_printer *buffer, tree stmt, int spc, int flags) dump_vops (pretty_printer *buffer, tree stmt, int spc, int flags)
{ {
tree use, def; tree use;
use_operand_p use_p; use_operand_p use_p;
def_operand_p def_p; def_operand_p def_p;
use_operand_p kill_p;
ssa_op_iter iter; ssa_op_iter iter;
FOR_EACH_SSA_MAYDEF_OPERAND (def_p, use_p, stmt, 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) ...@@ -2148,10 +2149,14 @@ dump_vops (pretty_printer *buffer, tree stmt, int spc, int flags)
newline_and_indent (buffer, spc); 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 <"); pp_string (buffer, "# ");
dump_generic_node (buffer, def, spc + 2, flags, false); 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, ">;"); pp_string (buffer, ">;");
newline_and_indent (buffer, spc); newline_and_indent (buffer, spc);
} }
......
...@@ -1041,7 +1041,7 @@ visit_assignment (tree stmt, tree *output_p) ...@@ -1041,7 +1041,7 @@ visit_assignment (tree stmt, tree *output_p)
{ {
/* If we make it here, then stmt only has one definition: /* If we make it here, then stmt only has one definition:
a V_MUST_DEF. */ 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) if (TREE_CODE (rhs) == SSA_NAME)
......
...@@ -112,7 +112,7 @@ static void find_control_dependence (struct edge_list *, int); ...@@ -112,7 +112,7 @@ static void find_control_dependence (struct edge_list *, int);
static inline basic_block find_pdom (basic_block); static inline basic_block find_pdom (basic_block);
static inline void mark_stmt_necessary (tree, bool); 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 mark_stmt_if_obviously_necessary (tree, bool);
static void find_obviously_necessary_stmts (struct edge_list *); static void find_obviously_necessary_stmts (struct edge_list *);
...@@ -234,10 +234,11 @@ mark_stmt_necessary (tree stmt, bool add_to_worklist) ...@@ -234,10 +234,11 @@ mark_stmt_necessary (tree stmt, bool add_to_worklist)
VARRAY_PUSH_TREE (worklist, stmt); 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 static inline void
mark_operand_necessary (tree op) mark_operand_necessary (tree op, bool phionly)
{ {
tree stmt; tree stmt;
int ver; int ver;
...@@ -253,7 +254,8 @@ mark_operand_necessary (tree op) ...@@ -253,7 +254,8 @@ mark_operand_necessary (tree op)
gcc_assert (stmt); gcc_assert (stmt);
if (NECESSARY (stmt) if (NECESSARY (stmt)
|| IS_EMPTY_STMT (stmt)) || IS_EMPTY_STMT (stmt)
|| (phionly && TREE_CODE (stmt) != PHI_NODE))
return; return;
NECESSARY (stmt) = 1; NECESSARY (stmt) = 1;
...@@ -592,7 +594,7 @@ propagate_necessity (struct edge_list *el) ...@@ -592,7 +594,7 @@ propagate_necessity (struct edge_list *el)
{ {
tree arg = PHI_ARG_DEF (i, k); tree arg = PHI_ARG_DEF (i, k);
if (TREE_CODE (arg) == SSA_NAME) if (TREE_CODE (arg) == SSA_NAME)
mark_operand_necessary (arg); mark_operand_necessary (arg, false);
} }
if (aggressive) if (aggressive)
...@@ -624,11 +626,79 @@ propagate_necessity (struct edge_list *el) ...@@ -624,11 +626,79 @@ propagate_necessity (struct edge_list *el)
links). */ links). */
FOR_EACH_SSA_TREE_OPERAND (use, i, iter, SSA_OP_ALL_USES) 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 /* Eliminate unnecessary statements. Any instruction not marked as necessary
contributes nothing to the program, and can be deleted. */ contributes nothing to the program, and can be deleted. */
...@@ -640,7 +710,7 @@ eliminate_unnecessary_stmts (void) ...@@ -640,7 +710,7 @@ eliminate_unnecessary_stmts (void)
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "\nEliminating unnecessary statements:\n"); fprintf (dump_file, "\nEliminating unnecessary statements:\n");
clear_special_calls (); clear_special_calls ();
FOR_EACH_BB (bb) FOR_EACH_BB (bb)
{ {
...@@ -650,23 +720,23 @@ eliminate_unnecessary_stmts (void) ...@@ -650,23 +720,23 @@ eliminate_unnecessary_stmts (void)
/* Remove dead statements. */ /* Remove dead statements. */
for (i = bsi_start (bb); ! bsi_end_p (i) ; ) 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 `i' is not necessary then remove it. */
if (! NECESSARY (t)) if (! NECESSARY (t))
remove_dead_stmt (&i, bb); remove_dead_stmt (&i, bb);
else else
{ {
tree call = get_call_expr_in (t); tree call = get_call_expr_in (t);
if (call) if (call)
notice_special_calls (call); notice_special_calls (call);
bsi_next (&i); bsi_next (&i);
} }
} }
} }
} }
/* Remove dead PHI nodes from block BB. */ /* Remove dead PHI nodes from block BB. */
...@@ -711,6 +781,9 @@ static void ...@@ -711,6 +781,9 @@ static void
remove_dead_stmt (block_stmt_iterator *i, basic_block bb) remove_dead_stmt (block_stmt_iterator *i, basic_block bb)
{ {
tree t = bsi_stmt (*i); tree t = bsi_stmt (*i);
def_operand_p def_p;
ssa_op_iter iter;
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
{ {
...@@ -765,9 +838,16 @@ remove_dead_stmt (block_stmt_iterator *i, basic_block bb) ...@@ -765,9 +838,16 @@ remove_dead_stmt (block_stmt_iterator *i, basic_block bb)
while (EDGE_COUNT (bb->succs) != 1) while (EDGE_COUNT (bb->succs) != 1)
remove_edge (EDGE_SUCC (bb, 1)); remove_edge (EDGE_SUCC (bb, 1));
} }
bsi_remove (i); FOR_EACH_SSA_DEF_OPERAND (def_p, t, iter,
release_defs (t); 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. */ /* Print out removed statement statistics. */
...@@ -875,6 +955,7 @@ perform_tree_ssa_dce (bool aggressive) ...@@ -875,6 +955,7 @@ perform_tree_ssa_dce (bool aggressive)
propagate_necessity (el); propagate_necessity (el);
mark_really_necessary_kill_operand_phis ();
eliminate_unnecessary_stmts (); eliminate_unnecessary_stmts ();
if (aggressive) if (aggressive)
...@@ -926,7 +1007,7 @@ struct tree_opt_pass pass_dce = ...@@ -926,7 +1007,7 @@ struct tree_opt_pass pass_dce =
0, /* properties_provided */ 0, /* properties_provided */
0, /* properties_destroyed */ 0, /* properties_destroyed */
0, /* todo_flags_start */ 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 */ 0 /* letter */
}; };
...@@ -943,7 +1024,7 @@ struct tree_opt_pass pass_cd_dce = ...@@ -943,7 +1024,7 @@ struct tree_opt_pass pass_cd_dce =
0, /* properties_provided */ 0, /* properties_provided */
0, /* properties_destroyed */ 0, /* properties_destroyed */
0, /* todo_flags_start */ 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 */ /* todo_flags_finish */
0 /* letter */ 0 /* letter */
}; };
......
...@@ -436,7 +436,7 @@ determine_max_movement (tree stmt, bool must_preserve_exec) ...@@ -436,7 +436,7 @@ determine_max_movement (tree stmt, bool must_preserve_exec)
if (!add_dependency (val, lim_data, loop, true)) if (!add_dependency (val, lim_data, loop, true))
return false; 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)) if (!add_dependency (val, lim_data, loop, false))
return false; return false;
...@@ -1034,8 +1034,7 @@ rewrite_mem_refs (tree tmp_var, struct mem_ref *mem_refs) ...@@ -1034,8 +1034,7 @@ rewrite_mem_refs (tree tmp_var, struct mem_ref *mem_refs)
for (; mem_refs; mem_refs = mem_refs->next) for (; mem_refs; mem_refs = mem_refs->next)
{ {
FOR_EACH_SSA_TREE_OPERAND (var, mem_refs->stmt, iter, FOR_EACH_SSA_TREE_OPERAND (var, mem_refs->stmt, iter, SSA_OP_ALL_VIRTUALS)
(SSA_OP_VIRTUAL_DEFS | SSA_OP_VUSE))
{ {
var = SSA_NAME_VAR (var); var = SSA_NAME_VAR (var);
bitmap_set_bit (vars_to_rename, var_ann (var)->uid); bitmap_set_bit (vars_to_rename, var_ann (var)->uid);
......
...@@ -254,7 +254,7 @@ find_uses_to_rename_stmt (tree stmt, bitmap *use_blocks) ...@@ -254,7 +254,7 @@ find_uses_to_rename_stmt (tree stmt, bitmap *use_blocks)
get_stmt_operands (stmt); 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); find_uses_to_rename_use (bb, var, use_blocks);
} }
......
...@@ -174,7 +174,7 @@ allocate_v_may_def_optype (unsigned num) ...@@ -174,7 +174,7 @@ allocate_v_may_def_optype (unsigned num)
v_may_def_optype v_may_def_ops; v_may_def_optype v_may_def_ops;
unsigned size; unsigned size;
size = sizeof (struct v_may_def_optype_d) 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 = ggc_alloc (size);
v_may_def_ops->num_v_may_defs = num; v_may_def_ops->num_v_may_defs = num;
return v_may_def_ops; return v_may_def_ops;
...@@ -202,7 +202,7 @@ allocate_v_must_def_optype (unsigned num) ...@@ -202,7 +202,7 @@ allocate_v_must_def_optype (unsigned num)
{ {
v_must_def_optype v_must_def_ops; v_must_def_optype v_must_def_ops;
unsigned size; 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 = ggc_alloc (size);
v_must_def_ops->num_v_must_defs = num; v_must_def_ops->num_v_must_defs = num;
return v_must_def_ops; return v_must_def_ops;
...@@ -650,7 +650,7 @@ finalize_ssa_v_must_defs (v_must_def_optype *old_ops_p, ...@@ -650,7 +650,7 @@ finalize_ssa_v_must_defs (v_must_def_optype *old_ops_p,
build_diff = false; build_diff = false;
for (x = 0; x < num; x++) 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) if (TREE_CODE (var) == SSA_NAME)
var = SSA_NAME_VAR (var); var = SSA_NAME_VAR (var);
if (var != VARRAY_TREE (build_v_must_defs, x)) 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, ...@@ -677,17 +677,21 @@ finalize_ssa_v_must_defs (v_must_def_optype *old_ops_p,
/* Look for VAR in the original vector. */ /* Look for VAR in the original vector. */
for (i = 0; i < old_num; i++) 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) if (TREE_CODE (result) == SSA_NAME)
result = SSA_NAME_VAR (result); result = SSA_NAME_VAR (result);
if (result == var) 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; break;
} }
} }
if (i == old_num) 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); VARRAY_POP_ALL (build_v_must_defs);
...@@ -1672,7 +1676,10 @@ copy_virtual_operands (tree dst, tree src) ...@@ -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)); *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++) 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) ...@@ -1701,7 +1708,7 @@ create_ssa_artficial_load_stmt (stmt_operands_p old_ops, tree new_stmt)
free_vuses (&(ann->operands.vuse_ops)); free_vuses (&(ann->operands.vuse_ops));
free_v_may_defs (&(ann->operands.v_may_def_ops)); free_v_may_defs (&(ann->operands.v_may_def_ops));
free_v_must_defs (&(ann->operands.v_must_def_ops)); free_v_must_defs (&(ann->operands.v_must_def_ops));
/* For each VDEF on the original statement, we want to create a /* 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 VUSE of the V_MAY_DEF result or V_MUST_DEF op on the new
statement. */ statement. */
...@@ -1713,7 +1720,7 @@ create_ssa_artficial_load_stmt (stmt_operands_p old_ops, tree new_stmt) ...@@ -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++) 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); append_vuse (op);
} }
......
...@@ -58,17 +58,17 @@ typedef struct use_optype_d GTY(()) ...@@ -58,17 +58,17 @@ typedef struct use_optype_d GTY(())
typedef use_optype_t *use_optype; typedef use_optype_t *use_optype;
/* Operand type which stores a def and a use tree. */ /* 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 def;
tree use; tree use;
} v_may_def_operand_type_t; } v_def_use_operand_type_t;
/* This represents the MAY_DEFS for a stmt. */ /* This represents the MAY_DEFS for a stmt. */
typedef struct v_may_def_optype_d GTY(()) typedef struct v_may_def_optype_d GTY(())
{ {
unsigned num_v_may_defs; 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_defs[1];
} v_may_def_optype_t; } v_may_def_optype_t;
...@@ -87,7 +87,7 @@ typedef vuse_optype_t *vuse_optype; ...@@ -87,7 +87,7 @@ typedef vuse_optype_t *vuse_optype;
typedef struct v_must_def_optype_d GTY(()) typedef struct v_must_def_optype_d GTY(())
{ {
unsigned num_v_must_defs; 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; } v_must_def_optype_t;
typedef v_must_def_optype_t *v_must_def_optype; typedef v_must_def_optype_t *v_must_def_optype;
...@@ -157,12 +157,14 @@ typedef stmt_operands_t *stmt_operands_p; ...@@ -157,12 +157,14 @@ typedef stmt_operands_t *stmt_operands_p;
#define V_MUST_DEF_OPS(ANN) get_v_must_def_ops (ANN) #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 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 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_RESULT_PTR(OPS, I) get_v_must_def_result_ptr ((OPS), (I))
#define V_MUST_DEF_OP(OPS, I) \ #define V_MUST_DEF_RESULT(OPS, I) \
(DEF_FROM_PTR (V_MUST_DEF_OP_PTR ((OPS), (I)))) (DEF_FROM_PTR (V_MUST_DEF_RESULT_PTR ((OPS), (I))))
#define SET_V_MUST_DEF_OP(OPS, I, V) \ #define SET_V_MUST_DEF_RESULT(OPS, I, V) \
(SET_DEF (V_MUST_DEF_OP_PTR ((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_PTR(PHI) get_phi_result_ptr (PHI)
#define PHI_RESULT(PHI) DEF_FROM_PTR (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 ...@@ -199,13 +201,15 @@ typedef struct ssa_operand_iterator_d
int num_vuse; int num_vuse;
int num_v_mayu; int num_v_mayu;
int num_v_mayd; int num_v_mayd;
int num_v_must; int num_v_mustu;
int num_v_mustd;
int use_i; int use_i;
int def_i; int def_i;
int vuse_i; int vuse_i;
int v_mayu_i; int v_mayu_i;
int v_mayd_i; int v_mayd_i;
int v_must_i; int v_mustu_i;
int v_mustd_i;
stmt_operands_p ops; stmt_operands_p ops;
bool done; bool done;
} ssa_op_iter; } ssa_op_iter;
...@@ -218,13 +222,17 @@ typedef struct ssa_operand_iterator_d ...@@ -218,13 +222,17 @@ typedef struct ssa_operand_iterator_d
#define SSA_OP_VMAYUSE 0x08 /* USE portion of V_MAY_DEFS. */ #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_VMAYDEF 0x10 /* DEF portion of V_MAY_DEFS. */
#define SSA_OP_VMUSTDEF 0x20 /* V_MUST_DEF definitions. */ #define SSA_OP_VMUSTDEF 0x20 /* V_MUST_DEF definitions. */
#define SSA_OP_VMUSTDEFKILL 0x40 /* V_MUST_DEF kills. */
/* These are commonly grouped operand flags. */ /* These are commonly grouped operand flags. */
#define SSA_OP_VIRTUAL_USES (SSA_OP_VUSE | SSA_OP_VMAYUSE) #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_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_USES (SSA_OP_VIRTUAL_USES | SSA_OP_USE)
#define SSA_OP_ALL_DEFS (SSA_OP_VIRTUAL_DEFS | SSA_OP_DEF) #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, /* 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 returning each operand as a 'tree' in the variable TREEVAR. ITER is an
...@@ -258,4 +266,12 @@ typedef struct ssa_operand_iterator_d ...@@ -258,4 +266,12 @@ typedef struct ssa_operand_iterator_d
!op_iter_done (&(ITER)); \ !op_iter_done (&(ITER)); \
op_iter_next_maydef (&(USEVAR), &(DEFVAR), &(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 */ #endif /* GCC_TREE_SSA_OPERANDS_H */
...@@ -672,7 +672,7 @@ verify_ssa (void) ...@@ -672,7 +672,7 @@ verify_ssa (void)
{ {
tree stmt = bsi_stmt (bsi); 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)], if (verify_use (bb, definition_block[SSA_NAME_VERSION (op)],
op, stmt, false, true, op, stmt, false, true,
...@@ -1082,7 +1082,8 @@ replace_immediate_uses (tree var, tree repl) ...@@ -1082,7 +1082,8 @@ replace_immediate_uses (tree var, tree repl)
} }
else 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) if (USE_FROM_PTR (use_p) == var)
propagate_value (use_p, repl); propagate_value (use_p, repl);
} }
...@@ -1464,3 +1465,4 @@ struct tree_opt_pass pass_late_warn_uninitialized = ...@@ -1464,3 +1465,4 @@ struct tree_opt_pass pass_late_warn_uninitialized =
0, /* todo_flags_finish */ 0, /* todo_flags_finish */
0 /* letter */ 0 /* letter */
}; };
...@@ -381,7 +381,10 @@ rename_variables_in_bb (basic_block bb) ...@@ -381,7 +381,10 @@ rename_variables_in_bb (basic_block bb)
v_must_defs = V_MUST_DEF_OPS (ann); v_must_defs = V_MUST_DEF_OPS (ann);
for (i = 0; i < NUM_V_MUST_DEFS (v_must_defs); i++) 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) FOR_EACH_EDGE (e, ei, bb->succs)
...@@ -1853,7 +1856,7 @@ vect_create_data_ref_ptr (tree stmt, block_stmt_iterator *bsi, tree offset, ...@@ -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++) 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) if (TREE_CODE (def) == SSA_NAME)
bitmap_set_bit (vars_to_rename, var_ann (SSA_NAME_VAR (def))->uid); bitmap_set_bit (vars_to_rename, var_ann (SSA_NAME_VAR (def))->uid);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment