On Wed, Aug 28, 2013 at 7:09 AM, Teresa Johnson <tejohn...@google.com> wrote: >> The inline stuff should be split and re-sent, it's non-obvious to me (extra >> function parameters are not documented for example). I'd rather have >> inline_and_report_call () for example instead of an extra bool parameter. >> But let's iterate over this once it's split out. > > Ok, I will send this separately. I guess we could have a separate > interface inline_and_report_call that is a wrapper around inline_call > and simply invokes the dumper. Note that flatten_function will need to > conditionally call one of the two interfaces based on the value of its > bool early parameter though.
Here is the split out patch. I realized why I need the extra bool parameter to indicate early inlining: the early inliner messages are emitted only under the more verbose MSG_NOTE, so we need to know whether we are in early or ipa inlining in dump_inline_decision. I have documented the additional parameter. Thanks, Teresa 2013-08-29 Teresa Johnson <tejohn...@google.com> Dehao Chen <de...@google.com> * ipa-inline.c (recursive_inlining): New inline_call parameter. (inline_small_functions): Ditto. (flatten_function): Ditto. (ipa_inline): Ditto. (inline_always_inline_functions): Ditto. (early_inline_small_functions): Ditto. * ipa-inline.h: Ditto. * ipa-inline-transform.c (cgraph_node_opt_info): New function. (cgraph_node_call_chain): Ditto. (dump_inline_decision): Ditto. (inline_call): Invoke dump_inline_decision, new parameter. Index: ipa-inline.c =================================================================== --- ipa-inline.c (revision 202059) +++ ipa-inline.c (working copy) @@ -1342,7 +1342,7 @@ recursive_inlining (struct cgraph_edge *edge, reset_edge_growth_cache (curr); } - inline_call (curr, false, new_edges, &overall_size, true); + inline_call (curr, false, new_edges, &overall_size, true, false); lookup_recursive_calls (node, curr->callee, heap); n++; } @@ -1757,7 +1757,8 @@ inline_small_functions (void) fprintf (dump_file, " Peeling recursion with depth %i\n", depth); gcc_checking_assert (!callee->global.inlined_to); - inline_call (edge, true, &new_indirect_edges, &overall_size, true); + inline_call (edge, true, &new_indirect_edges, &overall_size, true, + false); if (flag_indirect_inlining) add_new_edges_to_heap (edge_heap, new_indirect_edges); @@ -1879,7 +1880,7 @@ flatten_function (struct cgraph_node *node, bool e xstrdup (cgraph_node_name (callee)), xstrdup (cgraph_node_name (e->caller))); orig_callee = callee; - inline_call (e, true, NULL, NULL, false); + inline_call (e, true, NULL, NULL, false, early); if (e->callee != orig_callee) orig_callee->symbol.aux = (void *) node; flatten_function (e->callee, early); @@ -2017,7 +2018,7 @@ ipa_inline (void) inline_summary (node->callers->caller)->size); } - inline_call (node->callers, true, NULL, NULL, true); + inline_call (node->callers, true, NULL, NULL, true, false); if (dump_file) fprintf (dump_file, " Inlined into %s which now has %i size\n", @@ -2089,7 +2090,7 @@ inline_always_inline_functions (struct cgraph_node fprintf (dump_file, " Inlining %s into %s (always_inline).\n", xstrdup (cgraph_node_name (e->callee)), xstrdup (cgraph_node_name (e->caller))); - inline_call (e, true, NULL, NULL, false); + inline_call (e, true, NULL, NULL, false, true); inlined = true; } if (inlined) @@ -2141,7 +2142,7 @@ early_inline_small_functions (struct cgraph_node * fprintf (dump_file, " Inlining %s into %s.\n", xstrdup (cgraph_node_name (callee)), xstrdup (cgraph_node_name (e->caller))); - inline_call (e, true, NULL, NULL, true); + inline_call (e, true, NULL, NULL, true, true); inlined = true; } Index: ipa-inline.h =================================================================== --- ipa-inline.h (revision 202059) +++ ipa-inline.h (working copy) @@ -229,7 +229,8 @@ void compute_inline_parameters (struct cgraph_node bool speculation_useful_p (struct cgraph_edge *e, bool anticipate_inlining); /* In ipa-inline-transform.c */ -bool inline_call (struct cgraph_edge *, bool, vec<cgraph_edge_p> *, int *, bool); +bool inline_call (struct cgraph_edge *, bool, vec<cgraph_edge_p> *, int *, + bool, bool); unsigned int inline_transform (struct cgraph_node *); void clone_inlined_nodes (struct cgraph_edge *e, bool, bool, int *); Index: ipa-inline-transform.c =================================================================== --- ipa-inline-transform.c (revision 202059) +++ ipa-inline-transform.c (working copy) @@ -202,12 +202,119 @@ clone_inlined_nodes (struct cgraph_edge *e, bool d } +#define MAX_INT_LENGTH 20 + +/* Return NODE's name and profile count, if available. */ + +static const char * +cgraph_node_opt_info (struct cgraph_node *node) +{ + char *buf; + size_t buf_size; + const char *bfd_name = lang_hooks.dwarf_name (node->symbol.decl, 0); + + if (!bfd_name) + bfd_name = "unknown"; + + buf_size = strlen (bfd_name) + 1; + if (profile_info) + buf_size += (MAX_INT_LENGTH + 3); + buf_size += MAX_INT_LENGTH; + + buf = (char *) xmalloc (buf_size); + + strcpy (buf, bfd_name); + sprintf (buf, "%s/%i", buf, node->symbol.order); + + if (profile_info) + sprintf (buf, "%s ("HOST_WIDEST_INT_PRINT_DEC")", buf, node->count); + return buf; +} + + +/* Return CALLER's inlined call chain. Save the cgraph_node of the ultimate + function that the caller is inlined to in FINAL_CALLER. */ + +static const char * +cgraph_node_call_chain (struct cgraph_node *caller, + struct cgraph_node **final_caller) +{ + struct cgraph_node *node; + const char *via_str = " (via inline instance"; + size_t current_string_len = strlen (via_str) + 1; + size_t buf_size = current_string_len; + char *buf = (char *) xmalloc (buf_size); + + buf[0] = 0; + gcc_assert (caller->global.inlined_to != NULL); + strcat (buf, via_str); + for (node = caller; node->global.inlined_to != NULL; + node = node->callers->caller) + { + const char *name = cgraph_node_opt_info (node); + current_string_len += (strlen (name) + 1); + if (current_string_len >= buf_size) + { + buf_size = current_string_len * 2; + buf = (char *) xrealloc (buf, buf_size); + } + strcat (buf, " "); + strcat (buf, name); + } + strcat (buf, ")"); + *final_caller = node; + return buf; +} + + +/* Dump the inline decision of EDGE. If EARLY is true this is called + from early inlining, which is printed only under more verbose + reporting options, otherwise we are in ipa inlining. */ + +static void +dump_inline_decision (struct cgraph_edge *edge, bool early) +{ + location_t locus; + const char *inline_chain_text; + const char *call_count_text; + struct cgraph_node *final_caller = edge->caller; + + if (final_caller->global.inlined_to != NULL) + inline_chain_text = cgraph_node_call_chain (final_caller, &final_caller); + else + inline_chain_text = ""; + + if (edge->count > 0) + { + const char *call_count_str = " with call count "; + char *buf = (char *) xmalloc (strlen (call_count_str) + MAX_INT_LENGTH); + sprintf (buf, "%s"HOST_WIDEST_INT_PRINT_DEC, call_count_str, + edge->count); + call_count_text = buf; + } + else + { + call_count_text = ""; + } + + locus = gimple_location (edge->call_stmt); + dump_printf_loc (early ? MSG_NOTE : MSG_OPTIMIZED_LOCATIONS, + locus, + "%s inlined into %s%s%s\n", + cgraph_node_opt_info (edge->callee), + cgraph_node_opt_info (final_caller), + call_count_text, + inline_chain_text); +} + + /* Mark edge E as inlined and update callgraph accordingly. UPDATE_ORIGINAL specify whether profile of original function should be updated. If any new indirect edges are discovered in the process, add them to NEW_EDGES, unless - it is NULL. If UPDATE_OVERALL_SUMMARY is false, do not bother to recompute overall - size of caller after inlining. Caller is required to eventually do it via - inline_update_overall_summary. + it is NULL. If UPDATE_OVERALL_SUMMARY is false, do not bother to recompute + overall size of caller after inlining. Caller is required to eventually do + it via inline_update_overall_summary. If EARLY is true then we are in + early inlining, otherwise ipa inlining. Return true iff any new callgraph edges were discovered as a result of inlining. */ @@ -215,7 +322,8 @@ clone_inlined_nodes (struct cgraph_edge *e, bool d bool inline_call (struct cgraph_edge *e, bool update_original, vec<cgraph_edge_p> *new_edges, - int *overall_size, bool update_overall_summary) + int *overall_size, bool update_overall_summary, + bool early) { int old_size = 0, new_size = 0; struct cgraph_node *to = NULL; @@ -228,6 +336,9 @@ inline_call (struct cgraph_edge *e, bool update_or bool predicated = inline_edge_summary (e)->predicate != NULL; #endif + if (dump_enabled_p ()) + dump_inline_decision (e, early); + speculation_removed = false; /* Don't inline inlined edges. */ gcc_assert (e->inline_failed); -- Teresa Johnson | Software Engineer | tejohn...@google.com | 408-460-2413