Hi,
the original update of inliner for aliases contined some lazyness. This patch 
fixes I think
last remainder of it where inliner did not remove symbol with aliases on it.
This is more important now when ICF uses aliases quite often.

Bootstrapped/regtested x86_64-linux, comitted.

        PR ipa/63671
        * ipa-inline-transform.c (can_remove_node_now_p_1): Handle alises
        and -fno-devirtualize more carefully.
        (can_remove_node_now_p): Update.
Index: ipa-inline-transform.c
===================================================================
--- ipa-inline-transform.c      (revision 217980)
+++ ipa-inline-transform.c      (working copy)
@@ -93,19 +93,28 @@ update_noncloned_frequencies (struct cgr
    copy of function was removed.  */
 
 static bool
-can_remove_node_now_p_1 (struct cgraph_node *node)
+can_remove_node_now_p_1 (struct cgraph_node *node, struct cgraph_edge *e)
 {
+  ipa_ref *ref;
+
+  FOR_EACH_ALIAS (node, ref)
+    {
+      cgraph_node *alias = dyn_cast <cgraph_node *> (ref->referring);
+      if ((alias->callers && alias->callers != e)
+          || !can_remove_node_now_p_1 (alias, e))
+       return false;
+    }
   /* FIXME: When address is taken of DECL_EXTERNAL function we still
      can remove its offline copy, but we would need to keep unanalyzed node in
      the callgraph so references can point to it.  */
   return (!node->address_taken
-         && !node->has_aliases_p ()
          && node->can_remove_if_no_direct_calls_p ()
          /* Inlining might enable more devirtualizing, so we want to remove
             those only after all devirtualizable virtual calls are processed.
             Lacking may edges in callgraph we just preserve them post
             inlining.  */
-         && !DECL_VIRTUAL_P (node->decl)
+         && (!DECL_VIRTUAL_P (node->decl)
+             || !opt_for_fn (node->decl, flag_devirtualize))
          /* During early inlining some unanalyzed cgraph nodes might be in the
             callgraph and they might reffer the function in question.  */
          && !cgraph_new_nodes.exists ());
@@ -119,7 +128,7 @@ static bool
 can_remove_node_now_p (struct cgraph_node *node, struct cgraph_edge *e)
 {
   struct cgraph_node *next;
-  if (!can_remove_node_now_p_1 (node))
+  if (!can_remove_node_now_p_1 (node, e))
     return false;
 
   /* When we see same comdat group, we need to be sure that all
@@ -128,9 +137,13 @@ can_remove_node_now_p (struct cgraph_nod
     return true;
   for (next = dyn_cast<cgraph_node *> (node->same_comdat_group);
        next != node; next = dyn_cast<cgraph_node *> (next->same_comdat_group))
-    if ((next->callers && next->callers != e)
-       || !can_remove_node_now_p_1 (next))
-      return false;
+    {
+      if (next->alias)
+       continue;
+      if ((next->callers && next->callers != e)
+         || !can_remove_node_now_p_1 (next, e))
+        return false;
+    }
   return true;
 }
 

Reply via email to