aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog86
-rw-r--r--gcc/tree-cfg.c8
-rw-r--r--gcc/tree-dfa.c9
-rw-r--r--gcc/tree-flow-inline.h76
-rw-r--r--gcc/tree-flow.h1
-rw-r--r--gcc/tree-into-ssa.c204
-rw-r--r--gcc/tree-optimize.c5
-rw-r--r--gcc/tree-pass.h1
-rw-r--r--gcc/tree-pretty-print.c13
-rw-r--r--gcc/tree-ssa-ccp.c2
-rw-r--r--gcc/tree-ssa-dce.c135
-rw-r--r--gcc/tree-ssa-loop-im.c5
-rw-r--r--gcc/tree-ssa-loop-manip.c2
-rw-r--r--gcc/tree-ssa-operands.c25
-rw-r--r--gcc/tree-ssa-operands.h42
-rw-r--r--gcc/tree-ssa.c6
-rw-r--r--gcc/tree-vectorizer.c7
17 files changed, 465 insertions, 162 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 767af3e..75423d8 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index af78901..a963124 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -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)
diff --git a/gcc/tree-dfa.c b/gcc/tree-dfa.c
index cce0ff6..de4e225 100644
--- a/gcc/tree-dfa.c
+++ b/gcc/tree-dfa.c
@@ -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);
+ }
+ }
}
diff --git a/gcc/tree-flow-inline.h b/gcc/tree-flow-inline.h
index 0507921..e3c955e 100644
--- a/gcc/tree-flow-inline.h
+++ b/gcc/tree-flow-inline.h
@@ -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 */
diff --git a/gcc/tree-flow.h b/gcc/tree-flow.h
index 14b5972..37cf556 100644
--- a/gcc/tree-flow.h
+++ b/gcc/tree-flow.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);
diff --git a/gcc/tree-into-ssa.c b/gcc/tree-into-ssa.c
index 972bec9..079065e 100644
--- a/gcc/tree-into-ssa.c
+++ b/gcc/tree-into-ssa.c
@@ -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,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
proceeds in five main phases:
@@ -1395,13 +1493,11 @@ invalidate_name_tags (bitmap vars_to_rename)
order.
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).
- 5- Rename all the blocks (rewrite_initialize_block,
- rewrite_add_phi_arguments) and statements in the program
- (rewrite_stmt).
+ 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).
@@ -1414,10 +1510,7 @@ rewrite_into_ssa (bool all)
{
bitmap *dfs;
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;
- unsigned i;
timevar_push (TV_TREE_SSA_OTHER);
@@ -1441,9 +1534,7 @@ rewrite_into_ssa (bool all)
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);
+ mark_def_site_blocks ();
/* Initialize dominance frontier and immediate dominator bitmaps.
Also count the number of predecessors for each block. Doing so
@@ -1452,80 +1543,13 @@ rewrite_into_ssa (bool all)
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. */
- 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 (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. */
diff --git a/gcc/tree-optimize.c b/gcc/tree-optimize.c
index fed16c3..88d18a7 100644
--- a/gcc/tree-optimize.c
+++ b/gcc/tree-optimize.c
@@ -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)
{
diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
index 6250ae6..7140766 100644
--- a/gcc/tree-pass.h
+++ b/gcc/tree-pass.h
@@ -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)
diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
index a473139..3f2d4b6 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -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);
}
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index 3e8fa7b..b97424f 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -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)
diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c
index 341b768..2c68861 100644
--- a/gcc/tree-ssa-dce.c
+++ b/gcc/tree-ssa-dce.c
@@ -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);
-
- 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);
- }
+ tree t = bsi_stmt (i);
+
+ 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);
+ }
}
}
-}
+ }
/* 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 */
};
diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c
index 27bc1c0..bcdd9d7 100644
--- a/gcc/tree-ssa-loop-im.c
+++ b/gcc/tree-ssa-loop-im.c
@@ -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);
diff --git a/gcc/tree-ssa-loop-manip.c b/gcc/tree-ssa-loop-manip.c
index dc4b174..1f949a4 100644
--- a/gcc/tree-ssa-loop-manip.c
+++ b/gcc/tree-ssa-loop-manip.c
@@ -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);
}
diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c
index 953ef8d..55cebf2 100644
--- a/gcc/tree-ssa-operands.c
+++ b/gcc/tree-ssa-operands.c
@@ -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);
}
diff --git a/gcc/tree-ssa-operands.h b/gcc/tree-ssa-operands.h
index ad0a916..521845f 100644
--- a/gcc/tree-ssa-operands.h
+++ b/gcc/tree-ssa-operands.h
@@ -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 */
diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
index 7f73bcf..d9379ba 100644
--- a/gcc/tree-ssa.c
+++ b/gcc/tree-ssa.c
@@ -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 */
};
+
diff --git a/gcc/tree-vectorizer.c b/gcc/tree-vectorizer.c
index 656c612..df16c2c 100644
--- a/gcc/tree-vectorizer.c
+++ b/gcc/tree-vectorizer.c
@@ -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);
}