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
