summaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-dce.c
diff options
context:
space:
mode:
authordberlin <dberlin@138bc75d-0d04-0410-961f-82ee72b054a4>2004-10-27 17:45:21 +0000
committerdberlin <dberlin@138bc75d-0d04-0410-961f-82ee72b054a4>2004-10-27 17:45:21 +0000
commit1bd13ef117738b816e270e9fd9e3d475d92eb4f3 (patch)
tree36b6b5291cd04acd1807e64b366402dc565251b6 /gcc/tree-ssa-dce.c
parent746852fec1b23f14c601c2456929ff05f2ff6668 (diff)
downloadgcc-1bd13ef117738b816e270e9fd9e3d475d92eb4f3.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@89695 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-ssa-dce.c')
-rw-r--r--gcc/tree-ssa-dce.c135
1 files changed, 108 insertions, 27 deletions
diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c
index 341b7683040..2c688616fc8 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 */
};