summaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-dce.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-ssa-dce.c')
-rw-r--r--gcc/tree-ssa-dce.c307
1 files changed, 130 insertions, 177 deletions
diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c
index fd1bc69be56..ecc8c6f2264 100644
--- a/gcc/tree-ssa-dce.c
+++ b/gcc/tree-ssa-dce.c
@@ -87,7 +87,7 @@ static sbitmap bb_contains_live_stmts;
use a bitmap for each block recording its edges. An array holds the
bitmap. The Ith bit in the bitmap is set if that block is dependent
on the Ith edge. */
-static bitmap *control_dependence_map;
+static control_dependences *cd;
/* Vector indicating that a basic block has already had all the edges
processed that it is control dependent on. */
@@ -100,96 +100,6 @@ static sbitmap visited_control_parents;
to be recomputed. */
static bool cfg_altered;
-/* Execute code that follows the macro for each edge (given number
- EDGE_NUMBER within the CODE) for which the block with index N is
- control dependent. */
-#define EXECUTE_IF_CONTROL_DEPENDENT(BI, N, EDGE_NUMBER) \
- EXECUTE_IF_SET_IN_BITMAP (control_dependence_map[(N)], 0, \
- (EDGE_NUMBER), (BI))
-
-
-/* Indicate block BB is control dependent on an edge with index EDGE_INDEX. */
-static inline void
-set_control_dependence_map_bit (basic_block bb, int edge_index)
-{
- if (bb == ENTRY_BLOCK_PTR)
- return;
- gcc_assert (bb != EXIT_BLOCK_PTR);
- bitmap_set_bit (control_dependence_map[bb->index], edge_index);
-}
-
-/* Clear all control dependences for block BB. */
-static inline void
-clear_control_dependence_bitmap (basic_block bb)
-{
- bitmap_clear (control_dependence_map[bb->index]);
-}
-
-
-/* Find the immediate postdominator PDOM of the specified basic block BLOCK.
- This function is necessary because some blocks have negative numbers. */
-
-static inline basic_block
-find_pdom (basic_block block)
-{
- gcc_assert (block != ENTRY_BLOCK_PTR);
-
- if (block == EXIT_BLOCK_PTR)
- return EXIT_BLOCK_PTR;
- else
- {
- basic_block bb = get_immediate_dominator (CDI_POST_DOMINATORS, block);
- if (! bb)
- return EXIT_BLOCK_PTR;
- return bb;
- }
-}
-
-
-/* Determine all blocks' control dependences on the given edge with edge_list
- EL index EDGE_INDEX, ala Morgan, Section 3.6. */
-
-static void
-find_control_dependence (struct edge_list *el, int edge_index)
-{
- basic_block current_block;
- basic_block ending_block;
-
- gcc_assert (INDEX_EDGE_PRED_BB (el, edge_index) != EXIT_BLOCK_PTR);
-
- if (INDEX_EDGE_PRED_BB (el, edge_index) == ENTRY_BLOCK_PTR)
- ending_block = single_succ (ENTRY_BLOCK_PTR);
- else
- ending_block = find_pdom (INDEX_EDGE_PRED_BB (el, edge_index));
-
- for (current_block = INDEX_EDGE_SUCC_BB (el, edge_index);
- current_block != ending_block && current_block != EXIT_BLOCK_PTR;
- current_block = find_pdom (current_block))
- {
- edge e = INDEX_EDGE (el, edge_index);
-
- /* For abnormal edges, we don't make current_block control
- dependent because instructions that throw are always necessary
- anyway. */
- if (e->flags & EDGE_ABNORMAL)
- continue;
-
- set_control_dependence_map_bit (current_block, edge_index);
- }
-}
-
-
-/* Record all blocks' control dependences on all edges in the edge
- list EL, ala Morgan, Section 3.6. */
-
-static void
-find_all_control_dependences (struct edge_list *el)
-{
- int i;
-
- for (i = 0; i < NUM_EDGES (el); ++i)
- find_control_dependence (el, i);
-}
/* If STMT is not already marked necessary, mark it, and add it to the
worklist if ADD_TO_WORKLIST is true. */
@@ -400,8 +310,7 @@ mark_last_stmt_necessary (basic_block bb)
When IGNORE_SELF is true, ignore BB in the list of control dependences. */
static void
-mark_control_dependent_edges_necessary (basic_block bb, struct edge_list *el,
- bool ignore_self)
+mark_control_dependent_edges_necessary (basic_block bb, bool ignore_self)
{
bitmap_iterator bi;
unsigned edge_number;
@@ -412,9 +321,10 @@ mark_control_dependent_edges_necessary (basic_block bb, struct edge_list *el,
if (bb == ENTRY_BLOCK_PTR)
return;
- EXECUTE_IF_CONTROL_DEPENDENT (bi, bb->index, edge_number)
+ EXECUTE_IF_SET_IN_BITMAP (cd->get_edges_dependent_on (bb->index),
+ 0, edge_number, bi)
{
- basic_block cd_bb = INDEX_EDGE_PRED_BB (el, edge_number);
+ basic_block cd_bb = cd->get_edge (edge_number)->src;
if (ignore_self && cd_bb == bb)
{
@@ -439,7 +349,7 @@ mark_control_dependent_edges_necessary (basic_block bb, struct edge_list *el,
dependence analysis. */
static void
-find_obviously_necessary_stmts (struct edge_list *el)
+find_obviously_necessary_stmts (bool aggressive)
{
basic_block bb;
gimple_stmt_iterator gsi;
@@ -461,7 +371,7 @@ find_obviously_necessary_stmts (struct edge_list *el)
{
stmt = gsi_stmt (gsi);
gimple_set_plf (stmt, STMT_NECESSARY, false);
- mark_stmt_if_obviously_necessary (stmt, el != NULL);
+ mark_stmt_if_obviously_necessary (stmt, aggressive);
}
}
@@ -472,7 +382,7 @@ find_obviously_necessary_stmts (struct edge_list *el)
return;
/* Prevent the empty possibly infinite loops from being removed. */
- if (el)
+ if (aggressive)
{
loop_iterator li;
struct loop *loop;
@@ -488,7 +398,7 @@ find_obviously_necessary_stmts (struct edge_list *el)
if (dump_file)
fprintf (dump_file, "Marking back edge of irreducible loop %i->%i\n",
e->src->index, e->dest->index);
- mark_control_dependent_edges_necessary (e->dest, el, false);
+ mark_control_dependent_edges_necessary (e->dest, false);
}
}
@@ -497,7 +407,7 @@ find_obviously_necessary_stmts (struct edge_list *el)
{
if (dump_file)
fprintf (dump_file, "can not prove finiteness of loop %i\n", loop->num);
- mark_control_dependent_edges_necessary (loop->latch, el, false);
+ mark_control_dependent_edges_necessary (loop->latch, false);
}
scev_finalize ();
}
@@ -574,6 +484,11 @@ mark_aliased_reaching_defs_necessary_1 (ao_ref *ref, tree vdef, void *data)
in the references (gcc.c-torture/execute/pr42142.c).
The simplest way is to check if the kill dominates
the use. */
+ /* But when both are in the same block we cannot
+ easily tell whether we came from a backedge
+ unless we decide to compute stmt UIDs
+ (see PR58246). */
+ && (basic_block) data != gimple_bb (def_stmt)
&& dominated_by_p (CDI_DOMINATORS, (basic_block) data,
gimple_bb (def_stmt))
&& operand_equal_p (ref->ref, lhs, 0))
@@ -685,10 +600,9 @@ degenerate_phi_p (gimple phi)
In conservative mode, EL is NULL. */
static void
-propagate_necessity (struct edge_list *el)
+propagate_necessity (bool aggressive)
{
gimple stmt;
- bool aggressive = (el ? true : false);
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "\nProcessing worklist:\n");
@@ -713,7 +627,7 @@ propagate_necessity (struct edge_list *el)
basic_block bb = gimple_bb (stmt);
if (bb != ENTRY_BLOCK_PTR
&& !bitmap_bit_p (visited_control_parents, bb->index))
- mark_control_dependent_edges_necessary (bb, el, false);
+ mark_control_dependent_edges_necessary (bb, false);
}
if (gimple_code (stmt) == GIMPLE_PHI
@@ -820,7 +734,7 @@ propagate_necessity (struct edge_list *el)
else if (arg_bb != ENTRY_BLOCK_PTR
&& !bitmap_bit_p (visited_control_parents,
arg_bb->index))
- mark_control_dependent_edges_necessary (arg_bb, el, true);
+ mark_control_dependent_edges_necessary (arg_bb, true);
}
}
}
@@ -1481,12 +1395,6 @@ tree_dce_init (bool aggressive)
if (aggressive)
{
- int i;
-
- control_dependence_map = XNEWVEC (bitmap, last_basic_block);
- for (i = 0; i < last_basic_block; ++i)
- control_dependence_map[i] = BITMAP_ALLOC (NULL);
-
last_stmt_necessary = sbitmap_alloc (last_basic_block);
bitmap_clear (last_stmt_necessary);
bb_contains_live_stmts = sbitmap_alloc (last_basic_block);
@@ -1507,12 +1415,7 @@ tree_dce_done (bool aggressive)
{
if (aggressive)
{
- int i;
-
- for (i = 0; i < last_basic_block; ++i)
- BITMAP_FREE (control_dependence_map[i]);
- free (control_dependence_map);
-
+ delete cd;
sbitmap_free (visited_control_parents);
sbitmap_free (last_stmt_necessary);
sbitmap_free (bb_contains_live_stmts);
@@ -1541,7 +1444,6 @@ tree_dce_done (bool aggressive)
static unsigned int
perform_tree_ssa_dce (bool aggressive)
{
- struct edge_list *el = NULL;
bool something_changed = 0;
calculate_dominance_info (CDI_DOMINATORS);
@@ -1558,11 +1460,8 @@ perform_tree_ssa_dce (bool aggressive)
if (aggressive)
{
/* Compute control dependence. */
- timevar_push (TV_CONTROL_DEPENDENCES);
calculate_dominance_info (CDI_POST_DOMINATORS);
- el = create_edge_list ();
- find_all_control_dependences (el);
- timevar_pop (TV_CONTROL_DEPENDENCES);
+ cd = new control_dependences (create_edge_list ());
visited_control_parents = sbitmap_alloc (last_basic_block);
bitmap_clear (visited_control_parents);
@@ -1570,7 +1469,7 @@ perform_tree_ssa_dce (bool aggressive)
mark_dfs_back_edges ();
}
- find_obviously_necessary_stmts (el);
+ find_obviously_necessary_stmts (aggressive);
if (aggressive)
loop_optimizer_finalize ();
@@ -1580,7 +1479,7 @@ perform_tree_ssa_dce (bool aggressive)
nr_walks = 0;
chain_ovfl = false;
visited = BITMAP_ALLOC (NULL);
- propagate_necessity (el);
+ propagate_necessity (aggressive);
BITMAP_FREE (visited);
something_changed |= eliminate_unnecessary_stmts ();
@@ -1604,8 +1503,6 @@ perform_tree_ssa_dce (bool aggressive)
tree_dce_done (aggressive);
- free_edge_list (el);
-
if (something_changed)
return TODO_update_ssa | TODO_cleanup_cfg;
return 0;
@@ -1643,63 +1540,119 @@ gate_dce (void)
return flag_tree_dce != 0;
}
-struct gimple_opt_pass pass_dce =
+namespace {
+
+const pass_data pass_data_dce =
{
- {
- GIMPLE_PASS,
- "dce", /* name */
- OPTGROUP_NONE, /* optinfo_flags */
- gate_dce, /* gate */
- tree_ssa_dce, /* execute */
- NULL, /* sub */
- NULL, /* next */
- 0, /* static_pass_number */
- TV_TREE_DCE, /* tv_id */
- PROP_cfg | PROP_ssa, /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- TODO_verify_ssa /* todo_flags_finish */
- }
+ GIMPLE_PASS, /* type */
+ "dce", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
+ true, /* has_gate */
+ true, /* has_execute */
+ TV_TREE_DCE, /* tv_id */
+ ( PROP_cfg | PROP_ssa ), /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_verify_ssa, /* todo_flags_finish */
};
-struct gimple_opt_pass pass_dce_loop =
+class pass_dce : public gimple_opt_pass
{
- {
- GIMPLE_PASS,
- "dceloop", /* name */
- OPTGROUP_NONE, /* optinfo_flags */
- gate_dce, /* gate */
- tree_ssa_dce_loop, /* execute */
- NULL, /* sub */
- NULL, /* next */
- 0, /* static_pass_number */
- TV_TREE_DCE, /* tv_id */
- PROP_cfg | PROP_ssa, /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- TODO_verify_ssa /* todo_flags_finish */
- }
+public:
+ pass_dce(gcc::context *ctxt)
+ : gimple_opt_pass(pass_data_dce, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ opt_pass * clone () { return new pass_dce (ctxt_); }
+ bool gate () { return gate_dce (); }
+ unsigned int execute () { return tree_ssa_dce (); }
+
+}; // class pass_dce
+
+} // anon namespace
+
+gimple_opt_pass *
+make_pass_dce (gcc::context *ctxt)
+{
+ return new pass_dce (ctxt);
+}
+
+namespace {
+
+const pass_data pass_data_dce_loop =
+{
+ GIMPLE_PASS, /* type */
+ "dceloop", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
+ true, /* has_gate */
+ true, /* has_execute */
+ TV_TREE_DCE, /* tv_id */
+ ( PROP_cfg | PROP_ssa ), /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_verify_ssa, /* todo_flags_finish */
};
-struct gimple_opt_pass pass_cd_dce =
+class pass_dce_loop : public gimple_opt_pass
+{
+public:
+ pass_dce_loop(gcc::context *ctxt)
+ : gimple_opt_pass(pass_data_dce_loop, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ opt_pass * clone () { return new pass_dce_loop (ctxt_); }
+ bool gate () { return gate_dce (); }
+ unsigned int execute () { return tree_ssa_dce_loop (); }
+
+}; // class pass_dce_loop
+
+} // anon namespace
+
+gimple_opt_pass *
+make_pass_dce_loop (gcc::context *ctxt)
+{
+ return new pass_dce_loop (ctxt);
+}
+
+namespace {
+
+const pass_data pass_data_cd_dce =
{
- {
- GIMPLE_PASS,
- "cddce", /* name */
- OPTGROUP_NONE, /* optinfo_flags */
- gate_dce, /* gate */
- tree_ssa_cd_dce, /* execute */
- NULL, /* sub */
- NULL, /* next */
- 0, /* static_pass_number */
- TV_TREE_CD_DCE, /* tv_id */
- PROP_cfg | PROP_ssa, /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- TODO_verify_ssa
- | TODO_verify_flow /* todo_flags_finish */
- }
+ GIMPLE_PASS, /* type */
+ "cddce", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
+ true, /* has_gate */
+ true, /* has_execute */
+ TV_TREE_CD_DCE, /* tv_id */
+ ( PROP_cfg | PROP_ssa ), /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ ( TODO_verify_ssa | TODO_verify_flow ), /* todo_flags_finish */
};
+
+class pass_cd_dce : public gimple_opt_pass
+{
+public:
+ pass_cd_dce(gcc::context *ctxt)
+ : gimple_opt_pass(pass_data_cd_dce, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ opt_pass * clone () { return new pass_cd_dce (ctxt_); }
+ bool gate () { return gate_dce (); }
+ unsigned int execute () { return tree_ssa_cd_dce (); }
+
+}; // class pass_cd_dce
+
+} // anon namespace
+
+gimple_opt_pass *
+make_pass_cd_dce (gcc::context *ctxt)
+{
+ return new pass_cd_dce (ctxt);
+}