From patchwork Thu Dec 15 08:30:22 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Dehao Chen X-Patchwork-Id: 131533 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 337951007D7 for ; Thu, 15 Dec 2011 19:30:47 +1100 (EST) Received: (qmail 22558 invoked by alias); 15 Dec 2011 08:30:42 -0000 Received: (qmail 22530 invoked by uid 22791); 15 Dec 2011 08:30:37 -0000 X-SWARE-Spam-Status: No, hits=-3.3 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, RP_MATCHES_RCVD, TW_CP X-Spam-Check-By: sourceware.org Received: from mail-iy0-f175.google.com (HELO mail-iy0-f175.google.com) (209.85.210.175) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 15 Dec 2011 08:30:23 +0000 Received: by iadj38 with SMTP id j38so2748980iad.20 for ; Thu, 15 Dec 2011 00:30:22 -0800 (PST) Received: by 10.50.140.1 with SMTP id rc1mr2315303igb.25.1323937822596; Thu, 15 Dec 2011 00:30:22 -0800 (PST) MIME-Version: 1.0 Received: by 10.50.140.1 with SMTP id rc1mr2315295igb.25.1323937822510; Thu, 15 Dec 2011 00:30:22 -0800 (PST) Received: by 10.50.85.132 with HTTP; Thu, 15 Dec 2011 00:30:22 -0800 (PST) In-Reply-To: References: Date: Thu, 15 Dec 2011 16:30:22 +0800 Message-ID: Subject: Re: [google] dump inline decisions to stderr under -fopt-info From: Dehao Chen To: Xinliang David Li Cc: gcc-patches@gcc.gnu.org X-System-Of-Record: true X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org 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 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 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 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 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   >>>> >>>>        * 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. */