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

Reply via email to