Commit 2a5671ee by Richard Biener Committed by Richard Biener

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
parent 10ac6596
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>
* 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)
compute_function_frequency ();
/* Dump a textual representation of the flowgraph. */
if (dump_file)
gimple_dump_cfg (dump_file, dump_flags);
if (current_loops
&& (todo & TODO_cleanup_cfg))
loops_state_set (LOOPS_NEED_FIXUP);
......@@ -8737,7 +8733,7 @@ namespace {
const pass_data pass_data_fixup_cfg =
{
GIMPLE_PASS, /* type */
"*free_cfg_annotations", /* name */
"fixup_cfg", /* name */
OPTGROUP_NONE, /* optinfo_flags */
TV_NONE, /* tv_id */
PROP_cfg, /* properties_required */
......
......@@ -625,35 +625,13 @@ fixup_noreturn_call (gimple stmt)
update_stmt (stmt);
}
/* Mark the call as altering control flow. */
gimple_call_set_ctrl_altering (stmt, true);
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
changes. */
......@@ -703,10 +681,7 @@ cleanup_tree_cfg_1 (void)
{
bb = BASIC_BLOCK_FOR_FN (cfun, i);
if (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. */
......@@ -722,10 +697,6 @@ cleanup_tree_cfg_1 (void)
continue;
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 ();
......@@ -1111,9 +1082,12 @@ make_pass_merge_phi (gcc::context *ctxt)
static unsigned int
execute_cleanup_cfg_post_optimizing (void)
{
unsigned int todo = 0;
unsigned int todo = execute_fixup_cfg ();
if (cleanup_tree_cfg ())
{
todo &= ~TODO_cleanup_cfg;
todo |= TODO_update_ssa;
}
maybe_remove_unreachable_handlers ();
cleanup_dead_labels ();
group_case_labels ();
......
......@@ -74,6 +74,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-ssa-dom.h"
#include "inchash.h"
#include "gimplify.h"
#include "tree-cfgcleanup.h"
/* 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
remove their dead edges eventually. */
static bitmap need_eh_cleanup;
static vec<gimple> need_noreturn_fixup;
/* Statistics for dominator optimizations. */
struct opt_stats_d
......@@ -885,6 +887,7 @@ pass_dominator::execute (function *fun)
avail_exprs_stack.create (20);
const_and_copies_stack.create (20);
need_eh_cleanup = BITMAP_ALLOC (NULL);
need_noreturn_fixup.create (0);
calculate_dominance_info (CDI_DOMINATORS);
cfg_altered = false;
......@@ -967,6 +970,23 @@ pass_dominator::execute (function *fun)
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",
opt_stats.num_re);
statistics_counter_event (fun, "Constants propagated",
......@@ -986,7 +1006,7 @@ pass_dominator::execute (function *fun)
/* Free asserted bitmaps and stacks. */
BITMAP_FREE (need_eh_cleanup);
need_noreturn_fixup.release ();
avail_exprs_stack.release ();
const_and_copies_stack.release ();
......@@ -2364,8 +2384,10 @@ optimize_stmt (basic_block bb, gimple_stmt_iterator si)
gimple stmt, old_stmt;
bool may_optimize_p;
bool modified_p = false;
bool was_noreturn;
old_stmt = stmt = gsi_stmt (si);
was_noreturn = is_gimple_call (stmt) && gimple_call_noreturn_p (stmt);
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))
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);
int *postorder = XNEWVEC (int, n_basic_blocks_for_fn (fun));
int postorder_num = inverted_post_order_compute (postorder);
auto_vec<gimple, 4> to_fixup;
to_purge = BITMAP_ALLOC (NULL);
for (int i = 0; i < postorder_num; ++i)
{
......@@ -2340,6 +2341,8 @@ pass_forwprop::execute (function *fun)
gimple stmt = gsi_stmt (gsi);
gimple orig_stmt = stmt;
bool changed = false;
bool was_noreturn = (is_gimple_call (stmt)
&& gimple_call_noreturn_p (stmt));
/* Mark stmt as potentially needing revisiting. */
gimple_set_plf (stmt, GF_PLF_1, false);
......@@ -2350,6 +2353,9 @@ pass_forwprop::execute (function *fun)
stmt = gsi_stmt (gsi);
if (maybe_clean_or_replace_eh_stmt (orig_stmt, stmt))
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
true or false. */
if (gcond *cond = dyn_cast <gcond *> (stmt))
......@@ -2470,6 +2476,22 @@ pass_forwprop::execute (function *fun)
free (postorder);
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);
BITMAP_FREE (to_purge);
......
......@@ -98,6 +98,7 @@ along with GCC; see the file COPYING3. If not see
#include "ipa-prop.h"
#include "tree-ssa-propagate.h"
#include "ipa-utils.h"
#include "tree-cfgcleanup.h"
/* TODO:
......@@ -3922,6 +3923,7 @@ compute_avail (void)
/* Local state for the eliminate domwalk. */
static vec<gimple> el_to_remove;
static vec<gimple> el_to_fixup;
static unsigned int el_todo;
static vec<tree> el_avail;
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
is needed to fix up the noreturn call. */
if (!was_noreturn && gimple_call_noreturn_p (stmt))
el_todo |= TODO_cleanup_cfg;
el_to_fixup.safe_push (stmt);
}
else
{
......@@ -4529,6 +4531,7 @@ eliminate (bool do_pre)
need_ab_cleanup = BITMAP_ALLOC (NULL);
el_to_remove.create (0);
el_to_fixup.create (0);
el_todo = 0;
el_avail.create (num_ssa_names);
el_avail_stack.create (0);
......@@ -4580,6 +4583,25 @@ eliminate (bool do_pre)
}
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;
}
......
......@@ -67,6 +67,7 @@
#include "value-prof.h"
#include "domwalk.h"
#include "cfgloop.h"
#include "tree-cfgcleanup.h"
/* This file implements a generic value propagation engine based on
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)
{
stmts_to_remove.create (0);
stmts_to_fixup.create (0);
need_eh_cleanup = BITMAP_ALLOC (NULL);
}
~substitute_and_fold_dom_walker ()
{
stmts_to_remove.release ();
stmts_to_fixup.release ();
BITMAP_FREE (need_eh_cleanup);
}
......@@ -1087,6 +1090,7 @@ public:
bool do_dce;
bool something_changed;
vec<gimple> stmts_to_remove;
vec<gimple> stmts_to_fixup;
bitmap need_eh_cleanup;
};
......@@ -1125,7 +1129,6 @@ substitute_and_fold_dom_walker::before_dom_children (basic_block bb)
{
bool did_replace;
gimple stmt = gsi_stmt (i);
gimple old_stmt;
enum gimple_code code = gimple_code (stmt);
/* 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);
}
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
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))
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)
&& (get_gimple_rhs_class (gimple_assign_rhs_code (stmt))
== 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))
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",
prop_stats.num_const_prop);
statistics_counter_event (cfun, "Copies propagated",
......
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