]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/ipa-comdats.c
2019-01-09 Sandra Loosemore <sandra@codesourcery.com>
[thirdparty/gcc.git] / gcc / ipa-comdats.c
index b1bc35e9392c859f31b13066df4e93c1f225630f..69cc3f3b907f1e51e8a1272480042fb0c06aa912 100644 (file)
@@ -1,5 +1,5 @@
 /* Localize comdats.
-   Copyright (C) 2014 Free Software Foundation, Inc.
+   Copyright (C) 2014-2019 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -53,9 +53,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "tm.h"
 #include "tree.h"
-#include "cgraph.h"
 #include "tree-pass.h"
-#include "hash-map.h"
+#include "cgraph.h"
 
 /* Main dataflow loop propagating comdat groups across
    the symbol table.  All references to SYMBOL are examined
@@ -72,7 +71,7 @@ propagate_comdat_group (struct symtab_node *symbol,
   /* Walk all references to SYMBOL, recursively dive into aliases.  */
 
   for (i = 0;
-       ipa_ref_list_referring_iterate (&symbol->ref_list, i, ref)
+       symbol->iterate_referring (i, ref)
        && newgroup != error_mark_node; i++)
     {
       struct symtab_node *symbol2 = ref->referring;
@@ -83,7 +82,7 @@ propagate_comdat_group (struct symtab_node *symbol,
          continue;
        }
 
-      /* One COMDAT group can not hold both variables and functions at
+      /* One COMDAT group cannot hold both variables and functions at
         a same time.  For now we just go to BOTTOM, in future we may
         invent special comdat groups for this case.  */
 
@@ -126,12 +125,14 @@ propagate_comdat_group (struct symtab_node *symbol,
       {
        struct symtab_node *symbol2 = edge->caller;
 
-       /* If we see inline clone, its comdat group actually
-          corresponds to the comdat group of the function it is inlined
-          to.  */
-
        if (cgraph_node * cn = dyn_cast <cgraph_node *> (symbol2))
          {
+           /* Thunks cannot call across section boundary.  */
+           if (cn->thunk.thunk_p)
+             newgroup = propagate_comdat_group (symbol2, newgroup, map);
+           /* If we see inline clone, its comdat group actually
+              corresponds to the comdat group of the function it
+              is inlined to.  */
            if (cn->global.inlined_to)
              symbol2 = cn->global.inlined_to;
          }
@@ -161,11 +162,15 @@ enqueue_references (symtab_node **first,
                    symtab_node *symbol)
 {
   int i;
-  struct ipa_ref *ref;
+  struct ipa_ref *ref = NULL;
 
-  for (i = 0; ipa_ref_list_reference_iterate (&symbol->ref_list, i, ref); i++)
+  for (i = 0; symbol->iterate_reference (i, ref); i++)
     {
-      symtab_node *node = symtab_alias_ultimate_target (ref->referred, NULL);
+      symtab_node *node = ref->referred->ultimate_alias_target ();
+
+      /* Always keep thunks in same sections as target function.  */
+      if (is_a <cgraph_node *>(node))
+       node = dyn_cast <cgraph_node *> (node)->function_symbol ();
       if (!node->aux && node->definition)
        {
           node->aux = *first;
@@ -182,8 +187,11 @@ enqueue_references (symtab_node **first,
          enqueue_references (first, edge->callee);
        else
          {
-           symtab_node *node = symtab_alias_ultimate_target (edge->callee,
-                                                             NULL);
+           symtab_node *node = edge->callee->ultimate_alias_target ();
+
+           /* Always keep thunks in same sections as target function.  */
+           if (is_a <cgraph_node *>(node))
+             node = dyn_cast <cgraph_node *> (node)->function_symbol ();
            if (!node->aux && node->definition)
              {
                 node->aux = *first;
@@ -194,7 +202,7 @@ enqueue_references (symtab_node **first,
 }
 
 /* Set comdat group of SYMBOL to GROUP.
-   Callback for symtab_for_node_and_aliases.  */
+   Callback for for_node_and_aliases.  */
 
 bool
 set_comdat_group (symtab_node *symbol,
@@ -203,11 +211,24 @@ set_comdat_group (symtab_node *symbol,
   symtab_node *head = (symtab_node *)head_p;
 
   gcc_assert (!symbol->get_comdat_group ());
-  symbol->set_comdat_group (head->get_comdat_group ());
-  symtab_add_to_same_comdat_group (symbol, head);
+  if (symbol->real_symbol_p ())
+    {
+      symbol->set_comdat_group (head->get_comdat_group ());
+      symbol->add_to_same_comdat_group (head);
+    }
   return false;
 }
 
+/* Set comdat group of SYMBOL to GROUP.
+   Callback for for_node_thunks_and_aliases.  */
+
+bool
+set_comdat_group_1 (cgraph_node *symbol,
+                   void *head_p)
+{
+  return set_comdat_group (symbol, head_p);
+}
+
 /* The actual pass with the main dataflow loop.  */
 
 static unsigned int
@@ -225,7 +246,7 @@ ipa_comdats (void)
      ERROR_MARK_NODE as bottom for the propagation.  */
 
   FOR_EACH_DEFINED_SYMBOL (symbol)
-    if (!symtab_real_symbol_p (symbol))
+    if (!symbol->real_symbol_p ())
       ;
     else if ((group = symbol->get_comdat_group ()) != NULL)
       {
@@ -236,7 +257,7 @@ ipa_comdats (void)
        /* Mark the symbol so we won't waste time visiting it for dataflow.  */
        symbol->aux = (symtab_node *) (void *) 1;
       }
-    /* See symbols that can not be privatized to comdats; that is externally
+    /* See symbols that cannot be privatized to comdats; that is externally
        visible symbols or otherwise used ones.  We also do not want to mangle
        user section names.  */
     else if (symbol->externally_visible
@@ -248,7 +269,12 @@ ipa_comdats (void)
                 && (DECL_STATIC_CONSTRUCTOR (symbol->decl)
                     || DECL_STATIC_DESTRUCTOR (symbol->decl))))
       {
-       map.put (symtab_alias_ultimate_target (symbol, NULL), error_mark_node);
+       symtab_node *target = symbol->ultimate_alias_target ();
+
+       /* Always keep thunks in same sections as target function.  */
+       if (is_a <cgraph_node *>(target))
+         target = dyn_cast <cgraph_node *> (target)->function_symbol ();
+       map.put (target, error_mark_node);
 
        /* Mark the symbol so we won't waste time visiting it for dataflow.  */
        symbol->aux = (symtab_node *) (void *) 1;
@@ -313,23 +339,41 @@ ipa_comdats (void)
 
   FOR_EACH_DEFINED_SYMBOL (symbol)
     {
+      struct cgraph_node *fun;
       symbol->aux = NULL; 
       if (!symbol->get_comdat_group ()
          && !symbol->alias
-         && symtab_real_symbol_p (symbol))
+         && (!(fun = dyn_cast <cgraph_node *> (symbol))
+             || !fun->thunk.thunk_p)
+         && symbol->real_symbol_p ())
        {
-         tree group = *map.get (symbol);
+         tree *val = map.get (symbol);
+
+         /* A NULL here means that SYMBOL is unreachable in the definition
+            of ipa-comdats. Either ipa-comdats is wrong about this or someone
+            forgot to cleanup and remove unreachable functions earlier.  */
+         gcc_assert (val);
+
+         tree group = *val;
 
          if (group == error_mark_node)
            continue;
          if (dump_file)
            {
              fprintf (dump_file, "Localizing symbol\n");
-             dump_symtab_node (dump_file, symbol);
+             symbol->dump (dump_file);
              fprintf (dump_file, "To group: %s\n", IDENTIFIER_POINTER (group));
            }
-         symtab_for_node_and_aliases (symbol, set_comdat_group,
-                                      *comdat_head_map.get (group), true);
+         if (is_a <cgraph_node *> (symbol))
+          dyn_cast <cgraph_node *>(symbol)->call_for_symbol_thunks_and_aliases
+                 (set_comdat_group_1,
+                  *comdat_head_map.get (group),
+                  true);
+         else
+          symbol->call_for_symbol_and_aliases
+                 (set_comdat_group,
+                  *comdat_head_map.get (group),
+                  true);
        }
     }
   return 0;
@@ -342,7 +386,6 @@ const pass_data pass_data_ipa_comdats =
   IPA_PASS, /* type */
   "comdats", /* name */
   OPTGROUP_NONE, /* optinfo_flags */
-  true, /* has_execute */
   TV_IPA_COMDATS, /* tv_id */
   0, /* properties_required */
   0, /* properties_provided */
@@ -376,7 +419,7 @@ public:
 bool
 pass_ipa_comdats::gate (function *)
 {
-  return optimize;
+  return HAVE_COMDAT_GROUP;
 }
 
 } // anon namespace