This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: More of ipa-inline housekeeping


On Thu, Apr 14, 2011 at 12:20 AM, Jan Hubicka <hubicka@ucw.cz> wrote:
> Hi,
> this patch moves inline_summary from field in cgraph_node into its own on side
> datastructure. This moves it from arcane decision of mine to split all IPA data
> into global/local datas stored in common datastructure into the scheme we
> developed for new IPA passes some time ago.
>
> The advantage is that the code is more contained and less spread across the
> compiler. We also make cgraph_node smaller and dumps more compact that never
> hurts.
>
> While working on it I noticed that Richi's patch to introduce cgraph_edge
> times/sizes is bit iffy in computing data when they are missing in the
> datastructure. Also it computes incomming edge costs instead of outgoing that
> leads to fact that not all edges gets their info computed for IPA inliner
> (think of newly discovered direct calls or IPA merging).

Ah, that was the reason ... I didn't dig deep enough ... ;)

>
> I fixed this on the and added sanity check that the fields are initialized.
> This has shown problem with early inliner iteration fixed thusly and fact that
> early inliner is attempting to compute overall growth at a time the inline
> parameters are not computed for functions not visited by early optimizations
> yet. We previously agreed that early inliner should not try to do that (as this
> leads to early inliner inlining functions called once that should be deferred
> for later consieration). ?I just hope it won't cause benchmarks to
> regress too much ;)

Yeah, we agreed to that.  And I forgot about it as it wasn't part of the
early inliner reorg (which was supposed to be a 1:1 transform).

>
> Having place to pile inline analysis info in, there is more to cleanup. The
> cgraph_local/cgraph_global fields probably should go and the stuff from global
> info should go into inline_summary datastructure, too (the lifetimes are
> essentially the same so there is no need for the split). ?I will handle this
> incrementally.
>
> Bootstrapped/regtested x86_64-linux with slightly modified version of the patch.
> Re-testing with final version and intend to commit the patch tomorrow.

I looked over the patch and it looks ok to me.

Thanks,
Richard.

> Honza
>
> ? ? ? ?* cgraph.c (dump_cgraph_node): Do not dump inline summaries.
> ? ? ? ?* cgraph.h (struct inline_summary): Move to ipa-inline.h
> ? ? ? ?(cgraph_local_info): Remove inline_summary.
> ? ? ? ?* ipa-cp.c: Include ipa-inline.h.
> ? ? ? ?(ipcp_cloning_candidate_p, ipcp_estimate_growth,
> ? ? ? ?ipcp_estimate_cloning_cost, ipcp_insert_stage): Use inline_summary
> ? ? ? ?accesor.
> ? ? ? ?* lto-cgraph.c (lto_output_node): Do not stream inline summary.
> ? ? ? ?(input_overwrite_node): Do not set inline summary.
> ? ? ? ?(input_node): Do not stream inline summary.
> ? ? ? ?* ipa-inline.c (cgraph_decide_inlining): Dump inline summaries.
> ? ? ? ?(cgraph_decide_inlining_incrementally): Do not try to estimate overall
> ? ? ? ?growth; we do not have inline parameters computed for that anyway.
> ? ? ? ?(cgraph_early_inlining): After inlining compute call_stmt_sizes.
> ? ? ? ?* ipa-inline.h (struct inline_summary): Move here from ipa-inline.h
> ? ? ? ?(inline_summary_t): New type and VECtor.
> ? ? ? ?(debug_inline_summary, dump_inline_summaries): Declare.
> ? ? ? ?(inline_summary): Use VOCtor.
> ? ? ? ?(estimate_edge_growth): Kill hack computing call stmt size directly.
> ? ? ? ?* lto-section-in.c (lto_section_name): Add inline section.
> ? ? ? ?* ipa-inline-analysis.c: Include lto-streamer.h
> ? ? ? ?(node_removal_hook_holder, node_duplication_hook_holder): New holders
> ? ? ? ?(inline_node_removal_hook, inline_node_duplication_hook): New functions.
> ? ? ? ?(inline_summary_vec): Define.
> ? ? ? ?(inline_summary_alloc, dump_inline_summary, debug_inline_summary,
> ? ? ? ?dump_inline_summaries): New functions.
> ? ? ? ?(estimate_function_body_sizes): Properly compute size/time of outgoing calls.
> ? ? ? ?(compute_inline_parameters): Alloc inline_summary; do not compute size/time
> ? ? ? ?of incomming calls.
> ? ? ? ?(estimate_edge_time): Avoid missing time summary hack.
> ? ? ? ?(inline_read_summary): Read inline summary info.
> ? ? ? ?(inline_write_summary): Write inline summary info.
> ? ? ? ?(inline_free_summary): Free all hooks and inline summary vector.
> ? ? ? ?* lto-streamer.h: Add LTO_section_inline_summary section.
> ? ? ? ?* Makefile.in (ipa-cp.o, ipa-inline-analysis.o): Update dependencies.
> ? ? ? ?* ipa.c (cgraph_remove_unreachable_nodes): Fix dump file formating.
>
> ? ? ? ?* lto.c: Include ipa-inline.h
> ? ? ? ?(add_cgraph_node_to_partition, undo_partition): Use inline_summary accessor.
> ? ? ? ?(ipa_node_duplication_hook): Fix declaration.
> ? ? ? ?* Make-lang.in (lto.o): Update dependencies.
> Index: cgraph.c
> ===================================================================
> --- cgraph.c ? ?(revision 172396)
> +++ cgraph.c ? ?(working copy)
> @@ -1876,22 +1876,6 @@ dump_cgraph_node (FILE *f, struct cgraph
> ? if (node->count)
> ? ? fprintf (f, " executed "HOST_WIDEST_INT_PRINT_DEC"x",
> ? ? ? ? ? ? (HOST_WIDEST_INT)node->count);
> - ?if (node->local.inline_summary.self_time)
> - ? ?fprintf (f, " %i time, %i benefit", node->local.inline_summary.self_time,
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? node->local.inline_summary.time_inlining_benefit);
> - ?if (node->global.time && node->global.time
> - ? ? ?!= node->local.inline_summary.self_time)
> - ? ?fprintf (f, " (%i after inlining)", node->global.time);
> - ?if (node->local.inline_summary.self_size)
> - ? ?fprintf (f, " %i size, %i benefit", node->local.inline_summary.self_size,
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? node->local.inline_summary.size_inlining_benefit);
> - ?if (node->global.size && node->global.size
> - ? ? ?!= node->local.inline_summary.self_size)
> - ? ?fprintf (f, " (%i after inlining)", node->global.size);
> - ?if (node->local.inline_summary.estimated_self_stack_size)
> - ? ?fprintf (f, " %i bytes stack usage", (int)node->local.inline_summary.estimated_self_stack_size);
> - ?if (node->global.estimated_stack_size != node->local.inline_summary.estimated_self_stack_size)
> - ? ?fprintf (f, " %i bytes after inlining", (int)node->global.estimated_stack_size);
> ? if (node->origin)
> ? ? fprintf (f, " nested in: %s", cgraph_node_name (node->origin));
> ? if (node->needed)
> Index: cgraph.h
> ===================================================================
> --- cgraph.h ? ?(revision 172396)
> +++ cgraph.h ? ?(working copy)
> @@ -58,23 +58,6 @@ struct lto_file_decl_data;
> ?extern const char * const cgraph_availability_names[];
> ?extern const char * const ld_plugin_symbol_resolution_names[];
>
> -/* Function inlining information. ?*/
> -
> -struct GTY(()) inline_summary
> -{
> - ?/* Estimated stack frame consumption by the function. ?*/
> - ?HOST_WIDE_INT estimated_self_stack_size;
> -
> - ?/* Size of the function body. ?*/
> - ?int self_size;
> - ?/* How many instructions are likely going to disappear after inlining. ?*/
> - ?int size_inlining_benefit;
> - ?/* Estimated time spent executing the function body. ?*/
> - ?int self_time;
> - ?/* How much time is going to be saved by inlining. ?*/
> - ?int time_inlining_benefit;
> -};
> -
> ?/* Information about thunk, used only for same body aliases. ?*/
>
> ?struct GTY(()) cgraph_thunk_info {
> @@ -95,8 +78,6 @@ struct GTY(()) cgraph_local_info {
> ? /* File stream where this node is being written to. ?*/
> ? struct lto_file_decl_data * lto_file_data;
>
> - ?struct inline_summary inline_summary;
> -
> ? /* Set when function function is visible in current compilation unit only
> ? ? ?and its address is never taken. ?*/
> ? unsigned local : 1;
> Index: ipa-cp.c
> ===================================================================
> --- ipa-cp.c ? ?(revision 172396)
> +++ ipa-cp.c ? ?(working copy)
> @@ -148,6 +148,7 @@ along with GCC; see the file COPYING3.
> ?#include "tree-inline.h"
> ?#include "fibheap.h"
> ?#include "params.h"
> +#include "ipa-inline.h"
>
> ?/* Number of functions identified as candidates for cloning. When not cloning
> ? ?we can simplify iterate stage not forcing it to go through the decision
> @@ -495,7 +496,7 @@ ipcp_cloning_candidate_p (struct cgraph_
> ? ? ? ? ? ? ? ? cgraph_node_name (node));
> ? ? ? return false;
> ? ? }
> - ?if (node->local.inline_summary.self_size < n_calls)
> + ?if (inline_summary (node)->self_size < n_calls)
> ? ? {
> ? ? ? if (dump_file)
> ? ? ? ? fprintf (dump_file, "Considering %s for cloning; code would shrink.\n",
> @@ -1189,7 +1190,7 @@ ipcp_estimate_growth (struct cgraph_node
> ? ? ?call site. ?Precise cost is difficult to get, as our size metric counts
> ? ? ?constants and moves as free. ?Generally we are looking for cases that
> ? ? ?small function is called very many times. ?*/
> - ?growth = node->local.inline_summary.self_size
> + ?growth = inline_summary (node)->self_size
> ? ? ? ? ? - removable_args * redirectable_node_callers;
> ? if (growth < 0)
> ? ? return 0;
> @@ -1229,7 +1230,7 @@ ipcp_estimate_cloning_cost (struct cgrap
> ? ? cost /= freq_sum * 1000 / REG_BR_PROB_BASE + 1;
> ? if (dump_file)
> ? ? fprintf (dump_file, "Cost of versioning %s is %i, (size: %i, freq: %i)\n",
> - ? ? ? ? ? ? cgraph_node_name (node), cost, node->local.inline_summary.self_size,
> + ? ? ? ? ? ? cgraph_node_name (node), cost, inline_summary (node)->self_size,
> ? ? ? ? ? ? freq_sum);
> ? return cost + 1;
> ?}
> @@ -1364,7 +1365,7 @@ ipcp_insert_stage (void)
> ? ? ? {
> ? ? ? ?if (node->count > max_count)
> ? ? ? ? ?max_count = node->count;
> - ? ? ? overall_size += node->local.inline_summary.self_size;
> + ? ? ? overall_size += inline_summary (node)->self_size;
> ? ? ? }
>
> ? max_new_size = overall_size;
> Index: lto-cgraph.c
> ===================================================================
> --- lto-cgraph.c ? ? ? ?(revision 172396)
> +++ lto-cgraph.c ? ? ? ?(working copy)
> @@ -465,16 +465,6 @@ lto_output_node (struct lto_simple_outpu
>
> ? if (tag == LTO_cgraph_analyzed_node)
> ? ? {
> - ? ? ?lto_output_sleb128_stream (ob->main_stream,
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?node->local.inline_summary.estimated_self_stack_size);
> - ? ? ?lto_output_sleb128_stream (ob->main_stream,
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?node->local.inline_summary.self_size);
> - ? ? ?lto_output_sleb128_stream (ob->main_stream,
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?node->local.inline_summary.size_inlining_benefit);
> - ? ? ?lto_output_sleb128_stream (ob->main_stream,
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?node->local.inline_summary.self_time);
> - ? ? ?lto_output_sleb128_stream (ob->main_stream,
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?node->local.inline_summary.time_inlining_benefit);
> ? ? ? if (node->global.inlined_to)
> ? ? ? ?{
> ? ? ? ? ?ref = lto_cgraph_encoder_lookup (encoder, node->global.inlined_to);
> @@ -930,23 +920,9 @@ input_overwrite_node (struct lto_file_de
> ? ? ? ? ? ? ? ? ? ? ?struct cgraph_node *node,
> ? ? ? ? ? ? ? ? ? ? ?enum LTO_cgraph_tags tag,
> ? ? ? ? ? ? ? ? ? ? ?struct bitpack_d *bp,
> - ? ? ? ? ? ? ? ? ? ? unsigned int stack_size,
> - ? ? ? ? ? ? ? ? ? ? unsigned int self_time,
> - ? ? ? ? ? ? ? ? ? ? unsigned int time_inlining_benefit,
> - ? ? ? ? ? ? ? ? ? ? unsigned int self_size,
> - ? ? ? ? ? ? ? ? ? ? unsigned int size_inlining_benefit,
> ? ? ? ? ? ? ? ? ? ? ?enum ld_plugin_symbol_resolution resolution)
> ?{
> ? node->aux = (void *) tag;
> - ?node->local.inline_summary.estimated_self_stack_size = stack_size;
> - ?node->local.inline_summary.self_time = self_time;
> - ?node->local.inline_summary.time_inlining_benefit = time_inlining_benefit;
> - ?node->local.inline_summary.self_size = self_size;
> - ?node->local.inline_summary.size_inlining_benefit = size_inlining_benefit;
> - ?node->global.time = self_time;
> - ?node->global.size = self_size;
> - ?node->global.estimated_stack_size = stack_size;
> - ?node->global.estimated_growth = INT_MIN;
> ? node->local.lto_file_data = file_data;
>
> ? node->local.local = bp_unpack_value (bp, 1);
> @@ -1023,13 +999,8 @@ input_node (struct lto_file_decl_data *f
> ? tree fn_decl;
> ? struct cgraph_node *node;
> ? struct bitpack_d bp;
> - ?int stack_size = 0;
> ? unsigned decl_index;
> ? int ref = LCC_NOT_FOUND, ref2 = LCC_NOT_FOUND;
> - ?int self_time = 0;
> - ?int self_size = 0;
> - ?int time_inlining_benefit = 0;
> - ?int size_inlining_benefit = 0;
> ? unsigned long same_body_count = 0;
> ? int clone_ref;
> ? enum ld_plugin_symbol_resolution resolution;
> @@ -1051,15 +1022,7 @@ input_node (struct lto_file_decl_data *f
> ? node->count_materialization_scale = lto_input_sleb128 (ib);
>
> ? if (tag == LTO_cgraph_analyzed_node)
> - ? ?{
> - ? ? ?stack_size = lto_input_sleb128 (ib);
> - ? ? ?self_size = lto_input_sleb128 (ib);
> - ? ? ?size_inlining_benefit = lto_input_sleb128 (ib);
> - ? ? ?self_time = lto_input_sleb128 (ib);
> - ? ? ?time_inlining_benefit = lto_input_sleb128 (ib);
> -
> - ? ? ?ref = lto_input_sleb128 (ib);
> - ? ?}
> + ? ?ref = lto_input_sleb128 (ib);
>
> ? ref2 = lto_input_sleb128 (ib);
>
> @@ -1073,9 +1036,7 @@ input_node (struct lto_file_decl_data *f
>
> ? bp = lto_input_bitpack (ib);
> ? resolution = (enum ld_plugin_symbol_resolution)lto_input_uleb128 (ib);
> - ?input_overwrite_node (file_data, node, tag, &bp, stack_size, self_time,
> - ? ? ? ? ? ? ? ? ? ? ? time_inlining_benefit, self_size,
> - ? ? ? ? ? ? ? ? ? ? ? size_inlining_benefit, resolution);
> + ?input_overwrite_node (file_data, node, tag, &bp, resolution);
>
> ? /* Store a reference for now, and fix up later to be a pointer. ?*/
> ? node->global.inlined_to = (cgraph_node_ptr) (intptr_t) ref;
> Index: ipa-inline.c
> ===================================================================
> --- ipa-inline.c ? ? ? ?(revision 172396)
> +++ ipa-inline.c ? ? ? ?(working copy)
> @@ -1301,6 +1301,9 @@ cgraph_decide_inlining (void)
> ? ? ? ? ? ? ?max_benefit = benefit;
> ? ? ? ? ?}
> ? ? ? }
> +
> + ?if (dump_file)
> + ? ?dump_inline_summaries (dump_file);
> ? gcc_assert (in_lto_p
> ? ? ? ? ? ? ?|| !max_count
> ? ? ? ? ? ? ?|| (profile_info && flag_branch_probabilities));
> @@ -1558,8 +1561,7 @@ cgraph_decide_inlining_incrementally (st
> ? ? ? /* When the function body would grow and inlining the function
> ? ? ? ? won't eliminate the need for offline copy of the function,
> ? ? ? ? don't inline. ?*/
> - ? ? ?if (estimate_edge_growth (e) > allowed_growth
> - ? ? ? ? && estimate_growth (e->callee) > allowed_growth)
> + ? ? ?if (estimate_edge_growth (e) > allowed_growth)
> ? ? ? ?{
> ? ? ? ? ?if (dump_file)
> ? ? ? ? ? ?fprintf (dump_file,
> @@ -1601,6 +1603,7 @@ static unsigned int
> ?cgraph_early_inlining (void)
> ?{
> ? struct cgraph_node *node = cgraph_get_node (current_function_decl);
> + ?struct cgraph_edge *edge;
> ? unsigned int todo = 0;
> ? int iterations = 0;
> ? bool inlined = false;
> @@ -1652,6 +1655,19 @@ cgraph_early_inlining (void)
> ? ? {
> ? ? ? timevar_push (TV_INTEGRATION);
> ? ? ? todo |= optimize_inline_calls (current_function_decl);
> +
> + ? ? ?/* Technically we ought to recompute inline parameters so the new iteration of
> + ? ? ? ?early inliner works as expected. ?We however have values approximately right
> + ? ? ? ?and thus we only need to update edge info that might be cleared out for
> + ? ? ? ?newly discovered edges. ?*/
> + ? ? ?for (edge = node->callees; edge; edge = edge->next_callee)
> + ? ? ? {
> + ? ? ? ? edge->call_stmt_size
> + ? ? ? ? ? = estimate_num_insns (edge->call_stmt, &eni_size_weights);
> + ? ? ? ? edge->call_stmt_time
> + ? ? ? ? ? = estimate_num_insns (edge->call_stmt, &eni_time_weights);
> + ? ? ? }
> +
> ? ? ? timevar_pop (TV_INTEGRATION);
> ? ? }
>
> Index: ipa-inline.h
> ===================================================================
> --- ipa-inline.h ? ? ? ?(revision 172396)
> +++ ipa-inline.h ? ? ? ?(working copy)
> @@ -19,6 +19,30 @@ You should have received a copy of the G
> ?along with GCC; see the file COPYING3. ?If not see
> ?<http://www.gnu.org/licenses/>. ?*/
>
> +/* Function inlining information. ?*/
> +
> +struct inline_summary
> +{
> + ?/* Estimated stack frame consumption by the function. ?*/
> + ?HOST_WIDE_INT estimated_self_stack_size;
> +
> + ?/* Size of the function body. ?*/
> + ?int self_size;
> + ?/* How many instructions are likely going to disappear after inlining. ?*/
> + ?int size_inlining_benefit;
> + ?/* Estimated time spent executing the function body. ?*/
> + ?int self_time;
> + ?/* How much time is going to be saved by inlining. ?*/
> + ?int time_inlining_benefit;
> +};
> +
> +typedef struct inline_summary inline_summary_t;
> +DEF_VEC_O(inline_summary_t);
> +DEF_VEC_ALLOC_O(inline_summary_t,heap);
> +extern VEC(inline_summary_t,heap) *inline_summary_vec;
> +
> +void debug_inline_summary (struct cgraph_node *);
> +void dump_inline_summaries (FILE *f);
> ?void inline_generate_summary (void);
> ?void inline_read_summary (void);
> ?void inline_write_summary (cgraph_node_set, varpool_node_set);
> @@ -30,7 +54,7 @@ int estimate_growth (struct cgraph_node
> ?static inline struct inline_summary *
> ?inline_summary (struct cgraph_node *node)
> ?{
> - ?return &node->local.inline_summary;
> + ?return VEC_index (inline_summary_t, inline_summary_vec, node->uid);
> ?}
>
> ?/* Estimate the growth of the caller when inlining EDGE. ?*/
> @@ -39,12 +63,8 @@ static inline int
> ?estimate_edge_growth (struct cgraph_edge *edge)
> ?{
> ? int call_stmt_size;
> - ?/* ??? ?We throw away cgraph edges all the time so the information
> - ? ? we store in edges doesn't persist for early inlining. ?Ugh. ?*/
> - ?if (!edge->call_stmt)
> - ? ?call_stmt_size = edge->call_stmt_size;
> - ?else
> - ? ?call_stmt_size = estimate_num_insns (edge->call_stmt, &eni_size_weights);
> + ?call_stmt_size = edge->call_stmt_size;
> + ?gcc_checking_assert (call_stmt_size);
> ? return (edge->callee->global.size
> ? ? ? ? ?- inline_summary (edge->callee)->size_inlining_benefit
> ? ? ? ? ?- call_stmt_size);
> Index: lto-section-in.c
> ===================================================================
> --- lto-section-in.c ? ?(revision 172396)
> +++ lto-section-in.c ? ?(working copy)
> @@ -58,7 +58,8 @@ const char *lto_section_name[LTO_N_SECTI
> ? "reference",
> ? "symtab",
> ? "opts",
> - ?"cgraphopt"
> + ?"cgraphopt",
> + ?"inline"
> ?};
>
> ?unsigned char
> Index: ipa.c
> ===================================================================
> --- ipa.c ? ? ? (revision 172396)
> +++ ipa.c ? ? ? (working copy)
> @@ -517,6 +517,8 @@ cgraph_remove_unreachable_nodes (bool be
> ? ? ? ? ? ? ?}
> ? ? ? ? ?}
> ? ? ? }
> + ?if (file)
> + ? ?fprintf (file, "\n");
>
> ?#ifdef ENABLE_CHECKING
> ? verify_cgraph ();
> Index: ipa-inline-analysis.c
> ===================================================================
> --- ipa-inline-analysis.c ? ? ? (revision 172396)
> +++ ipa-inline-analysis.c ? ? ? (working copy)
> @@ -23,13 +23,13 @@ along with GCC; see the file COPYING3.
>
> ? ?We estimate for each function
> ? ? ?- function body size
> - ? ? - function runtime
> + ? ? - average function execution time
> ? ? ?- inlining size benefit (that is how much of function body size
> ? ? ? ?and its call sequence is expected to disappear by inlining)
> ? ? ?- inlining time benefit
> ? ? ?- function frame size
> ? ?For each call
> - ? ? - call sequence size
> + ? ? - call statement size and time
>
> ? ?inlinie_summary datastructures store above information locally (i.e.
> ? ?parameters of the function itself) and globally (i.e. parameters of
> @@ -61,12 +61,100 @@ along with GCC; see the file COPYING3.
> ?#include "ggc.h"
> ?#include "tree-flow.h"
> ?#include "ipa-prop.h"
> +#include "lto-streamer.h"
> ?#include "ipa-inline.h"
>
> ?#define MAX_TIME 1000000000
>
> ?/* Holders of ipa cgraph hooks: */
> ?static struct cgraph_node_hook_list *function_insertion_hook_holder;
> +static struct cgraph_node_hook_list *node_removal_hook_holder;
> +static struct cgraph_2node_hook_list *node_duplication_hook_holder;
> +static void inline_node_removal_hook (struct cgraph_node *, void *);
> +static void inline_node_duplication_hook (struct cgraph_node *,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct cgraph_node *, void *);
> +
> +/* VECtor holding inline summaries. ?*/
> +VEC(inline_summary_t,heap) *inline_summary_vec;
> +
> +/* Allocate the inline summary vector or resize it to cover all cgraph nodes. */
> +
> +static void
> +inline_summary_alloc (void)
> +{
> + ?if (!node_removal_hook_holder)
> + ? ?node_removal_hook_holder =
> + ? ? ?cgraph_add_node_removal_hook (&inline_node_removal_hook, NULL);
> + ?if (!node_duplication_hook_holder)
> + ? ?node_duplication_hook_holder =
> + ? ? ?cgraph_add_node_duplication_hook (&inline_node_duplication_hook, NULL);
> +
> + ?if (VEC_length (inline_summary_t, inline_summary_vec)
> + ? ? ?<= (unsigned) cgraph_max_uid)
> + ? ?VEC_safe_grow_cleared (inline_summary_t, heap,
> + ? ? ? ? ? ? ? ? ? ? ? ? ?inline_summary_vec, cgraph_max_uid + 1);
> +}
> +
> +/* Hook that is called by cgraph.c when a node is removed. ?*/
> +
> +static void
> +inline_node_removal_hook (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
> +{
> + ?/* During IPA-CP updating we can be called on not-yet analyze clones. ?*/
> + ?if (VEC_length (inline_summary_t, inline_summary_vec)
> + ? ? ?<= (unsigned)node->uid)
> + ? ?return;
> + ?memset (inline_summary (node),
> + ? ? ? ? 0, sizeof (inline_summary_t));
> +}
> +
> +/* Hook that is called by cgraph.c when a node is duplicated. ?*/
> +
> +static void
> +inline_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ATTRIBUTE_UNUSED void *data)
> +{
> + ?inline_summary_alloc ();
> + ?memcpy (inline_summary (dst), inline_summary (src),
> + ? ? ? ? sizeof (struct inline_summary));
> +}
> +
> +static void
> +dump_inline_summary (FILE *f, struct cgraph_node *node)
> +{
> + ?if (node->analyzed)
> + ? ?{
> + ? ? ?struct inline_summary *s = inline_summary (node);
> + ? ? ?fprintf (f, "Inline summary for %s/%i\n", cgraph_node_name (node),
> + ? ? ? ? ? ? ?node->uid);
> + ? ? ?fprintf (f, " ?self time: ? ? ? %i, benefit: %i\n",
> + ? ? ? ? ? ? ?s->self_time, s->time_inlining_benefit);
> + ? ? ?fprintf (f, " ?global time: ? ? %i\n", node->global.time);
> + ? ? ?fprintf (f, " ?self size: ? ? ? %i, benefit: %i\n",
> + ? ? ? ? ? ? ?s->self_size, s->size_inlining_benefit);
> + ? ? ?fprintf (f, " ?global size: ? ? %i", node->global.size);
> + ? ? ?fprintf (f, " ?self stack: ? ? ?%i\n",
> + ? ? ? ? ? ? ?(int)s->estimated_self_stack_size);
> + ? ? ?fprintf (f, " ?global stack: ? ?%i\n",
> + ? ? ? ? ? ? ?(int)node->global.estimated_stack_size);
> + ? ?}
> +}
> +
> +void
> +debug_inline_summary (struct cgraph_node *node)
> +{
> + ?dump_inline_summary (stderr, node);
> +}
> +
> +void
> +dump_inline_summaries (FILE *f)
> +{
> + ?struct cgraph_node *node;
> +
> + ?for (node = cgraph_nodes; node; node = node->next)
> + ? ?if (node->analyzed)
> + ? ? ?dump_inline_summary (f, node);
> +}
>
> ?/* See if statement might disappear after inlining.
> ? ?0 - means not eliminated
> @@ -179,16 +267,27 @@ estimate_function_body_sizes (struct cgr
> ? ? ? ? ? ? ? ? ? ? ? freq, this_size, this_time);
> ? ? ? ? ? ? ?print_gimple_stmt (dump_file, stmt, 0, 0);
> ? ? ? ? ? ?}
> +
> + ? ? ? ? if (is_gimple_call (stmt))
> + ? ? ? ? ? {
> + ? ? ? ? ? ? struct cgraph_edge *edge = cgraph_edge (node, stmt);
> + ? ? ? ? ? ? edge->call_stmt_size = this_size;
> + ? ? ? ? ? ? edge->call_stmt_time = this_time;
> + ? ? ? ? ? }
> +
> ? ? ? ? ?this_time *= freq;
> ? ? ? ? ?time += this_time;
> ? ? ? ? ?size += this_size;
> +
> ? ? ? ? ?prob = eliminated_by_inlining_prob (stmt);
> ? ? ? ? ?if (prob == 1 && dump_file && (dump_flags & TDF_DETAILS))
> ? ? ? ? ? ?fprintf (dump_file, " ? ?50%% will be eliminated by inlining\n");
> ? ? ? ? ?if (prob == 2 && dump_file && (dump_flags & TDF_DETAILS))
> ? ? ? ? ? ?fprintf (dump_file, " ? ?will eliminated by inlining\n");
> +
> ? ? ? ? ?size_inlining_benefit += this_size * prob;
> ? ? ? ? ?time_inlining_benefit += this_time * prob;
> +
> ? ? ? ? ?gcc_assert (time >= 0);
> ? ? ? ? ?gcc_assert (size >= 0);
> ? ? ? ?}
> @@ -222,6 +321,8 @@ compute_inline_parameters (struct cgraph
>
> ? gcc_assert (!node->global.inlined_to);
>
> + ?inline_summary_alloc ();
> +
> ? /* Estimate the stack size for the function if we're optimizing. ?*/
> ? self_stack_size = optimize ? estimated_stack_frame_size (node) : 0;
> ? inline_summary (node)->estimated_self_stack_size = self_stack_size;
> @@ -247,17 +348,7 @@ compute_inline_parameters (struct cgraph
> ? ? ? node->local.can_change_signature = !e;
> ? ? }
> ? estimate_function_body_sizes (node);
> - ?/* Compute size of call statements. ?We have to do this for callers here,
> - ? ? those sizes need to be present for edges _to_ us as early as
> - ? ? we are finished with early opts. ?*/
> - ?for (e = node->callers; e; e = e->next_caller)
> - ? ?if (e->call_stmt)
> - ? ? ?{
> - ? ? ? e->call_stmt_size
> - ? ? ? ? = estimate_num_insns (e->call_stmt, &eni_size_weights);
> - ? ? ? e->call_stmt_time
> - ? ? ? ? = estimate_num_insns (e->call_stmt, &eni_time_weights);
> - ? ? ?}
> +
> ? /* Inlining characteristics are maintained by the cgraph_mark_inline. ?*/
> ? node->global.time = inline_summary (node)->self_time;
> ? node->global.size = inline_summary (node)->self_size;
> @@ -300,12 +391,8 @@ static inline int
> ?estimate_edge_time (struct cgraph_edge *edge)
> ?{
> ? int call_stmt_time;
> - ?/* ??? ?We throw away cgraph edges all the time so the information
> - ? ? we store in edges doesn't persist for early inlining. ?Ugh. ?*/
> - ?if (!edge->call_stmt)
> - ? ?call_stmt_time = edge->call_stmt_time;
> - ?else
> - ? ?call_stmt_time = estimate_num_insns (edge->call_stmt, &eni_time_weights);
> + ?call_stmt_time = edge->call_stmt_time;
> + ?gcc_checking_assert (call_stmt_time);
> ? return (((gcov_type)edge->callee->global.time
> ? ? ? ? ? - inline_summary (edge->callee)->time_inlining_benefit
> ? ? ? ? ? - call_stmt_time) * edge->frequency
> @@ -379,8 +466,10 @@ estimate_growth (struct cgraph_node *nod
> ? return growth;
> ?}
>
> +
> ?/* This function performs intraprocedural analysis in NODE that is required to
> ? ?inline indirect calls. ?*/
> +
> ?static void
> ?inline_indirect_intraprocedural_analysis (struct cgraph_node *node)
> ?{
> @@ -437,8 +526,6 @@ inline_generate_summary (void)
> ? for (node = cgraph_nodes; node; node = node->next)
> ? ? if (node->analyzed)
> ? ? ? inline_analyze_function (node);
> -
> - ?return;
> ?}
>
>
> @@ -449,6 +536,57 @@ inline_generate_summary (void)
> ?void
> ?inline_read_summary (void)
> ?{
> + ?struct lto_file_decl_data **file_data_vec = lto_get_file_decl_data ();
> + ?struct lto_file_decl_data *file_data;
> + ?unsigned int j = 0;
> +
> + ?inline_summary_alloc ();
> +
> + ?while ((file_data = file_data_vec[j++]))
> + ? ?{
> + ? ? ?size_t len;
> + ? ? ?const char *data = lto_get_section_data (file_data, LTO_section_inline_summary, NULL, &len);
> +
> + ? ? ?struct lto_input_block *ib
> + ? ? ? = lto_create_simple_input_block (file_data,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?LTO_section_inline_summary,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?&data, &len);
> + ? ? ?if (ib)
> + ? ? ? {
> + ? ? ? ? unsigned int i;
> + ? ? ? ? unsigned int f_count = lto_input_uleb128 (ib);
> +
> + ? ? ? ? for (i = 0; i < f_count; i++)
> + ? ? ? ? ? {
> + ? ? ? ? ? ? unsigned int index;
> + ? ? ? ? ? ? struct cgraph_node *node;
> + ? ? ? ? ? ? struct inline_summary *info;
> + ? ? ? ? ? ? lto_cgraph_encoder_t encoder;
> +
> + ? ? ? ? ? ? index = lto_input_uleb128 (ib);
> + ? ? ? ? ? ? encoder = file_data->cgraph_node_encoder;
> + ? ? ? ? ? ? node = lto_cgraph_encoder_deref (encoder, index);
> + ? ? ? ? ? ? info = inline_summary (node);
> +
> + ? ? ? ? ? ? node->global.estimated_stack_size
> + ? ? ? ? ? ? ? = info->estimated_self_stack_size = lto_input_uleb128 (ib);
> + ? ? ? ? ? ? node->global.time = info->self_time = lto_input_uleb128 (ib);
> + ? ? ? ? ? ? info->time_inlining_benefit = lto_input_uleb128 (ib);
> + ? ? ? ? ? ? node->global.size = info->self_size = lto_input_uleb128 (ib);
> + ? ? ? ? ? ? info->size_inlining_benefit = lto_input_uleb128 (ib);
> + ? ? ? ? ? ? node->global.estimated_growth = INT_MIN;
> + ? ? ? ? ? }
> +
> + ? ? ? ? lto_destroy_simple_input_block (file_data,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? LTO_section_inline_summary,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ib, data, len);
> + ? ? ? }
> + ? ? ?else
> + ? ? ? /* Fatal error here. ?We do not want to support compiling ltrans units with
> + ? ? ? ? ?different version of compiler or different flags than the WPA unit, so
> + ? ? ? ? ?this should never happen. ?*/
> + ? ? ? fatal_error ("ipa reference summary is missing in ltrans unit");
> + ? ?}
> ? if (flag_indirect_inlining)
> ? ? {
> ? ? ? ipa_register_cgraph_hooks ();
> @@ -468,14 +606,57 @@ void
> ?inline_write_summary (cgraph_node_set set,
> ? ? ? ? ? ? ? ? ? ? ?varpool_node_set vset ATTRIBUTE_UNUSED)
> ?{
> + ?struct cgraph_node *node;
> + ?struct lto_simple_output_block *ob
> + ? ?= lto_create_simple_output_block (LTO_section_inline_summary);
> + ?lto_cgraph_encoder_t encoder = ob->decl_state->cgraph_node_encoder;
> + ?unsigned int count = 0;
> + ?int i;
> +
> + ?for (i = 0; i < lto_cgraph_encoder_size (encoder); i++)
> + ? ?if (lto_cgraph_encoder_deref (encoder, i)->analyzed)
> + ? ? ?count++;
> + ?lto_output_uleb128_stream (ob->main_stream, count);
> +
> + ?for (i = 0; i < lto_cgraph_encoder_size (encoder); i++)
> + ? ?{
> + ? ? ?node = lto_cgraph_encoder_deref (encoder, i);
> + ? ? ?if (node->analyzed)
> + ? ? ? {
> + ? ? ? ? struct inline_summary *info = inline_summary (node);
> + ? ? ? ? lto_output_uleb128_stream (ob->main_stream,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?lto_cgraph_encoder_encode (encoder, node));
> + ? ? ? ? lto_output_sleb128_stream (ob->main_stream,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?info->estimated_self_stack_size);
> + ? ? ? ? lto_output_sleb128_stream (ob->main_stream,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?info->self_size);
> + ? ? ? ? lto_output_sleb128_stream (ob->main_stream,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?info->size_inlining_benefit);
> + ? ? ? ? lto_output_sleb128_stream (ob->main_stream,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?info->self_time);
> + ? ? ? ? lto_output_sleb128_stream (ob->main_stream,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?info->time_inlining_benefit);
> + ? ? ? }
> + ? ?}
> +
> ? if (flag_indirect_inlining && !flag_ipa_cp)
> ? ? ipa_prop_write_jump_functions (set);
> ?}
>
> +
> ?/* Release inline summary. ?*/
>
> ?void
> ?inline_free_summary (void)
> ?{
> - ?cgraph_remove_function_insertion_hook (function_insertion_hook_holder);
> + ?if (function_insertion_hook_holder)
> + ? ?cgraph_remove_function_insertion_hook (function_insertion_hook_holder);
> + ?function_insertion_hook_holder = NULL;
> + ?if (node_removal_hook_holder)
> + ? ?cgraph_remove_node_removal_hook (node_removal_hook_holder);
> + ?node_removal_hook_holder = NULL;
> + ?if (node_duplication_hook_holder)
> + ? ?cgraph_remove_node_duplication_hook (node_duplication_hook_holder);
> + ?node_duplication_hook_holder = NULL;
> + ?VEC_free (inline_summary_t, heap, inline_summary_vec);
> ?}
> Index: lto/lto.c
> ===================================================================
> --- lto/lto.c ? (revision 172396)
> +++ lto/lto.c ? (working copy)
> @@ -44,6 +44,7 @@ along with GCC; see the file COPYING3.
> ?#include "lto-streamer.h"
> ?#include "splay-tree.h"
> ?#include "params.h"
> +#include "ipa-inline.h"
>
> ?static GTY(()) tree first_personality_decl;
>
> @@ -750,7 +751,7 @@ add_cgraph_node_to_partition (ltrans_par
> ?{
> ? struct cgraph_edge *e;
>
> - ?part->insns += node->local.inline_summary.self_size;
> + ?part->insns += inline_summary (node)->self_size;
>
> ? if (node->aux)
> ? ? {
> @@ -811,7 +812,7 @@ undo_partition (ltrans_partition partiti
> ? ? ? struct cgraph_node *node = VEC_index (cgraph_node_ptr,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?partition->cgraph_set->nodes,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?n_cgraph_nodes);
> - ? ? ?partition->insns -= node->local.inline_summary.self_size;
> + ? ? ?partition->insns -= inline_summary (node)->self_size;
> ? ? ? cgraph_node_set_remove (partition->cgraph_set, node);
> ? ? ? node->aux = (void *)((size_t)node->aux - 1);
> ? ? }
> Index: lto/Make-lang.in
> ===================================================================
> --- lto/Make-lang.in ? ?(revision 172396)
> +++ lto/Make-lang.in ? ?(working copy)
> @@ -85,7 +85,8 @@ lto/lto.o: lto/lto.c $(CONFIG_H) $(SYSTE
> ? ? ? ?$(CGRAPH_H) $(GGC_H) tree-ssa-operands.h $(TREE_PASS_H) \
> ? ? ? ?langhooks.h $(VEC_H) $(BITMAP_H) pointer-set.h $(IPA_PROP_H) \
> ? ? ? ?$(COMMON_H) debug.h $(TIMEVAR_H) $(GIMPLE_H) $(LTO_H) $(LTO_TREE_H) \
> - ? ? ? $(LTO_TAGS_H) $(LTO_STREAMER_H) $(SPLAY_TREE_H) gt-lto-lto.h $(PARAMS_H)
> + ? ? ? $(LTO_TAGS_H) $(LTO_STREAMER_H) $(SPLAY_TREE_H) gt-lto-lto.h $(PARAMS_H) \
> + ? ? ? ipa-inline.h
> ?lto/lto-object.o: lto/lto-object.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
> ? ? ? ?$(DIAGNOSTIC_CORE_H) $(LTO_H) $(TM_H) $(LTO_STREAMER_H) \
> ? ? ? ?../include/simple-object.h
> Index: ipa-prop.c
> ===================================================================
> --- ipa-prop.c ?(revision 172396)
> +++ ipa-prop.c ?(working copy)
> @@ -1998,7 +1998,7 @@ ipa_edge_duplication_hook (struct cgraph
>
> ?static void
> ?ipa_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst,
> - ? ? ? ? ? ? ? ? ? ? ? ? ?__attribute__((unused)) void *data)
> + ? ? ? ? ? ? ? ? ? ? ? ? ?ATTRIBUTE_UNUSED void *data)
> ?{
> ? struct ipa_node_params *old_info, *new_info;
> ? int param_count, i;
> Index: Makefile.in
> ===================================================================
> --- Makefile.in (revision 172396)
> +++ Makefile.in (working copy)
> @@ -3011,7 +3011,7 @@ ipa-ref.o : ipa-ref.c $(CONFIG_H) $(SYST
> ?ipa-cp.o : ipa-cp.c $(CONFIG_H) $(SYSTEM_H) coretypes.h ?\
> ? ?$(TREE_H) $(TARGET_H) $(GIMPLE_H) $(CGRAPH_H) $(IPA_PROP_H) $(TREE_FLOW_H) \
> ? ?$(TREE_PASS_H) $(FLAGS_H) $(TIMEVAR_H) $(DIAGNOSTIC_H) $(TREE_DUMP_H) \
> - ? $(TREE_INLINE_H) $(FIBHEAP_H) $(PARAMS_H) tree-pretty-print.h
> + ? $(TREE_INLINE_H) $(FIBHEAP_H) $(PARAMS_H) tree-pretty-print.h ipa-inline.h
> ?ipa-split.o : ipa-split.c $(CONFIG_H) $(SYSTEM_H) coretypes.h ?\
> ? ?$(TREE_H) $(TARGET_H) $(CGRAPH_H) $(IPA_PROP_H) $(TREE_FLOW_H) \
> ? ?$(TREE_PASS_H) $(FLAGS_H) $(TIMEVAR_H) $(DIAGNOSTIC_H) $(TREE_DUMP_H) \
> @@ -3032,7 +3032,7 @@ ipa-inline-analysis.o : ipa-inline-analy
> ? ?$(TREE_H) langhooks.h $(TREE_INLINE_H) $(FLAGS_H) $(CGRAPH_H) intl.h \
> ? ?$(DIAGNOSTIC_H) $(PARAMS_H) $(TIMEVAR_H) $(TREE_PASS_H) \
> ? ?$(HASHTAB_H) $(COVERAGE_H) $(GGC_H) $(TREE_FLOW_H) $(IPA_PROP_H) \
> - ? gimple-pretty-print.h ipa-inline.h
> + ? gimple-pretty-print.h ipa-inline.h $(LTO_STREAMER_H)
> ?ipa-utils.o : ipa-utils.c $(IPA_UTILS_H) $(CONFIG_H) $(SYSTEM_H) \
> ? ?coretypes.h $(TM_H) $(TREE_H) $(TREE_FLOW_H) $(TREE_INLINE_H) langhooks.h \
> ? ?pointer-set.h $(GGC_H) $(GIMPLE_H) $(SPLAY_TREE_H) \
> Index: lto-streamer.h
> ===================================================================
> --- lto-streamer.h ? ? ?(revision 172396)
> +++ lto-streamer.h ? ? ?(working copy)
> @@ -264,6 +264,7 @@ enum lto_section_type
> ? LTO_section_symtab,
> ? LTO_section_opts,
> ? LTO_section_cgraph_opt_sum,
> + ?LTO_section_inline_summary,
> ? LTO_N_SECTION_TYPES ? ? ? ? ?/* Must be last. ?*/
> ?};
>
>


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]