diff options
author | Jan Hubicka <jh@suse.cz> | 2005-06-28 04:20:29 +0200 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2005-06-28 02:20:29 +0000 |
commit | d63db217aed8c803f7d8b85910d6c8cfedc2acca (patch) | |
tree | 02b6b104f2f54b8af2a5bad55640e994b28ecfb5 /gcc/ipa-inline.c | |
parent | 2aba33dd6f2d9cf16b2c2e25e73071b5e6d4368c (diff) | |
download | gcc-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.c | 103 |
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 */ |