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 <[email protected]> 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 <[email protected]>
> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]>
>>>>
>>>> * 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. */