aboutsummaryrefslogtreecommitdiff
path: root/gcc/ipa-inline.c
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2005-06-28 04:20:29 +0200
committerJan Hubicka <hubicka@gcc.gnu.org>2005-06-28 02:20:29 +0000
commitd63db217aed8c803f7d8b85910d6c8cfedc2acca (patch)
tree02b6b104f2f54b8af2a5bad55640e994b28ecfb5 /gcc/ipa-inline.c
parent2aba33dd6f2d9cf16b2c2e25e73071b5e6d4368c (diff)
downloadgcc-d63db217aed8c803f7d8b85910d6c8cfedc2acca.zip
gcc-d63db217aed8c803f7d8b85910d6c8cfedc2acca.tar.gz
gcc-d63db217aed8c803f7d8b85910d6c8cfedc2acca.tar.bz2
cgraph.c (cgraph_remove_node): Do not release function bodies until full cgraph is built.
* cgraph.c (cgraph_remove_node): Do not release function bodies until full cgraph is built. * cgraph.h (cgraph_decide_inlining_incrementally): Add early argument. * cgraphunit.c (cgraph_finalize_function): Update call of cgraph_decide_inlining_incrementally. (initialize_inline_failed): Break out of ... (cgraph_analyze_function): ... here. (rebuild_cgraph_edges): New function. (pass_rebuild_cgraph_edges): New pass. * common.opt (fearly-inlining): New flag. * ipa-inline.c: Include ggc.h (cgraph_clone_inlined_nodes): Avoid re-using of original copy when cgraph is not fully built. (cgraph_decide_inlining_incrementally): Add early mode. (cgraph_early_inlining): New function. (cgraph_gate_early_inlining): Likewise. (pass_early_ipa_inline): New pass. * ipa.c (cgraph_postorder): NULLify aux pointer. * tree-inline.c (expand_call_inline): Avoid warning early. * tree-optimize.c (pass_early_local_passes): New. (execute_cleanup_cfg_pre_ipa): New. (pass_cleanup_cfg): New. (register_dump_files): Fix handling subpasses of IPA pass. (init_tree_optimization_passes): Add early passes. (execute_ipa_pass_list): Fix handling of subpasses of IPA pass. * passes.h (pass_early_tree_profile, pass_rebuild_cgraph_edges, pass_early_ipa_inline): New passes. * tree-profile.c (do_early_tree_profiling, pass_early_tree_profile): New. * invoke.texi: Document early-inlining. From-SVN: r101369
Diffstat (limited to 'gcc/ipa-inline.c')
-rw-r--r--gcc/ipa-inline.c103
1 files changed, 96 insertions, 7 deletions
diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c
index c176eb7..26ea8f5 100644
--- a/gcc/ipa-inline.c
+++ b/gcc/ipa-inline.c
@@ -79,6 +79,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
#include "intl.h"
#include "tree-pass.h"
#include "coverage.h"
+#include "ggc.h"
/* Statistics we collect about inlining algorithm. */
static int ncalls_inlined;
@@ -120,7 +121,7 @@ cgraph_clone_inlined_nodes (struct cgraph_edge *e, bool duplicate)
if (!e->callee->callers->next_caller
&& (!e->callee->needed || DECL_EXTERNAL (e->callee->decl))
&& duplicate
- && flag_unit_at_a_time)
+ && (flag_unit_at_a_time && cgraph_global_info_ready))
{
gcc_assert (!e->callee->global.inlined_to);
if (!DECL_EXTERNAL (e->callee->decl))
@@ -870,10 +871,11 @@ cgraph_decide_inlining (void)
/* Decide on the inlining. We do so in the topological order to avoid
expenses on updating data structures. */
-void
-cgraph_decide_inlining_incrementally (struct cgraph_node *node)
+bool
+cgraph_decide_inlining_incrementally (struct cgraph_node *node, bool early)
{
struct cgraph_edge *e;
+ bool inlined = false;
/* First of all look for always inline functions. */
for (e = node->callees; e; e = e->next_callee)
@@ -883,7 +885,13 @@ cgraph_decide_inlining_incrementally (struct cgraph_node *node)
/* ??? It is possible that renaming variable removed the function body
in duplicate_decls. See gcc.c-torture/compile/20011119-2.c */
&& DECL_SAVED_TREE (e->callee->decl))
- cgraph_mark_inline (e);
+ {
+ if (dump_file && early)
+ fprintf (dump_file, " Early inlining %s into %s\n",
+ cgraph_node_name (e->callee), cgraph_node_name (node));
+ cgraph_mark_inline (e);
+ inlined = true;
+ }
/* Now do the automatic inlining. */
if (!flag_really_no_inline)
@@ -892,15 +900,36 @@ cgraph_decide_inlining_incrementally (struct cgraph_node *node)
&& e->inline_failed
&& !e->callee->local.disregard_inline_limits
&& !cgraph_recursive_inlining_p (node, e->callee, &e->inline_failed)
+ && (!early
+ || (cgraph_estimate_size_after_inlining (1, e->caller, node)
+ <= e->caller->global.insns))
&& cgraph_check_inline_limits (node, e->callee, &e->inline_failed)
&& DECL_SAVED_TREE (e->callee->decl))
{
if (cgraph_default_inline_p (e->callee))
- cgraph_mark_inline (e);
- else
+ {
+ if (dump_file && early)
+ fprintf (dump_file, " Early inlining %s into %s\n",
+ cgraph_node_name (e->callee), cgraph_node_name (node));
+ cgraph_mark_inline (e);
+ inlined = true;
+ }
+ else if (!early)
e->inline_failed
= N_("--param max-inline-insns-single limit reached");
}
+ if (early && inlined)
+ {
+ push_cfun (DECL_STRUCT_FUNCTION (node->decl));
+ tree_register_cfg_hooks ();
+ current_function_decl = node->decl;
+ optimize_inline_calls (current_function_decl);
+ node->local.self_insns = node->global.insns;
+ current_function_decl = NULL;
+ pop_cfun ();
+ ggc_collect ();
+ }
+ return inlined;
}
/* When inlining shall be performed. */
@@ -920,7 +949,67 @@ struct tree_opt_pass pass_ipa_inline =
0, /* static_pass_number */
TV_INTEGRATION, /* tv_id */
0, /* properties_required */
- PROP_trees, /* properties_provided */
+ PROP_cfg, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_dump_cgraph | TODO_dump_func, /* todo_flags_finish */
+ 0 /* letter */
+};
+
+/* Do inlining of small functions. Doing so early helps profiling and other
+ passes to be somewhat more effective and avoids some code duplication in
+ later real inlining pass for testcases with very many function calls. */
+static void
+cgraph_early_inlining (void)
+{
+ struct cgraph_node *node;
+ int nnodes;
+ struct cgraph_node **order =
+ xcalloc (cgraph_n_nodes, sizeof (struct cgraph_node *));
+ int i;
+
+ if (sorrycount || errorcount)
+ return;
+#ifdef ENABLE_CHECKING
+ for (node = cgraph_nodes; node; node = node->next)
+ gcc_assert (!node->aux);
+#endif
+
+ nnodes = cgraph_postorder (order);
+ for (i = nnodes - 1; i >= 0; i--)
+ {
+ node = order[i];
+ if (node->analyzed && node->local.inlinable
+ && (node->needed || node->reachable)
+ && node->callers)
+ cgraph_decide_inlining_incrementally (node, true);
+ }
+ cgraph_remove_unreachable_nodes (true, dump_file);
+#ifdef ENABLE_CHECKING
+ for (node = cgraph_nodes; node; node = node->next)
+ gcc_assert (!node->global.inlined_to);
+#endif
+ free (order);
+}
+
+/* When inlining shall be performed. */
+static bool
+cgraph_gate_early_inlining (void)
+{
+ return flag_inline_trees && flag_early_inlining;
+}
+
+struct tree_opt_pass pass_early_ipa_inline =
+{
+ "einline", /* name */
+ cgraph_gate_early_inlining, /* gate */
+ cgraph_early_inlining, /* execute */
+ NULL, /* sub */
+ NULL, /* next */
+ 0, /* static_pass_number */
+ TV_INTEGRATION, /* tv_id */
+ 0, /* properties_required */
+ PROP_cfg, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
TODO_dump_cgraph | TODO_dump_func, /* todo_flags_finish */