cgraph.c (cgraph_for_node_thunks_and_aliases, [...]): Fix thinko in recursive walking.
authorJan Hubicka <jh@suse.cz>
Mon, 13 Jun 2011 09:19:09 +0000 (11:19 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Mon, 13 Jun 2011 09:19:09 +0000 (09:19 +0000)
* cgraph.c (cgraph_for_node_thunks_and_aliases,
cgraph_for_node_and_aliases): Fix thinko in recursive walking.
(nonremovable_p): New function.
(cgraph_can_remove_if_no_direct_calls_p): New function.
(used_from_object_file_p): New functoin.
(cgraph_will_be_removed_from_program_if_no_direct_calls): Look for references
from aliases.
* cgraph.h (cgraph_can_remove_if_no_direct_calls_p): Bring offline.
* ipa-inline.c (check_caller_edge): New function.
(want_inline_function_called_once_p): Use it; accept aliases called once, too.
* ipa-inline-analysis.c (do_estimate_growth): Remove FIXME.

From-SVN: r174985

gcc/ChangeLog
gcc/cgraph.c
gcc/cgraph.h
gcc/ipa-inline-analysis.c
gcc/ipa-inline.c

index 87bb65fc55ae048bd738ee45f6947991f63aa764..5404f099f210b49e56037d3601a0492d739324f1 100644 (file)
@@ -1,3 +1,17 @@
+2011-06-13  Jan Hubicka  <jh@suse.cz>
+
+       * cgraph.c (cgraph_for_node_thunks_and_aliases,
+       cgraph_for_node_and_aliases): Fix thinko in recursive walking.
+       (nonremovable_p): New function.
+       (cgraph_can_remove_if_no_direct_calls_p): New function.
+       (used_from_object_file_p): New functoin.
+       (cgraph_will_be_removed_from_program_if_no_direct_calls): Look for references
+       from aliases.
+       * cgraph.h (cgraph_can_remove_if_no_direct_calls_p): Bring offline.
+       * ipa-inline.c (check_caller_edge): New function.
+       (want_inline_function_called_once_p): Use it; accept aliases called once, too.
+       * ipa-inline-analysis.c (do_estimate_growth): Remove FIXME.
+
 2011-06-13  Ramana Radhakrishnan  <ramana.radhakrishnan@linaro.org>
 
        PR target/48454
index 2805d46dfadc403fe9c843cf18668e528bc08932..dfa5439ad9638d011c04aebe9c832b58ddc2b92f 100644 (file)
@@ -2567,14 +2567,18 @@ cgraph_for_node_thunks_and_aliases (struct cgraph_node *node,
     if (e->caller->thunk.thunk_p
        && (include_overwritable
            || cgraph_function_body_availability (e->caller)))
-      cgraph_for_node_thunks_and_aliases (e->caller, callback, data, include_overwritable);
+      if (cgraph_for_node_thunks_and_aliases (e->caller, callback, data,
+                                             include_overwritable))
+       return true;
   for (i = 0; ipa_ref_list_refering_iterate (&node->ref_list, i, ref); i++)
     if (ref->use == IPA_REF_ALIAS)
       {
        struct cgraph_node *alias = ipa_ref_refering_node (ref);
        if (include_overwritable
            || cgraph_function_body_availability (alias) > AVAIL_OVERWRITABLE)
-          cgraph_for_node_thunks_and_aliases (alias, callback, data, include_overwritable);
+         if (cgraph_for_node_thunks_and_aliases (alias, callback, data,
+                                                 include_overwritable))
+           return true;
       }
   return false;
 }
@@ -2600,7 +2604,9 @@ cgraph_for_node_and_aliases (struct cgraph_node *node,
        struct cgraph_node *alias = ipa_ref_refering_node (ref);
        if (include_overwritable
            || cgraph_function_body_availability (alias) > AVAIL_OVERWRITABLE)
-          cgraph_for_node_and_aliases (alias, callback, data, include_overwritable);
+          if (cgraph_for_node_and_aliases (alias, callback, data,
+                                          include_overwritable))
+           return true;
       }
   return false;
 }
@@ -2900,6 +2906,36 @@ cgraph_can_remove_if_no_direct_calls_and_refs_p (struct cgraph_node *node)
   return true;
 }
 
+/* Worker for cgraph_can_remove_if_no_direct_calls_p.  */
+
+static bool
+nonremovable_p (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
+{
+  return !cgraph_can_remove_if_no_direct_calls_and_refs_p (node);
+}
+
+/* Return true when function NODE and its aliases can be removed from callgraph
+   if all direct calls are eliminated.  */
+
+bool
+cgraph_can_remove_if_no_direct_calls_p (struct cgraph_node *node)
+{
+  /* Extern inlines can always go, we will use the external definition.  */
+  if (DECL_EXTERNAL (node->decl))
+    return true;
+  if (node->address_taken)
+    return false;
+  return !cgraph_for_node_and_aliases (node, nonremovable_p, NULL, true);
+}
+
+/* Worker for cgraph_can_remove_if_no_direct_calls_p.  */
+
+static bool
+used_from_object_file_p (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
+{
+  return cgraph_used_from_object_file_p (node);
+}
+
 /* Return true when function NODE can be expected to be removed
    from program when direct calls in this compilation unit are removed.
 
@@ -2918,7 +2954,7 @@ bool
 cgraph_will_be_removed_from_program_if_no_direct_calls (struct cgraph_node *node)
 {
   gcc_assert (!node->global.inlined_to);
-  if (cgraph_used_from_object_file_p (node))
+  if (cgraph_for_node_and_aliases (node, used_from_object_file_p, NULL, true))
     return false;
   if (!in_lto_p && !flag_whole_program)
     return cgraph_only_called_directly_p (node);
index 09d99b1c1f7426f4018aa40a4645fb352d36de01..feb742d387e16bd07cb08e663e1b0f271604b405 100644 (file)
@@ -535,6 +535,7 @@ bool cgraph_will_be_removed_from_program_if_no_direct_calls
   (struct cgraph_node *node);
 bool cgraph_can_remove_if_no_direct_calls_and_refs_p
   (struct cgraph_node *node);
+bool cgraph_can_remove_if_no_direct_calls_p (struct cgraph_node *node);
 bool resolution_used_from_other_file_p (enum ld_plugin_symbol_resolution);
 bool cgraph_used_from_object_file_p (struct cgraph_node *);
 bool varpool_used_from_object_file_p (struct varpool_node *);
@@ -922,20 +923,6 @@ cgraph_only_called_directly_or_aliased_p (struct cgraph_node *node)
          && !node->local.externally_visible);
 }
 
-/* Return true when function NODE can be removed from callgraph
-   if all direct calls are eliminated.  */
-
-static inline bool
-cgraph_can_remove_if_no_direct_calls_p (struct cgraph_node *node)
-{
-  /* Extern inlines can always go, we will use the external definition.  */
-  if (DECL_EXTERNAL (node->decl))
-    return true;
-  return (!node->address_taken
-         && cgraph_can_remove_if_no_direct_calls_and_refs_p (node)
-         && !ipa_ref_has_aliases_p (&node->ref_list));
-}
-
 /* Return true when function NODE can be removed from callgraph
    if all direct calls are eliminated.  */
 
index 473f554e4ae184c5f305a9b5d5f5deea69cd49ba..43e0f8124d0cff0fe4f9112210b9b7ac930372cc 100644 (file)
@@ -2229,8 +2229,7 @@ do_estimate_growth (struct cgraph_node *node)
          && !cgraph_will_be_removed_from_program_if_no_direct_calls (node))
        d.growth -= info->size;
       /* COMDAT functions are very often not shared across multiple units since they
-        come from various template instantiations.  Take this into account.
-         FIXME: allow also COMDATs with COMDAT aliases.  */
+        come from various template instantiations.  Take this into account.  */
       else  if (DECL_COMDAT (node->decl)
                && cgraph_can_remove_if_no_direct_calls_p (node))
        d.growth -= (info->size
index 4283770a1c3e87b1ff10f74052562d998ebec975..a2e55b981b774497c58c5829cb3170fc44d2b39f 100644 (file)
@@ -643,6 +643,16 @@ want_inline_self_recursive_call_p (struct cgraph_edge *edge,
   return want_inline;
 }
 
+/* Return true when NODE has caller other than EDGE. 
+   Worker for cgraph_for_node_and_aliases.  */
+
+static bool
+check_caller_edge (struct cgraph_node *node, void *edge)
+{
+  return (node->callers
+          && node->callers != edge);
+}
+
 
 /* Decide if NODE is called once inlining it would eliminate need
    for the offline copy of function.  */
@@ -650,24 +660,26 @@ want_inline_self_recursive_call_p (struct cgraph_edge *edge,
 static bool
 want_inline_function_called_once_p (struct cgraph_node *node)
 {
-   if (node->alias)
-     return false;
+   struct cgraph_node *function = cgraph_function_or_thunk_node (node, NULL);
    /* Already inlined?  */
-   if (node->global.inlined_to)
+   if (function->global.inlined_to)
      return false;
    /* Zero or more then one callers?  */
    if (!node->callers
        || node->callers->next_caller)
      return false;
+   /* Maybe other aliases has more direct calls.  */
+   if (cgraph_for_node_and_aliases (node, check_caller_edge, node->callers, true))
+     return false;
    /* Recursive call makes no sense to inline.  */
-   if (node->callers->caller == node)
+   if (cgraph_edge_recursive_p (node->callers))
      return false;
    /* External functions are not really in the unit, so inlining
       them when called once would just increase the program size.  */
-   if (DECL_EXTERNAL (node->decl))
+   if (DECL_EXTERNAL (function->decl))
      return false;
    /* Offline body must be optimized out.  */
-   if (!cgraph_will_be_removed_from_program_if_no_direct_calls (node))
+   if (!cgraph_will_be_removed_from_program_if_no_direct_calls (function))
      return false;
    if (!can_inline_edge_p (node->callers, true))
      return false;