mirror of git://gcc.gnu.org/git/gcc.git
re PR ipa/44563 (GCC uses a lot of RAM when compiling a large numbers of functions)
2015-03-10 Richard Biener <rguenther@suse.de> PR middle-end/44563 * tree-cfgcleanup.c (split_bb_on_noreturn_calls): Remove. (cleanup_tree_cfg_1): Do not call it. (execute_cleanup_cfg_post_optimizing): Fixup the CFG here. (fixup_noreturn_call): Mark the stmt as control altering. * tree-cfg.c (execute_fixup_cfg): Do not dump the function here. (pass_data_fixup_cfg): Produce a dump file. * tree-ssa-dom.c: Include tree-cfgcleanup.h. (need_noreturn_fixup): New global. (pass_dominator::execute): Fixup queued noreturn calls. (optimize_stmt): Queue calls that became noreturn for fixup. * tree-ssa-forwprop.c (pass_forwprop::execute): Likewise. * tree-ssa-pre.c: Include tree-cfgcleanup.h. (el_to_fixup): New global. (eliminate_dom_walker::before_dom_childre): Queue calls that became noreturn for fixup. (eliminate): Fixup queued noreturn calls. * tree-ssa-propagate.c: Include tree-cfgcleanup.h. (substitute_and_fold_dom_walker): New member stmts_to_fixup. (substitute_and_fold_dom_walker::before_dom_children): Queue alls that became noreturn for fixup. (substitute_and_fold): Fixup queued noreturn calls. From-SVN: r221409
This commit is contained in:
parent
10ac659618
commit
2a5671ee80
|
|
@ -1,3 +1,29 @@
|
||||||
|
2015-03-13 Richard Biener <rguenther@suse.de>
|
||||||
|
|
||||||
|
PR middle-end/44563
|
||||||
|
* tree-cfgcleanup.c (split_bb_on_noreturn_calls): Remove.
|
||||||
|
(cleanup_tree_cfg_1): Do not call it.
|
||||||
|
(execute_cleanup_cfg_post_optimizing): Fixup the CFG here.
|
||||||
|
(fixup_noreturn_call): Mark the stmt as control altering.
|
||||||
|
* tree-cfg.c (execute_fixup_cfg): Do not dump the function
|
||||||
|
here.
|
||||||
|
(pass_data_fixup_cfg): Produce a dump file.
|
||||||
|
* tree-ssa-dom.c: Include tree-cfgcleanup.h.
|
||||||
|
(need_noreturn_fixup): New global.
|
||||||
|
(pass_dominator::execute): Fixup queued noreturn calls.
|
||||||
|
(optimize_stmt): Queue calls that became noreturn for fixup.
|
||||||
|
* tree-ssa-forwprop.c (pass_forwprop::execute): Likewise.
|
||||||
|
* tree-ssa-pre.c: Include tree-cfgcleanup.h.
|
||||||
|
(el_to_fixup): New global.
|
||||||
|
(eliminate_dom_walker::before_dom_childre): Queue calls that
|
||||||
|
became noreturn for fixup.
|
||||||
|
(eliminate): Fixup queued noreturn calls.
|
||||||
|
* tree-ssa-propagate.c: Include tree-cfgcleanup.h.
|
||||||
|
(substitute_and_fold_dom_walker): New member stmts_to_fixup.
|
||||||
|
(substitute_and_fold_dom_walker::before_dom_children): Queue
|
||||||
|
alls that became noreturn for fixup.
|
||||||
|
(substitute_and_fold): Fixup queued noreturn calls.
|
||||||
|
|
||||||
2015-03-12 Jan Hubicka <hubicka@ucw.cz>
|
2015-03-12 Jan Hubicka <hubicka@ucw.cz>
|
||||||
|
|
||||||
* ipa-icf.c (sem_function::equals_wpa): Match CXX_CONSTRUCTOR_P
|
* ipa-icf.c (sem_function::equals_wpa): Match CXX_CONSTRUCTOR_P
|
||||||
|
|
|
||||||
|
|
@ -8721,10 +8721,6 @@ execute_fixup_cfg (void)
|
||||||
if (count_scale != REG_BR_PROB_BASE)
|
if (count_scale != REG_BR_PROB_BASE)
|
||||||
compute_function_frequency ();
|
compute_function_frequency ();
|
||||||
|
|
||||||
/* Dump a textual representation of the flowgraph. */
|
|
||||||
if (dump_file)
|
|
||||||
gimple_dump_cfg (dump_file, dump_flags);
|
|
||||||
|
|
||||||
if (current_loops
|
if (current_loops
|
||||||
&& (todo & TODO_cleanup_cfg))
|
&& (todo & TODO_cleanup_cfg))
|
||||||
loops_state_set (LOOPS_NEED_FIXUP);
|
loops_state_set (LOOPS_NEED_FIXUP);
|
||||||
|
|
@ -8737,7 +8733,7 @@ namespace {
|
||||||
const pass_data pass_data_fixup_cfg =
|
const pass_data pass_data_fixup_cfg =
|
||||||
{
|
{
|
||||||
GIMPLE_PASS, /* type */
|
GIMPLE_PASS, /* type */
|
||||||
"*free_cfg_annotations", /* name */
|
"fixup_cfg", /* name */
|
||||||
OPTGROUP_NONE, /* optinfo_flags */
|
OPTGROUP_NONE, /* optinfo_flags */
|
||||||
TV_NONE, /* tv_id */
|
TV_NONE, /* tv_id */
|
||||||
PROP_cfg, /* properties_required */
|
PROP_cfg, /* properties_required */
|
||||||
|
|
|
||||||
|
|
@ -625,35 +625,13 @@ fixup_noreturn_call (gimple stmt)
|
||||||
update_stmt (stmt);
|
update_stmt (stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Mark the call as altering control flow. */
|
||||||
|
gimple_call_set_ctrl_altering (stmt, true);
|
||||||
|
|
||||||
return remove_fallthru_edge (bb->succs);
|
return remove_fallthru_edge (bb->succs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Split basic blocks on calls in the middle of a basic block that are now
|
|
||||||
known not to return, and remove the unreachable code. */
|
|
||||||
|
|
||||||
static bool
|
|
||||||
split_bb_on_noreturn_calls (basic_block bb)
|
|
||||||
{
|
|
||||||
bool changed = false;
|
|
||||||
gimple_stmt_iterator gsi;
|
|
||||||
|
|
||||||
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
|
|
||||||
{
|
|
||||||
gimple stmt = gsi_stmt (gsi);
|
|
||||||
|
|
||||||
if (!is_gimple_call (stmt))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (gimple_call_noreturn_p (stmt))
|
|
||||||
changed |= fixup_noreturn_call (stmt);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (changed)
|
|
||||||
bitmap_set_bit (cfgcleanup_altered_bbs, bb->index);
|
|
||||||
return changed;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Tries to cleanup cfg in basic block BB. Returns true if anything
|
/* Tries to cleanup cfg in basic block BB. Returns true if anything
|
||||||
changes. */
|
changes. */
|
||||||
|
|
||||||
|
|
@ -703,10 +681,7 @@ cleanup_tree_cfg_1 (void)
|
||||||
{
|
{
|
||||||
bb = BASIC_BLOCK_FOR_FN (cfun, i);
|
bb = BASIC_BLOCK_FOR_FN (cfun, i);
|
||||||
if (bb)
|
if (bb)
|
||||||
{
|
|
||||||
retval |= cleanup_tree_cfg_bb (bb);
|
retval |= cleanup_tree_cfg_bb (bb);
|
||||||
retval |= split_bb_on_noreturn_calls (bb);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now process the altered blocks, as long as any are available. */
|
/* Now process the altered blocks, as long as any are available. */
|
||||||
|
|
@ -722,10 +697,6 @@ cleanup_tree_cfg_1 (void)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
retval |= cleanup_tree_cfg_bb (bb);
|
retval |= cleanup_tree_cfg_bb (bb);
|
||||||
|
|
||||||
/* Rerun split_bb_on_noreturn_calls, in case we have altered any noreturn
|
|
||||||
calls. */
|
|
||||||
retval |= split_bb_on_noreturn_calls (bb);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
end_recording_case_labels ();
|
end_recording_case_labels ();
|
||||||
|
|
@ -1111,9 +1082,12 @@ make_pass_merge_phi (gcc::context *ctxt)
|
||||||
static unsigned int
|
static unsigned int
|
||||||
execute_cleanup_cfg_post_optimizing (void)
|
execute_cleanup_cfg_post_optimizing (void)
|
||||||
{
|
{
|
||||||
unsigned int todo = 0;
|
unsigned int todo = execute_fixup_cfg ();
|
||||||
if (cleanup_tree_cfg ())
|
if (cleanup_tree_cfg ())
|
||||||
|
{
|
||||||
|
todo &= ~TODO_cleanup_cfg;
|
||||||
todo |= TODO_update_ssa;
|
todo |= TODO_update_ssa;
|
||||||
|
}
|
||||||
maybe_remove_unreachable_handlers ();
|
maybe_remove_unreachable_handlers ();
|
||||||
cleanup_dead_labels ();
|
cleanup_dead_labels ();
|
||||||
group_case_labels ();
|
group_case_labels ();
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,7 @@ along with GCC; see the file COPYING3. If not see
|
||||||
#include "tree-ssa-dom.h"
|
#include "tree-ssa-dom.h"
|
||||||
#include "inchash.h"
|
#include "inchash.h"
|
||||||
#include "gimplify.h"
|
#include "gimplify.h"
|
||||||
|
#include "tree-cfgcleanup.h"
|
||||||
|
|
||||||
/* This file implements optimizations on the dominator tree. */
|
/* This file implements optimizations on the dominator tree. */
|
||||||
|
|
||||||
|
|
@ -246,6 +247,7 @@ static bool cfg_altered;
|
||||||
/* Bitmap of blocks that have had EH statements cleaned. We should
|
/* Bitmap of blocks that have had EH statements cleaned. We should
|
||||||
remove their dead edges eventually. */
|
remove their dead edges eventually. */
|
||||||
static bitmap need_eh_cleanup;
|
static bitmap need_eh_cleanup;
|
||||||
|
static vec<gimple> need_noreturn_fixup;
|
||||||
|
|
||||||
/* Statistics for dominator optimizations. */
|
/* Statistics for dominator optimizations. */
|
||||||
struct opt_stats_d
|
struct opt_stats_d
|
||||||
|
|
@ -885,6 +887,7 @@ pass_dominator::execute (function *fun)
|
||||||
avail_exprs_stack.create (20);
|
avail_exprs_stack.create (20);
|
||||||
const_and_copies_stack.create (20);
|
const_and_copies_stack.create (20);
|
||||||
need_eh_cleanup = BITMAP_ALLOC (NULL);
|
need_eh_cleanup = BITMAP_ALLOC (NULL);
|
||||||
|
need_noreturn_fixup.create (0);
|
||||||
|
|
||||||
calculate_dominance_info (CDI_DOMINATORS);
|
calculate_dominance_info (CDI_DOMINATORS);
|
||||||
cfg_altered = false;
|
cfg_altered = false;
|
||||||
|
|
@ -967,6 +970,23 @@ pass_dominator::execute (function *fun)
|
||||||
bitmap_clear (need_eh_cleanup);
|
bitmap_clear (need_eh_cleanup);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Fixup stmts that became noreturn calls. This may require splitting
|
||||||
|
blocks and thus isn't possible during the dominator walk or before
|
||||||
|
jump threading finished. Do this in reverse order so we don't
|
||||||
|
inadvertedly remove a stmt we want to fixup by visiting a dominating
|
||||||
|
now noreturn call first. */
|
||||||
|
while (!need_noreturn_fixup.is_empty ())
|
||||||
|
{
|
||||||
|
gimple stmt = need_noreturn_fixup.pop ();
|
||||||
|
if (dump_file && dump_flags & TDF_DETAILS)
|
||||||
|
{
|
||||||
|
fprintf (dump_file, "Fixing up noreturn call ");
|
||||||
|
print_gimple_stmt (dump_file, stmt, 0, 0);
|
||||||
|
fprintf (dump_file, "\n");
|
||||||
|
}
|
||||||
|
fixup_noreturn_call (stmt);
|
||||||
|
}
|
||||||
|
|
||||||
statistics_counter_event (fun, "Redundant expressions eliminated",
|
statistics_counter_event (fun, "Redundant expressions eliminated",
|
||||||
opt_stats.num_re);
|
opt_stats.num_re);
|
||||||
statistics_counter_event (fun, "Constants propagated",
|
statistics_counter_event (fun, "Constants propagated",
|
||||||
|
|
@ -986,7 +1006,7 @@ pass_dominator::execute (function *fun)
|
||||||
|
|
||||||
/* Free asserted bitmaps and stacks. */
|
/* Free asserted bitmaps and stacks. */
|
||||||
BITMAP_FREE (need_eh_cleanup);
|
BITMAP_FREE (need_eh_cleanup);
|
||||||
|
need_noreturn_fixup.release ();
|
||||||
avail_exprs_stack.release ();
|
avail_exprs_stack.release ();
|
||||||
const_and_copies_stack.release ();
|
const_and_copies_stack.release ();
|
||||||
|
|
||||||
|
|
@ -2364,8 +2384,10 @@ optimize_stmt (basic_block bb, gimple_stmt_iterator si)
|
||||||
gimple stmt, old_stmt;
|
gimple stmt, old_stmt;
|
||||||
bool may_optimize_p;
|
bool may_optimize_p;
|
||||||
bool modified_p = false;
|
bool modified_p = false;
|
||||||
|
bool was_noreturn;
|
||||||
|
|
||||||
old_stmt = stmt = gsi_stmt (si);
|
old_stmt = stmt = gsi_stmt (si);
|
||||||
|
was_noreturn = is_gimple_call (stmt) && gimple_call_noreturn_p (stmt);
|
||||||
|
|
||||||
if (dump_file && (dump_flags & TDF_DETAILS))
|
if (dump_file && (dump_flags & TDF_DETAILS))
|
||||||
{
|
{
|
||||||
|
|
@ -2545,6 +2567,10 @@ optimize_stmt (basic_block bb, gimple_stmt_iterator si)
|
||||||
if (dump_file && (dump_flags & TDF_DETAILS))
|
if (dump_file && (dump_flags & TDF_DETAILS))
|
||||||
fprintf (dump_file, " Flagged to clear EH edges.\n");
|
fprintf (dump_file, " Flagged to clear EH edges.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!was_noreturn
|
||||||
|
&& is_gimple_call (stmt) && gimple_call_noreturn_p (stmt))
|
||||||
|
need_noreturn_fixup.safe_push (stmt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2141,6 +2141,7 @@ pass_forwprop::execute (function *fun)
|
||||||
lattice.quick_grow_cleared (num_ssa_names);
|
lattice.quick_grow_cleared (num_ssa_names);
|
||||||
int *postorder = XNEWVEC (int, n_basic_blocks_for_fn (fun));
|
int *postorder = XNEWVEC (int, n_basic_blocks_for_fn (fun));
|
||||||
int postorder_num = inverted_post_order_compute (postorder);
|
int postorder_num = inverted_post_order_compute (postorder);
|
||||||
|
auto_vec<gimple, 4> to_fixup;
|
||||||
to_purge = BITMAP_ALLOC (NULL);
|
to_purge = BITMAP_ALLOC (NULL);
|
||||||
for (int i = 0; i < postorder_num; ++i)
|
for (int i = 0; i < postorder_num; ++i)
|
||||||
{
|
{
|
||||||
|
|
@ -2340,6 +2341,8 @@ pass_forwprop::execute (function *fun)
|
||||||
gimple stmt = gsi_stmt (gsi);
|
gimple stmt = gsi_stmt (gsi);
|
||||||
gimple orig_stmt = stmt;
|
gimple orig_stmt = stmt;
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
|
bool was_noreturn = (is_gimple_call (stmt)
|
||||||
|
&& gimple_call_noreturn_p (stmt));
|
||||||
|
|
||||||
/* Mark stmt as potentially needing revisiting. */
|
/* Mark stmt as potentially needing revisiting. */
|
||||||
gimple_set_plf (stmt, GF_PLF_1, false);
|
gimple_set_plf (stmt, GF_PLF_1, false);
|
||||||
|
|
@ -2350,6 +2353,9 @@ pass_forwprop::execute (function *fun)
|
||||||
stmt = gsi_stmt (gsi);
|
stmt = gsi_stmt (gsi);
|
||||||
if (maybe_clean_or_replace_eh_stmt (orig_stmt, stmt))
|
if (maybe_clean_or_replace_eh_stmt (orig_stmt, stmt))
|
||||||
bitmap_set_bit (to_purge, bb->index);
|
bitmap_set_bit (to_purge, bb->index);
|
||||||
|
if (!was_noreturn
|
||||||
|
&& is_gimple_call (stmt) && gimple_call_noreturn_p (stmt))
|
||||||
|
to_fixup.safe_push (stmt);
|
||||||
/* Cleanup the CFG if we simplified a condition to
|
/* Cleanup the CFG if we simplified a condition to
|
||||||
true or false. */
|
true or false. */
|
||||||
if (gcond *cond = dyn_cast <gcond *> (stmt))
|
if (gcond *cond = dyn_cast <gcond *> (stmt))
|
||||||
|
|
@ -2470,6 +2476,22 @@ pass_forwprop::execute (function *fun)
|
||||||
free (postorder);
|
free (postorder);
|
||||||
lattice.release ();
|
lattice.release ();
|
||||||
|
|
||||||
|
/* Fixup stmts that became noreturn calls. This may require splitting
|
||||||
|
blocks and thus isn't possible during the walk. Do this
|
||||||
|
in reverse order so we don't inadvertedly remove a stmt we want to
|
||||||
|
fixup by visiting a dominating now noreturn call first. */
|
||||||
|
while (!to_fixup.is_empty ())
|
||||||
|
{
|
||||||
|
gimple stmt = to_fixup.pop ();
|
||||||
|
if (dump_file && dump_flags & TDF_DETAILS)
|
||||||
|
{
|
||||||
|
fprintf (dump_file, "Fixing up noreturn call ");
|
||||||
|
print_gimple_stmt (dump_file, stmt, 0, 0);
|
||||||
|
fprintf (dump_file, "\n");
|
||||||
|
}
|
||||||
|
cfg_changed |= fixup_noreturn_call (stmt);
|
||||||
|
}
|
||||||
|
|
||||||
cfg_changed |= gimple_purge_all_dead_eh_edges (to_purge);
|
cfg_changed |= gimple_purge_all_dead_eh_edges (to_purge);
|
||||||
BITMAP_FREE (to_purge);
|
BITMAP_FREE (to_purge);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -98,6 +98,7 @@ along with GCC; see the file COPYING3. If not see
|
||||||
#include "ipa-prop.h"
|
#include "ipa-prop.h"
|
||||||
#include "tree-ssa-propagate.h"
|
#include "tree-ssa-propagate.h"
|
||||||
#include "ipa-utils.h"
|
#include "ipa-utils.h"
|
||||||
|
#include "tree-cfgcleanup.h"
|
||||||
|
|
||||||
/* TODO:
|
/* TODO:
|
||||||
|
|
||||||
|
|
@ -3922,6 +3923,7 @@ compute_avail (void)
|
||||||
|
|
||||||
/* Local state for the eliminate domwalk. */
|
/* Local state for the eliminate domwalk. */
|
||||||
static vec<gimple> el_to_remove;
|
static vec<gimple> el_to_remove;
|
||||||
|
static vec<gimple> el_to_fixup;
|
||||||
static unsigned int el_todo;
|
static unsigned int el_todo;
|
||||||
static vec<tree> el_avail;
|
static vec<tree> el_avail;
|
||||||
static vec<tree> el_avail_stack;
|
static vec<tree> el_avail_stack;
|
||||||
|
|
@ -4429,7 +4431,7 @@ eliminate_dom_walker::before_dom_children (basic_block b)
|
||||||
/* When changing a call into a noreturn call, cfg cleanup
|
/* When changing a call into a noreturn call, cfg cleanup
|
||||||
is needed to fix up the noreturn call. */
|
is needed to fix up the noreturn call. */
|
||||||
if (!was_noreturn && gimple_call_noreturn_p (stmt))
|
if (!was_noreturn && gimple_call_noreturn_p (stmt))
|
||||||
el_todo |= TODO_cleanup_cfg;
|
el_to_fixup.safe_push (stmt);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -4529,6 +4531,7 @@ eliminate (bool do_pre)
|
||||||
need_ab_cleanup = BITMAP_ALLOC (NULL);
|
need_ab_cleanup = BITMAP_ALLOC (NULL);
|
||||||
|
|
||||||
el_to_remove.create (0);
|
el_to_remove.create (0);
|
||||||
|
el_to_fixup.create (0);
|
||||||
el_todo = 0;
|
el_todo = 0;
|
||||||
el_avail.create (num_ssa_names);
|
el_avail.create (num_ssa_names);
|
||||||
el_avail_stack.create (0);
|
el_avail_stack.create (0);
|
||||||
|
|
@ -4580,6 +4583,25 @@ eliminate (bool do_pre)
|
||||||
}
|
}
|
||||||
el_to_remove.release ();
|
el_to_remove.release ();
|
||||||
|
|
||||||
|
/* Fixup stmts that became noreturn calls. This may require splitting
|
||||||
|
blocks and thus isn't possible during the dominator walk. Do this
|
||||||
|
in reverse order so we don't inadvertedly remove a stmt we want to
|
||||||
|
fixup by visiting a dominating now noreturn call first. */
|
||||||
|
while (!el_to_fixup.is_empty ())
|
||||||
|
{
|
||||||
|
stmt = el_to_fixup.pop ();
|
||||||
|
|
||||||
|
if (dump_file && (dump_flags & TDF_DETAILS))
|
||||||
|
{
|
||||||
|
fprintf (dump_file, "Fixing up noreturn call ");
|
||||||
|
print_gimple_stmt (dump_file, stmt, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fixup_noreturn_call (stmt))
|
||||||
|
el_todo |= TODO_cleanup_cfg;
|
||||||
|
}
|
||||||
|
el_to_fixup.release ();
|
||||||
|
|
||||||
return el_todo;
|
return el_todo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,7 @@
|
||||||
#include "value-prof.h"
|
#include "value-prof.h"
|
||||||
#include "domwalk.h"
|
#include "domwalk.h"
|
||||||
#include "cfgloop.h"
|
#include "cfgloop.h"
|
||||||
|
#include "tree-cfgcleanup.h"
|
||||||
|
|
||||||
/* This file implements a generic value propagation engine based on
|
/* This file implements a generic value propagation engine based on
|
||||||
the same propagation used by the SSA-CCP algorithm [1].
|
the same propagation used by the SSA-CCP algorithm [1].
|
||||||
|
|
@ -1071,11 +1072,13 @@ public:
|
||||||
fold_fn (fold_fn_), do_dce (do_dce_), something_changed (false)
|
fold_fn (fold_fn_), do_dce (do_dce_), something_changed (false)
|
||||||
{
|
{
|
||||||
stmts_to_remove.create (0);
|
stmts_to_remove.create (0);
|
||||||
|
stmts_to_fixup.create (0);
|
||||||
need_eh_cleanup = BITMAP_ALLOC (NULL);
|
need_eh_cleanup = BITMAP_ALLOC (NULL);
|
||||||
}
|
}
|
||||||
~substitute_and_fold_dom_walker ()
|
~substitute_and_fold_dom_walker ()
|
||||||
{
|
{
|
||||||
stmts_to_remove.release ();
|
stmts_to_remove.release ();
|
||||||
|
stmts_to_fixup.release ();
|
||||||
BITMAP_FREE (need_eh_cleanup);
|
BITMAP_FREE (need_eh_cleanup);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1087,6 +1090,7 @@ public:
|
||||||
bool do_dce;
|
bool do_dce;
|
||||||
bool something_changed;
|
bool something_changed;
|
||||||
vec<gimple> stmts_to_remove;
|
vec<gimple> stmts_to_remove;
|
||||||
|
vec<gimple> stmts_to_fixup;
|
||||||
bitmap need_eh_cleanup;
|
bitmap need_eh_cleanup;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1125,7 +1129,6 @@ substitute_and_fold_dom_walker::before_dom_children (basic_block bb)
|
||||||
{
|
{
|
||||||
bool did_replace;
|
bool did_replace;
|
||||||
gimple stmt = gsi_stmt (i);
|
gimple stmt = gsi_stmt (i);
|
||||||
gimple old_stmt;
|
|
||||||
enum gimple_code code = gimple_code (stmt);
|
enum gimple_code code = gimple_code (stmt);
|
||||||
|
|
||||||
/* Ignore ASSERT_EXPRs. They are used by VRP to generate
|
/* Ignore ASSERT_EXPRs. They are used by VRP to generate
|
||||||
|
|
@ -1163,7 +1166,9 @@ substitute_and_fold_dom_walker::before_dom_children (basic_block bb)
|
||||||
print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
|
print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
|
||||||
}
|
}
|
||||||
|
|
||||||
old_stmt = stmt;
|
gimple old_stmt = stmt;
|
||||||
|
bool was_noreturn = (is_gimple_call (stmt)
|
||||||
|
&& gimple_call_noreturn_p (stmt));
|
||||||
|
|
||||||
/* Some statements may be simplified using propagator
|
/* Some statements may be simplified using propagator
|
||||||
specific information. Do this before propagating
|
specific information. Do this before propagating
|
||||||
|
|
@ -1194,6 +1199,13 @@ substitute_and_fold_dom_walker::before_dom_children (basic_block bb)
|
||||||
if (maybe_clean_or_replace_eh_stmt (old_stmt, stmt))
|
if (maybe_clean_or_replace_eh_stmt (old_stmt, stmt))
|
||||||
bitmap_set_bit (need_eh_cleanup, bb->index);
|
bitmap_set_bit (need_eh_cleanup, bb->index);
|
||||||
|
|
||||||
|
/* If we turned a not noreturn call into a noreturn one
|
||||||
|
schedule it for fixup. */
|
||||||
|
if (!was_noreturn
|
||||||
|
&& is_gimple_call (stmt)
|
||||||
|
&& gimple_call_noreturn_p (stmt))
|
||||||
|
stmts_to_fixup.safe_push (stmt);
|
||||||
|
|
||||||
if (is_gimple_assign (stmt)
|
if (is_gimple_assign (stmt)
|
||||||
&& (get_gimple_rhs_class (gimple_assign_rhs_code (stmt))
|
&& (get_gimple_rhs_class (gimple_assign_rhs_code (stmt))
|
||||||
== GIMPLE_SINGLE_RHS))
|
== GIMPLE_SINGLE_RHS))
|
||||||
|
|
@ -1286,6 +1298,22 @@ substitute_and_fold (ssa_prop_get_value_fn get_value_fn,
|
||||||
if (!bitmap_empty_p (walker.need_eh_cleanup))
|
if (!bitmap_empty_p (walker.need_eh_cleanup))
|
||||||
gimple_purge_all_dead_eh_edges (walker.need_eh_cleanup);
|
gimple_purge_all_dead_eh_edges (walker.need_eh_cleanup);
|
||||||
|
|
||||||
|
/* Fixup stmts that became noreturn calls. This may require splitting
|
||||||
|
blocks and thus isn't possible during the dominator walk. Do this
|
||||||
|
in reverse order so we don't inadvertedly remove a stmt we want to
|
||||||
|
fixup by visiting a dominating now noreturn call first. */
|
||||||
|
while (!walker.stmts_to_fixup.is_empty ())
|
||||||
|
{
|
||||||
|
gimple stmt = walker.stmts_to_fixup.pop ();
|
||||||
|
if (dump_file && dump_flags & TDF_DETAILS)
|
||||||
|
{
|
||||||
|
fprintf (dump_file, "Fixing up noreturn call ");
|
||||||
|
print_gimple_stmt (dump_file, stmt, 0, 0);
|
||||||
|
fprintf (dump_file, "\n");
|
||||||
|
}
|
||||||
|
fixup_noreturn_call (stmt);
|
||||||
|
}
|
||||||
|
|
||||||
statistics_counter_event (cfun, "Constants propagated",
|
statistics_counter_event (cfun, "Constants propagated",
|
||||||
prop_stats.num_const_prop);
|
prop_stats.num_const_prop);
|
||||||
statistics_counter_event (cfun, "Copies propagated",
|
statistics_counter_event (cfun, "Copies propagated",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue