ipa-icf.c (sem_function::merge): Fix handling of COMDAT.
authorJan Hubicka <hubicka@ucw.cz>
Sun, 1 Mar 2015 01:09:25 +0000 (02:09 +0100)
committerJan Hubicka <hubicka@gcc.gnu.org>
Sun, 1 Mar 2015 01:09:25 +0000 (01:09 +0000)
* ipa-icf.c (sem_function::merge): Fix handling of COMDAT.
(sem_variable::merge) Likewise.

From-SVN: r221085

gcc/ChangeLog
gcc/ipa-icf.c

index ee6f7fe7fd9a8e5983c9fcd144621b3525145b0a..1b4b17dea95477a51f1263f738479ccc76cddb6c 100644 (file)
@@ -1,3 +1,8 @@
+2015-02-28  Jan Hubicka  <hubicka@ucw.cz>
+
+       * ipa-icf.c (sem_function::merge): Fix handling of COMDAT.
+       (sem_variable::merge) Likewise.
+
 2015-02-28  Jan Hubicka  <hubicka@ucw.cz>
 
        * ipa-inline.c (can_inline_edge_p): Match opt_for_fn on inline
index 6db5c084ad519e37975415a16700cb1771314237..70a2883d412b3b7cfde696188696059b27ba61a5 100644 (file)
@@ -733,6 +733,7 @@ sem_function::merge (sem_item *alias_item)
   bool remove = false;
 
   bool original_discardable = false;
+  bool original_discarded = false;
 
   bool original_address_matters = original->address_matters_p ();
   bool alias_address_matters = alias->address_matters_p ();
@@ -761,15 +762,16 @@ sem_function::merge (sem_item *alias_item)
     }
 
   /* See if original is in a section that can be discarded if the main
-     symbol is not used.
+     symbol is not used.  */
 
-     Also consider case where we have resolution info and we know that
+  if (original->can_be_discarded_p ())
+    original_discardable = true;
+  /* Also consider case where we have resolution info and we know that
      original's definition is not going to be used.  In this case we can not
      create alias to original.  */
-  if (original->can_be_discarded_p ()
-      || (node->resolution != LDPR_UNKNOWN
-         && !decl_binds_to_current_def_p (node->decl)))
-    original_discardable = true;
+  if (node->resolution != LDPR_UNKNOWN
+      && !decl_binds_to_current_def_p (node->decl))
+    original_discardable = original_discarded = true;
 
   /* Creating a symtab alias is the optimal way to merge.
      It however can not be used in the following cases:
@@ -788,6 +790,7 @@ sem_function::merge (sem_item *alias_item)
          && (!DECL_COMDAT_GROUP (alias->decl)
              || (DECL_COMDAT_GROUP (alias->decl)
                  != DECL_COMDAT_GROUP (original->decl))))
+      || original_discarded
       || !sem_item::target_supports_symbol_aliases_p ()
       || DECL_COMDAT_GROUP (alias->decl) != DECL_COMDAT_GROUP (original->decl))
     {
@@ -797,7 +800,7 @@ sem_function::merge (sem_item *alias_item)
         comdat group. Other compiler producing the body of the
         another comdat group may make opossite decision and with unfortunate
         linker choices this may close a loop.  */
-      if (DECL_COMDAT_GROUP (alias->decl)
+      if (DECL_COMDAT_GROUP (original->decl) && DECL_COMDAT_GROUP (alias->decl)
          && (DECL_COMDAT_GROUP (alias->decl)
              != DECL_COMDAT_GROUP (original->decl)))
        {
@@ -854,26 +857,27 @@ sem_function::merge (sem_item *alias_item)
 
       /* Work out the symbol the wrapper should call.
         If ORIGINAL is interposable, we need to call a local alias.
-        Also produce local alias (if possible) as an optimization.  */
-      if (!original_discardable
-         || (DECL_COMDAT_GROUP (original->decl)
-             && (DECL_COMDAT_GROUP (original->decl)
-                 == DECL_COMDAT_GROUP (alias->decl))))
+        Also produce local alias (if possible) as an optimization.
+
+        Local aliases can not be created inside comdat groups because that
+        prevents inlining.  */
+      if (!original_discardable && !original->get_comdat_group ())
        {
          local_original
            = dyn_cast <cgraph_node *> (original->noninterposable_alias ());
          if (!local_original
              && original->get_availability () > AVAIL_INTERPOSABLE)
            local_original = original;
-         /* If original is COMDAT local, we can not really redirect external
-            callers to it.  */
-         if (original->comdat_local_p ())
-           redirect_callers = false;
        }
       /* If we can not use local alias, fallback to the original
         when possible.  */
       else if (original->get_availability () > AVAIL_INTERPOSABLE)
        local_original = original;
+
+      /* If original is COMDAT local, we can not really redirect calls outside
+        of its comdat group to it.  */
+      if (original->comdat_local_p ())
+        redirect_callers = false;
       if (!local_original)
        {
          if (dump_file)
@@ -1545,11 +1549,16 @@ sem_variable::merge (sem_item *alias_item)
                 "adress of original and alias may be compared.\n\n");
       return false;
     }
+  if (DECL_COMDAT_GROUP (original->decl) != DECL_COMDAT_GROUP (alias->decl))
+    {
+      if (dump_file)
+       fprintf (dump_file, "Not unifying; alias cannot be created; "
+                "across comdat group boundary\n\n");
+
+      return false;
+    }
 
-  if (original_discardable
-      && (!DECL_COMDAT_GROUP (original->decl)
-         || (DECL_COMDAT_GROUP (original->decl)
-             != DECL_COMDAT_GROUP (alias->decl))))
+  if (original_discardable)
     {
       if (dump_file)
        fprintf (dump_file, "Not unifying; alias cannot be created; "