OSDN Git Service

* decl2.c (maybe_emit_vtables): Produce same comdat group when outputting
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 22 May 2010 14:48:40 +0000 (14:48 +0000)
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 22 May 2010 14:48:40 +0000 (14:48 +0000)
comdat vtables.
(cxx_callgraph_analyze_expr): Remove code marking vtables needed.

* cgraph.h (struct varpool_node): Add same_comdat_group.
* lto-cgrpah.c (lto_output_varpool_node): Output same_comdat_group
pointer.
(output_varpool): Update call of lto_output_varpool_node.
(input_varpool): Read same_comdat_group pointer.
(input_varpool_1): Fixup same_comdat_group pointer.
* ipa.c (cgraph_remove_unreachable_nodes): WHen one of same comdat
group is needed, all are.
* varpool.c (varpool_remove_node): Remove node from same comdat group
linklist too.
(varpool_analyze_pending_decls): Walk same comdat groups.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@159699 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/cgraph.h
gcc/cp/ChangeLog
gcc/cp/decl2.c
gcc/ipa.c
gcc/lto-cgraph.c
gcc/varpool.c

index b924627..e7f0f71 100644 (file)
@@ -1,3 +1,17 @@
+2010-05-22  Jan Hubicka  <jh@suse.cz>
+
+       * cgraph.h (struct varpool_node): Add same_comdat_group.
+       * lto-cgrpah.c (lto_output_varpool_node): Output same_comdat_group
+       pointer.
+       (output_varpool): Update call of lto_output_varpool_node.
+       (input_varpool): Read same_comdat_group pointer.
+       (input_varpool_1): Fixup same_comdat_group pointer.
+       * ipa.c (cgraph_remove_unreachable_nodes): WHen one of same comdat
+       group is needed, all are.
+       * varpool.c (varpool_remove_node): Remove node from same comdat group
+       linklist too.
+       (varpool_analyze_pending_decls): Walk same comdat groups.
+
 2010-05-22  Steven Bosscher  <steven@gcc.gnu.org>
 
        * rtl.h (union rtunion_def): Remove rt_bit member.
index b092301..a9a2962 100644 (file)
@@ -457,6 +457,8 @@ struct GTY((chain_next ("%h.next"), chain_prev ("%h.prev"))) varpool_node {
   /* For normal nodes a pointer to the first extra name alias.  For alias
      nodes a pointer to the normal node.  */
   struct varpool_node *extra_name;
+  /* Circular list of nodes in the same comdat group if non-NULL.  */
+  struct varpool_node *same_comdat_group;
   struct ipa_ref_list ref_list;
   PTR GTY ((skip)) aux;
   /* Ordering of all cgraph nodes.  */
index 5275eca..47f5308 100644 (file)
@@ -1,3 +1,9 @@
+2010-05-22  Jan Hubicka  <jh@suse.cz>
+
+       * decl2.c (maybe_emit_vtables): Produce same comdat group when outputting
+       comdat vtables.
+       (cxx_callgraph_analyze_expr): Remove code marking vtables needed.
+
 2010-05-21  Joseph Myers  <joseph@codesourcery.com>
 
        * cxx-pretty-print.c: Correct merge error.
index 25c1175..2fd6305 100644 (file)
@@ -1808,6 +1808,7 @@ maybe_emit_vtables (tree ctype)
   tree vtbl;
   tree primary_vtbl;
   int needed = 0;
+  struct varpool_node *current = NULL, *last = NULL, *first = NULL;
 
   /* If the vtables for this class have already been emitted there is
      nothing more to do.  */
@@ -1865,8 +1866,20 @@ maybe_emit_vtables (tree ctype)
         actually marking the variable as written.  */
       if (flag_syntax_only)
        TREE_ASM_WRITTEN (vtbl) = 1;
+      else if (DECL_COMDAT (vtbl))
+       {
+         current = varpool_node (vtbl);
+         if (last)
+           last->same_comdat_group = current;
+         last = current;
+         if (!first)
+           first = current;
+       }
     }
 
+  if (first != last)
+    last->same_comdat_group = first;
+
   /* Since we're writing out the vtable here, also write the debug
      info.  */
   note_debug_info_needed (ctype);
@@ -3358,19 +3371,9 @@ cxx_callgraph_analyze_expr (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED)
        cgraph_mark_address_taken_node (cgraph_node (BASELINK_FUNCTIONS (t)));
       break;
     case VAR_DECL:
-      if (DECL_VTABLE_OR_VTT_P (t))
-       {
-         /* The ABI requires that all virtual tables be emitted
-            whenever one of them is.  */
-         tree vtbl;
-         for (vtbl = CLASSTYPE_VTABLES (DECL_CONTEXT (t));
-              vtbl;
-              vtbl = TREE_CHAIN (vtbl))
-           mark_decl_referenced (vtbl);
-       }
-      else if (DECL_CONTEXT (t)
-              && flag_use_repository
-              && TREE_CODE (DECL_CONTEXT (t)) == FUNCTION_DECL)
+      if (DECL_CONTEXT (t)
+         && flag_use_repository
+         && TREE_CODE (DECL_CONTEXT (t)) == FUNCTION_DECL)
        /* If we need a static variable in a function, then we
           need the containing function.  */
        mark_decl_referenced (DECL_CONTEXT (t));
index c8b0d7b..319a3f1 100644 (file)
--- a/gcc/ipa.c
+++ b/gcc/ipa.c
@@ -334,6 +334,21 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
          first_varpool = (struct varpool_node *)first_varpool->aux;
          vnode->aux = NULL;
          process_references (&vnode->ref_list, &first, &first_varpool, before_inlining_p);
+         /* If any function in a comdat group is reachable, force
+            all other functions in the same comdat group to be
+            also reachable.  */
+         if (vnode->same_comdat_group)
+           {
+             struct varpool_node *next;
+             for (next = vnode->same_comdat_group;
+                  next != vnode;
+                  next = next->same_comdat_group)
+               if (!next->needed)
+                 {
+                   varpool_mark_needed_node (next);
+                   enqueue_varpool_node (next, &first_varpool);
+                 }
+           }
        }
     }
 
index 8b0f8e1..f911c3a 100644 (file)
@@ -565,12 +565,14 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
 
 static void
 lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node *node,
+                        lto_varpool_encoder_t varpool_encoder,
                         cgraph_node_set set, varpool_node_set vset)
 {
   bool boundary_p = !varpool_node_in_set_p (node, vset) && node->analyzed;
   struct bitpack_d *bp;
   struct varpool_node *alias;
   int count = 0;
+  int ref;
 
   lto_output_var_decl_index (ob->decl_state, ob->main_stream, node->decl);
   bp = bitpack_create ();
@@ -602,6 +604,14 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node
   bp_pack_value (bp, count != 0, 1);
   lto_output_bitpack (ob->main_stream, bp);
   bitpack_delete (bp);
+  if (node->same_comdat_group && !boundary_p)
+    {
+      ref = lto_varpool_encoder_lookup (varpool_encoder, node->same_comdat_group);
+      gcc_assert (ref != LCC_NOT_FOUND);
+    }
+  else
+    ref = LCC_NOT_FOUND;
+  lto_output_sleb128_stream (ob->main_stream, ref);
 
   if (count)
     {
@@ -961,6 +971,7 @@ output_varpool (cgraph_node_set set, varpool_node_set vset)
   for (i = 0; i < len; i++)
     {
       lto_output_varpool_node (ob, lto_varpool_encoder_deref (varpool_encoder, i),
+                              varpool_encoder,
                               set, vset);
     }
 
@@ -1081,6 +1092,7 @@ input_varpool_node (struct lto_file_decl_data *file_data,
   struct bitpack_d *bp;
   bool aliases_p;
   int count;
+  int ref = LCC_NOT_FOUND;
 
   decl_index = lto_input_uleb128 (ib);
   var_decl = lto_file_decl_data_get_var_decl (file_data, decl_index);
@@ -1098,6 +1110,9 @@ input_varpool_node (struct lto_file_decl_data *file_data,
   if (node->finalized)
     varpool_mark_needed_node (node);
   bitpack_delete (bp);
+  ref = lto_input_sleb128 (ib);
+  /* Store a reference for now, and fix up later to be a pointer.  */
+  node->same_comdat_group = (struct varpool_node *) (intptr_t) ref;
   if (aliases_p)
     {
       count = lto_input_uleb128 (ib);
@@ -1291,6 +1306,8 @@ input_varpool_1 (struct lto_file_decl_data *file_data,
 {
   unsigned HOST_WIDE_INT len;
   VEC(varpool_node_ptr, heap) *varpool = NULL;
+  int i;
+  struct varpool_node *node;
 
   len = lto_input_uleb128 (ib);
   while (len)
@@ -1299,6 +1316,16 @@ input_varpool_1 (struct lto_file_decl_data *file_data,
                     input_varpool_node (file_data, ib));
       len--;
     }
+  for (i = 0; VEC_iterate (varpool_node_ptr, varpool, i, node); i++)
+    {
+      int ref = (int) (intptr_t) node->same_comdat_group;
+
+      /* Fixup same_comdat_group from reference to pointer.  */
+      if (ref != LCC_NOT_FOUND)
+       node->same_comdat_group = VEC_index (varpool_node_ptr, varpool, ref);
+      else
+       node->same_comdat_group = NULL;
+    }
   return varpool;
 }
 
index 7185c85..73d39f3 100644 (file)
@@ -194,6 +194,19 @@ varpool_remove_node (struct varpool_node *node)
       gcc_assert (varpool_nodes_queue == node);
       varpool_nodes_queue = node->next_needed;
     }
+  if (node->same_comdat_group)
+    {
+      struct varpool_node *prev;
+      for (prev = node->same_comdat_group;
+          prev->same_comdat_group != node;
+          prev = prev->same_comdat_group)
+       ;
+      if (node->same_comdat_group == prev)
+       prev->same_comdat_group = NULL;
+      else
+       prev->same_comdat_group = node->same_comdat_group;
+      node->same_comdat_group = NULL;
+    }
   ipa_remove_all_references (&node->ref_list);
   ipa_remove_all_refering (&node->ref_list);
   ggc_free (node);
@@ -416,8 +429,9 @@ varpool_analyze_pending_decls (void)
   timevar_push (TV_VARPOOL);
   while (varpool_first_unanalyzed_node)
     {
-      tree decl = varpool_first_unanalyzed_node->decl;
-      bool analyzed = varpool_first_unanalyzed_node->analyzed;
+      struct varpool_node *node = varpool_first_unanalyzed_node, *next;
+      tree decl = node->decl;
+      bool analyzed = node->analyzed;
 
       varpool_first_unanalyzed_node->analyzed = true;
 
@@ -435,6 +449,13 @@ varpool_analyze_pending_decls (void)
        }
       if (DECL_INITIAL (decl))
        record_references_in_initializer (decl, analyzed);
+      if (node->same_comdat_group)
+       {
+         for (next = node->same_comdat_group;
+              next != node;
+              next = next->same_comdat_group)
+           varpool_mark_needed_node (next);
+       }
       changed = true;
     }
   timevar_pop (TV_VARPOOL);