I change to use the bfd_name, which is much shorter for C++ symbols. Thanks, Dehao
On Thu, Dec 15, 2011 at 2:07 AM, Xinliang David Li <davi...@google.com> wrote: > Another usability related issue for C++. The long demangled function > names will make the info messages very hard to swallow. Since there > will be source lines to show the source context, it might be better to > just use the short decl names. The downside is it can be ambiguous for > template functions. > > David > > On Tue, Dec 13, 2011 at 11:18 PM, Xinliang David Li <davi...@google.com> > wrote: >> There are a couple of problems with the patch (the patch is only >> compatible with 4_6 branch) >> >> 1) the dump_inline_decision should be called inside >> cgraph_mark_inline_edge when the edge is finally picked (and when the >> callee node is cloned) >> 2) The source location is not printed which makes the dumping less useful >> 3) the information line should clearly print out the final caller >> where the inlining happens, and the intermediate inline instance >> information should be clearly printed as additional information >> showing the inline context. For instance, >> >> foo1->foo2->foo3->foo4 >> >> If all callsites are inlined in top down order, the messages I expect >> to see are: >> >> a.c:5: note: 'foo2' is inlined into 'foo1' with call count xxxx >> a.c:10: note: 'foo3' is inlined into 'foo1' with call count yyyy (via >> inline instance 'foo2') >> a.c:20: note: 'foo4' is inlined into foo1' with call count zzzz (via >> inline instances 'foo3', 'foo2') >> >> >> If the decision is bottom up, the messages should look like: >> >> a.c:20: note: 'foo4' is inlined into 'foo3' with call count zzzz >> a.c:10: note: 'foo3' is inlined into 'foo2' with call count yyyy >> a.c:5: note: 'foo2' is inlined into 'foo1' with call count xxxx >> >> Ideally, the caller and callee should also be marked with 'entry count >> and max bb count' information -- but that probably should be >> controlled by opt-info level. >> >> 4) Also notice that for inline node clones, the right way to walk up >> the call context chain is via 'edge->caller->callers'. >> 5) there should be a test case. >> >> Thanks, >> >> David >> >> On Tue, Dec 13, 2011 at 5:13 PM, Dehao Chen <de...@google.com> wrote: >>> I've updated the patch to fix a bug in dump_inline_decision. >>> >>> Thanks, >>> Dehao >>> >>> On Thu, Dec 1, 2011 at 9:59 AM, Dehao Chen <de...@google.com> wrote: >>>> >>>> This patch is for google-{main|gcc_4.6} only. >>>> >>>> Tested with bootstrap and regression tests. >>>> >>>> Dump inline decisions, also output the inline chain. >>>> >>>> Dehao >>>> >>>> 2011-12-01 Dehao Chen <de...@google.com> >>>> >>>> * ipa-inline.c (dump_inline_decision): New function. >>>> (inline_small_functions): Use it to dump the inline decisions to >>>> stderr. >>>> >>>> Index: gcc/ipa-inline.c >>>> =================================================================== >>>> --- gcc/ipa-inline.c (revision 181835) >>>> +++ gcc/ipa-inline.c (working copy) >>>> @@ -1377,6 +1377,45 @@ >>>> } >>>> >>>> >>>> +/* Dump the inline decision of EDGE to stderr. */ >>>> + >>>> +static void >>>> +dump_inline_decision (struct cgraph_edge *edge) >>>> +{ >>>> + location_t locus; >>>> + size_t buf_size = 4096; >>>> + size_t current_string_len = 0; >>>> + char *buf = (char *) xmalloc (buf_size); >>>> + struct cgraph_node *inlined_to; >>>> + gcov_type callee_count = edge->callee->count; >>>> + buf[0] = 0; >>>> + if (edge->inline_failed == CIF_OK && edge->callee->clone_of) >>>> + callee_count += edge->callee->clone_of->count; >>>> + for (inlined_to = edge->caller->global.inlined_to; >>>> + inlined_to; inlined_to = inlined_to->global.inlined_to) >>>> + { >>>> + const char *name = cgraph_node_name (inlined_to); >>>> + if (!name) >>>> + name = "unknown"; >>>> + current_string_len += (strlen (name) + 4); >>>> + while (current_string_len >= buf_size) >>>> + { >>>> + buf_size *= 2; >>>> + buf = (char *) xrealloc (buf, buf_size); >>>> + } >>>> + strcat (buf, "-->"); >>>> + strcat (buf, name); >>>> + } >>>> + locus = gimple_location (edge->call_stmt); >>>> + inform (locus, "%s ("HOST_WIDEST_INT_PRINT_DEC") --" >>>> + HOST_WIDEST_INT_PRINT_DEC"--> %s (" >>>> + HOST_WIDEST_INT_PRINT_DEC") %s : %s", >>>> + cgraph_node_name (edge->callee), callee_count, edge->count, >>>> + cgraph_node_name (edge->caller), edge->caller->count, buf, >>>> + edge->inline_failed == CIF_OK ? "INLINED": "IGNORED"); >>>> +} >>>> + >>>> + >>>> /* We use greedy algorithm for inlining of small functions: >>>> All inline candidates are put into prioritized heap ordered in >>>> increasing badness. >>>> @@ -1428,6 +1467,7 @@ >>>> overall_size = initial_size; >>>> max_size = compute_max_insns (overall_size); >>>> min_size = overall_size; >>>> + edge = NULL; >>>> >>>> /* Populate the heeap with all edges we might inline. */ >>>> >>>> @@ -1462,6 +1502,9 @@ >>>> int current_badness; >>>> int growth; >>>> >>>> + if (edge && flag_opt_info >= OPT_INFO_MIN) >>>> + dump_inline_decision (edge); >>>> + >>>> edge = (struct cgraph_edge *) fibheap_extract_min (heap); >>>> gcc_assert (edge->aux); >>>> edge->aux = NULL; >>>> @@ -1482,6 +1525,7 @@ >>>> if (current_badness != badness) >>>> { >>>> edge->aux = fibheap_insert (heap, current_badness, edge); >>>> + edge = NULL; >>>> continue; >>>> } >>>> >>>> @@ -1636,6 +1680,8 @@ >>>> fprintf (dump_file, "New minimal size reached: %i\n", min_size); >>>> } >>>> } >>>> + if (edge && flag_opt_info >= OPT_INFO_MIN) >>>> + dump_inline_decision (edge); >>>> >>>> free_growth_caches (); >>>> if (new_indirect_edges)
Index: testsuite/gcc.dg/inline-dump.c =================================================================== --- testsuite/gcc.dg/inline-dump.c (revision 0) +++ testsuite/gcc.dg/inline-dump.c (revision 0) @@ -0,0 +1,6 @@ +/* Verify that -fopt-info can output correct inline info. */ +/* { dg-do compile } */ +/* { dg-options "-Wall -fopt-info -O2 -fno-early-inlining" } */ +static inline int foo(void) { return 1; } +int bar1(void) { return foo(); } /* { dg-message "note: foo inlined into bar1 with call count 0" } */ +int bar2(void) { return foo(); } /* { dg-message "note: foo inlined into bar2 with call count 0" } */ Index: ipa-inline.c =================================================================== --- ipa-inline.c (revision 181835) +++ ipa-inline.c (working copy) @@ -292,6 +292,96 @@ cgraph_clone_inlined_nodes (e, duplicate, update_original); } +#define MAX_INT_LENGTH 16 + +/* Return NODE's name and aux info. The output is controled by OPT_INFO + level. */ + +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->decl, 0); + const char *count_text = "count="; + const char *max_count_text = "max_count="; + + if (!bfd_name) + bfd_name = "unknown"; + + buf_size = strlen (bfd_name) + 1; + if (flag_opt_info >= OPT_INFO_MED) + buf_size += (strlen (count_text) + MAX_INT_LENGTH + 1); + if (flag_opt_info >= OPT_INFO_MAX) + buf_size += (strlen (max_count_text) + MAX_INT_LENGTH + 1); + buf = (char *) xmalloc (buf_size); + + strcpy (buf, bfd_name); + if (flag_opt_info >= OPT_INFO_MED) + sprintf (buf, "%s,%s"HOST_WIDEST_INT_PRINT_DEC, + buf, count_text, node->count); + if (flag_opt_info >= OPT_INFO_MAX) + sprintf (buf, "%s,%s"HOST_WIDEST_INT_PRINT_DEC, + buf, max_count_text, node->max_bb_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->clone_of != NULL); + strcat (buf, via_str); + for (node = caller; node->clone_of != 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 to stderr. */ + +static void +dump_inline_decision (struct cgraph_edge *edge) +{ + location_t locus; + const char *inline_chain_text; + struct cgraph_node *final_caller = edge->caller; + + if (final_caller->clone_of != NULL) + inline_chain_text = cgraph_node_call_chain (final_caller, &final_caller); + else + inline_chain_text = ""; + + locus = gimple_location (edge->call_stmt); + inform (locus, + "%s inlined into %s with call count "HOST_WIDEST_INT_PRINT_DEC"%s", + cgraph_node_opt_info (edge->callee), + cgraph_node_opt_info (final_caller), + edge->count, + 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 @@ -311,6 +401,9 @@ if (L_IPO_COMP_MODE && !e->call_stmt) return false; + if (flag_opt_info >= OPT_INFO_MIN) + dump_inline_decision (e); + /* Don't inline inlined edges. */ gcc_assert (e->inline_failed); /* Don't even think of inlining inline clone. */