Hi,
this patch makes inlining of functions called once to work even if they are 
called
by alias.

Bootstrapped/regtested x86_64-linux, comitted.

        PR middle-end/58094
        * ipa-inline.c (has_caller_p): New function.
        (want_inline_function_to_all_callers_p): Use it.
        (sum_callers, inline_to_all_callers): Break out from ...
        (ipa_inline): ... here.
Index: ipa-inline.c
===================================================================
--- ipa-inline.c        (revision 202334)
+++ ipa-inline.c        (working copy)
@@ -750,6 +750,15 @@ check_caller_edge (struct cgraph_node *n
           && node->callers != edge);
 }
 
+/* If NODE has a caller, return true.  */
+
+static bool
+has_caller_p (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
+{
+  if (node->callers)
+    return true;
+  return false;
+}
 
 /* Decide if inlining NODE would reduce unit size by eliminating
    the offline copy of function.  
@@ -763,7 +772,7 @@ want_inline_function_to_all_callers_p (s
    bool has_hot_call = false;
 
    /* Does it have callers?  */
-   if (!node->callers)
+   if (!cgraph_for_node_and_aliases (node, has_caller_p, NULL, true))
      return false;
    /* Already inlined?  */
    if (function->global.inlined_to)
@@ -1892,6 +1901,60 @@ flatten_function (struct cgraph_node *no
     inline_update_overall_summary (node);
 }
 
+/* Count number of callers of NODE and store it into DATA (that
+   points to int.  Worker for cgraph_for_node_and_aliases.  */
+
+static bool
+sum_callers (struct cgraph_node *node, void *data)
+{
+  struct cgraph_edge *e;
+  int *num_calls = (int *)data;
+
+  for (e = node->callers; e; e = e->next_caller)
+    (*num_calls)++;
+  return false;
+}
+
+/* Inline NODE to all callers.  Worker for cgraph_for_node_and_aliases.
+   DATA points to number of calls originally found so we avoid infinite
+   recursion.  */
+
+static bool
+inline_to_all_callers (struct cgraph_node *node, void *data)
+{
+  int *num_calls = (int *)data;
+  while (node->callers && !node->global.inlined_to)
+    {
+      struct cgraph_node *caller = node->callers->caller;
+
+      if (dump_file)
+       {
+         fprintf (dump_file,
+                  "\nInlining %s size %i.\n",
+                  cgraph_node_name (node),
+                  inline_summary (node)->size);
+         fprintf (dump_file,
+                  " Called once from %s %i insns.\n",
+                  cgraph_node_name (node->callers->caller),
+                  inline_summary (node->callers->caller)->size);
+       }
+
+      inline_call (node->callers, true, NULL, NULL, true);
+      if (dump_file)
+       fprintf (dump_file,
+                " Inlined into %s which now has %i size\n",
+                cgraph_node_name (caller),
+                inline_summary (caller)->size);
+      if (!(*num_calls)--)
+       {
+         if (dump_file)
+           fprintf (dump_file, "New calls found; giving up.\n");
+         break;
+       }
+    }
+  return false;
+}
+
 /* Decide on the inlining.  We do so in the topological order to avoid
    expenses on updating data structures.  */
 
@@ -2003,39 +2066,11 @@ ipa_inline (void)
              && want_inline_function_to_all_callers_p (node, cold))
            {
              int num_calls = 0;
-             struct cgraph_edge *e;
-             for (e = node->callers; e; e = e->next_caller)
-               num_calls++;
-             while (node->callers && !node->global.inlined_to)
-               {
-                 struct cgraph_node *caller = node->callers->caller;
-
-                 if (dump_file)
-                   {
-                     fprintf (dump_file,
-                              "\nInlining %s size %i.\n",
-                              cgraph_node_name (node),
-                              inline_summary (node)->size);
-                     fprintf (dump_file,
-                              " Called once from %s %i insns.\n",
-                              cgraph_node_name (node->callers->caller),
-                              inline_summary (node->callers->caller)->size);
-                   }
-
-                 inline_call (node->callers, true, NULL, NULL, true);
-                 remove_functions = true;
-                 if (dump_file)
-                   fprintf (dump_file,
-                            " Inlined into %s which now has %i size\n",
-                            cgraph_node_name (caller),
-                            inline_summary (caller)->size);
-                 if (!num_calls--)
-                   {
-                     if (dump_file)
-                       fprintf (dump_file, "New calls found; giving up.\n");
-                     break;
-                   }
-               }
+             cgraph_for_node_and_aliases (node, sum_callers,
+                                          &num_calls, true);
+             cgraph_for_node_and_aliases (node, inline_to_all_callers,
+                                          &num_calls, true);
+             remove_functions = true;
            }
        }
     }

Reply via email to