re PR ipa/65245 (internal compiler error: in address_matters_p, at symtab.c:1908)
authorMartin Liska <mliska@suse.cz>
Sun, 1 Mar 2015 20:23:21 +0000 (21:23 +0100)
committerJan Hubicka <hubicka@gcc.gnu.org>
Sun, 1 Mar 2015 20:23:21 +0000 (20:23 +0000)
2015-02-28  Martin Liska  <mliska@suse.cz>
    Jan Hubicka   <hubicka@ucw.cz>

PR ipa/65245
* ipa-icf-gimple.c (func_checker::compare_function_decl):
Remove.
(func_checker::compare_variable_decl): Skip symtab vars.
(func_checker::compare_cst_or_decl): Update.
* ipa-icf.c (sem_function::parse): Do not consider aliases.
(sem_function::compare_cgraph_references): Add ADDRESS parameter;
use correct symtab predicates.
(sem_function::equals_wpa): Update uses of compare_cgraph_references.
(sem_variable::parse):  Update comment.
(sem_item_optimizer::build_graph): Consider ultimate aliases
for references.

* gcc.dg/ipa/ipa-icf-34.c: New test.

Co-Authored-By: Jan Hubicka <hubicka@ucw.cz>
From-SVN: r221090

gcc/ChangeLog
gcc/ipa-icf-gimple.c
gcc/ipa-icf.c
gcc/ipa-icf.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/ipa/ipa-icf-34.c [new file with mode: 0644]

index b47008e9750aa00afacec123e438d08660a75957..ef9292f0f81a7064461de4e015bf6e64b711e39a 100644 (file)
@@ -1,3 +1,19 @@
+2015-02-28  Martin Liska  <mliska@suse.cz>
+           Jan Hubicka   <hubicka@ucw.cz>
+
+       PR ipa/65245
+       * ipa-icf-gimple.c (func_checker::compare_function_decl):
+       Remove.
+       (func_checker::compare_variable_decl): Skip symtab vars.
+       (func_checker::compare_cst_or_decl): Update.
+       * ipa-icf.c (sem_function::parse): Do not consider aliases.
+       (sem_function::compare_cgraph_references): Add ADDRESS parameter;
+       use correct symtab predicates.
+       (sem_function::equals_wpa): Update uses of compare_cgraph_references.
+       (sem_variable::parse):  Update comment.
+       (sem_item_optimizer::build_graph): Consider ultimate aliases
+       for references.
+
 2015-02-28  Jan Hubicka  <hubicka@ucw.cz>
 
        * ipa-icf-gimple.c (func_checker::compare_operand): Fix handling
index 18631730b69cbe4540a7de746bdd24c35b11e263..7cc58d461e2905bbd123317716c703a7fb305610 100644 (file)
@@ -312,10 +312,9 @@ func_checker::compare_cst_or_decl (tree t1, tree t2)
        return return_with_debug (ret);
       }
     case FUNCTION_DECL:
-      {
-       ret = compare_function_decl (t1, t2);
-       return return_with_debug (ret);
-      }
+      /* All function decls are in the symbol table and known to match
+        before we start comparing bodies.  */
+      return true;
     case VAR_DECL:
       return return_with_debug (compare_variable_decl (t1, t2));
     case FIELD_DECL:
@@ -537,39 +536,6 @@ func_checker::compare_tree_list_operand (tree t1, tree t2)
   return true;
 }
 
-/* Verifies that trees T1 and T2, representing function declarations
-   are equivalent from perspective of ICF.  */
-
-bool
-func_checker::compare_function_decl (tree t1, tree t2)
-{
-  bool ret = false;
-
-  if (t1 == t2)
-    return true;
-
-  symtab_node *n1 = symtab_node::get (t1);
-  symtab_node *n2 = symtab_node::get (t2);
-
-  if (m_ignored_source_nodes != NULL && m_ignored_target_nodes != NULL)
-    {
-      ret = m_ignored_source_nodes->contains (n1)
-           && m_ignored_target_nodes->contains (n2);
-
-      if (ret)
-       return true;
-    }
-
-  /* If function decl is WEAKREF, we compare targets.  */
-  cgraph_node *f1 = cgraph_node::get (t1);
-  cgraph_node *f2 = cgraph_node::get (t2);
-
-  if(f1 && f2 && f1->weakref && f2->weakref)
-    ret = f1->alias_target == f2->alias_target;
-
-  return ret;
-}
-
 /* Verifies that trees T1 and T2 do correspond.  */
 
 bool
@@ -590,20 +556,10 @@ func_checker::compare_variable_decl (tree t1, tree t2)
       && DECL_ASSEMBLER_NAME (t1) != DECL_ASSEMBLER_NAME (t2))
     return return_false_with_msg ("HARD REGISTERS are different");
 
-  if (TREE_CODE (t1) == VAR_DECL && (DECL_EXTERNAL (t1) || TREE_STATIC (t1)))
-    {
-      symtab_node *n1 = symtab_node::get (t1);
-      symtab_node *n2 = symtab_node::get (t2);
-
-      if (m_ignored_source_nodes != NULL && m_ignored_target_nodes != NULL)
-       {
-         ret = m_ignored_source_nodes->contains (n1)
-               && m_ignored_target_nodes->contains (n2);
-
-         if (ret)
-           return true;
-       }
-    }
+  /* Symbol table variables are known to match before we start comparing
+     bodies.  */
+  if (decl_in_symtab_p (t1))
+    return decl_in_symtab_p (t2);
   ret = compare_decl (t1, t2);
 
   return return_with_debug (ret);
index 70a2883d412b3b7cfde696188696059b27ba61a5..0de69a83fb5a4d78f0c68aeacb53ca709096e72c 100644 (file)
@@ -335,17 +335,26 @@ sem_function::get_hash (void)
 
 /* For a given symbol table nodes N1 and N2, we check that FUNCTION_DECLs
    point to a same function. Comparison can be skipped if IGNORED_NODES
-   contains these nodes.  */
+   contains these nodes.  ADDRESS indicate if address is taken.  */
 
 bool
-sem_function::compare_cgraph_references (hash_map <symtab_node *, sem_item *>
-    &ignored_nodes,
-    symtab_node *n1, symtab_node *n2)
+sem_function::compare_cgraph_references (
+    hash_map <symtab_node *, sem_item *> &ignored_nodes,
+    symtab_node *n1, symtab_node *n2, bool address)
 {
-  if (n1 == n2 || (ignored_nodes.get (n1) && ignored_nodes.get (n2)))
+  enum availability avail1, avail2;
+
+  if (address && n1->equal_address_to (n2) == 1)
+    return true;
+  if (!address && n1->semantically_equivalent_p (n2))
     return true;
 
-  /* TODO: add more precise comparison for weakrefs, etc.  */
+  n1 = n1->ultimate_alias_target (&avail1);
+  n2 = n2->ultimate_alias_target (&avail2);
+
+  if (avail1 >= AVAIL_INTERPOSABLE && ignored_nodes.get (n1)
+      && avail2 >= AVAIL_INTERPOSABLE && ignored_nodes.get (n2))
+    return true;
 
   return return_false_with_msg ("different references");
 }
@@ -412,7 +421,9 @@ sem_function::equals_wpa (sem_item *item,
     {
       item->node->iterate_reference (i, ref2);
 
-      if (!compare_cgraph_references (ignored_nodes, ref->referred, ref2->referred))
+      if (!compare_cgraph_references (ignored_nodes, ref->referred,
+                                     ref2->referred,
+                                     ref->address_matters_p ()))
        return false;
     }
 
@@ -421,7 +432,8 @@ sem_function::equals_wpa (sem_item *item,
 
   while (e1 && e2)
     {
-      if (!compare_cgraph_references (ignored_nodes, e1->callee, e2->callee))
+      if (!compare_cgraph_references (ignored_nodes, e1->callee,
+                                     e2->callee, false))
        return false;
 
       e1 = e1->next_callee;
@@ -1117,7 +1129,7 @@ sem_function::parse (cgraph_node *node, bitmap_obstack *stack)
   tree fndecl = node->decl;
   function *func = DECL_STRUCT_FUNCTION (fndecl);
 
-  /* TODO: add support for thunks and aliases.  */
+  /* TODO: add support for thunks.  */
 
   if (!func || !node->has_gimple_body_p ())
     return NULL;
@@ -1429,6 +1441,9 @@ sem_variable::parse (varpool_node *node, bitmap_obstack *stack)
 {
   tree decl = node->decl;
 
+  if (node->alias)
+    return NULL;
+
   bool readonly = TYPE_P (decl) ? TYPE_READONLY (decl) : TREE_READONLY (decl);
   if (!readonly)
     return NULL;
@@ -2086,7 +2101,8 @@ sem_item_optimizer::build_graph (void)
          cgraph_edge *e = cnode->callees;
          while (e)
            {
-             sem_item **slot = m_symtab_node_map.get (e->callee);
+             sem_item **slot = m_symtab_node_map.get
+               (e->callee->ultimate_alias_target ());
              if (slot)
                item->add_reference (*slot);
 
@@ -2097,7 +2113,8 @@ sem_item_optimizer::build_graph (void)
       ipa_ref *ref = NULL;
       for (unsigned i = 0; item->node->iterate_reference (i, ref); i++)
        {
-         sem_item **slot = m_symtab_node_map.get (ref->referred);
+         sem_item **slot = m_symtab_node_map.get
+           (ref->referred->ultimate_alias_target ());
          if (slot)
            item->add_reference (*slot);
        }
index 077267ce087ffebc1fe35be8846013674bec8888..bf01cf09f213a967a15318fece3cc8cc157ce05d 100644 (file)
@@ -353,10 +353,11 @@ private:
 
   /* For a given symbol table nodes N1 and N2, we check that FUNCTION_DECLs
      point to a same function. Comparison can be skipped if IGNORED_NODES
-     contains these nodes.  */
+     contains these nodes.  ADDRESS indicate if address is taken.  */
   bool compare_cgraph_references (hash_map <symtab_node *, sem_item *>
                                  &ignored_nodes,
-                                 symtab_node *n1, symtab_node *n2);
+                                 symtab_node *n1, symtab_node *n2,
+                                 bool address);
 
   /* Processes function equality comparison.  */
   bool equals_private (sem_item *item,
index d8f5180059c1433cf85ff1434f9ad3b02b17a2e1..e397689d287c731c36dbe7b97b4c8b400524b555 100644 (file)
@@ -1,3 +1,9 @@
+2015-02-28  Martin Liska  <mliska@suse.cz>
+           Jan Hubicka   <hubicka@ucw.cz>
+
+       PR ipa/65245
+       * gcc.dg/ipa/ipa-icf-34.c: New test.
+
 2015-03-01  Oleg Endo  <olegendo@gcc.gnu.org>
 
        PR target/61142
diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-icf-34.c b/gcc/testsuite/gcc.dg/ipa/ipa-icf-34.c
new file mode 100644 (file)
index 0000000..698044a
--- /dev/null
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-O0 -fipa-icf -fdump-ipa-icf"  } */
+
+static int do_work(void)
+{
+  return 0;
+}
+
+static int foo() __attribute__((alias("do_work")));
+static int bar() __attribute__((alias("do_work")));
+
+static int a()
+{
+  return foo();
+}
+
+static int b()
+{
+  return bar();
+}
+
+int main()
+{
+  return a() + b();
+}
+
+/* { dg-final { scan-ipa-dump "Equal symbols: 1" "icf"  } } */
+/* { dg-final { cleanup-ipa-dump "icf" } } */