]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
* lto-symtab.c (lto_symtab_resolve_symbols): Preffer decl with constructor
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 17 May 2012 16:37:33 +0000 (16:37 +0000)
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 17 May 2012 16:37:33 +0000 (16:37 +0000)
over decl without.
* cgraph.c (cgraph_remove_node): Clear also body of unanalyzed nodes.
* cgraph.h (varpool_can_remove_if_no_refs): Handle external correctly.
* cgraphunit.c (process_function_and_variable_attributes): Finalize
extrnal decls.
(mark_functions_to_output): Also accept bodies for functions with clones.
(output_in_order): Skip external vars.
* lto-cgraph.c (lto_output_node): External functions are never in other
partition.
(lto_output_varpool_node): Likewise.
* lto-streamer-out.c (lto_write_tree): Always use error_mark_nodes for
forgotten initializers.
* ipa.c (process_references): Handle external vars.
(symtab_remove_unreachable_nodes): Update to handle external vars.
(varpool_externally_visible_p): External vars are externally visible.
* gimple-fold.c (can_refer_decl_in_current_unit_p): Update.
* varpool.c (varpool_remove_node): Remove constructor.
(decide_is_variable_needed): Handle externals.
(varpool_remove_unreferenced_decls): Likewise.

* lto-partition.c (add_references_to_partition): Handle external vars.
(partition_varpool_node_p): Likewise.
(lto_promote_cross_file_statics): Do not promote externals.

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

12 files changed:
gcc/ChangeLog
gcc/cgraph.c
gcc/cgraph.h
gcc/cgraphunit.c
gcc/gimple-fold.c
gcc/ipa.c
gcc/lto-cgraph.c
gcc/lto-streamer-out.c
gcc/lto-symtab.c
gcc/lto/ChangeLog
gcc/lto/lto-partition.c
gcc/varpool.c

index 425ebfd5fca2aba7fbc363f4769634f3abe548cf..d64c667ab3e964746a3250ca502fda5fb8214ce6 100644 (file)
@@ -1,3 +1,26 @@
+2012-05-17  Jan Hubicka  <jh@suse.cz>
+
+       * lto-symtab.c (lto_symtab_resolve_symbols): Preffer decl with constructor
+       over decl without.
+       * cgraph.c (cgraph_remove_node): Clear also body of unanalyzed nodes.
+       * cgraph.h (varpool_can_remove_if_no_refs): Handle external correctly.
+       * cgraphunit.c (process_function_and_variable_attributes): Finalize 
+       extrnal decls.
+       (mark_functions_to_output): Also accept bodies for functions with clones.
+       (output_in_order): Skip external vars.
+       * lto-cgraph.c (lto_output_node): External functions are never in other
+       partition.
+       (lto_output_varpool_node): Likewise.
+       * lto-streamer-out.c (lto_write_tree): Always use error_mark_nodes for
+       forgotten initializers.
+       * ipa.c (process_references): Handle external vars.
+       (symtab_remove_unreachable_nodes): Update to handle external vars.
+       (varpool_externally_visible_p): External vars are externally visible.
+       * gimple-fold.c (can_refer_decl_in_current_unit_p): Update.
+       * varpool.c (varpool_remove_node): Remove constructor.
+       (decide_is_variable_needed): Handle externals.
+       (varpool_remove_unreferenced_decls): Likewise.
+
 2012-05-17  Manuel López-Ibáñez  <manu@gcc.gnu.org>
 
        * opts.c (common_handle_option): -pedantic-errors enables -Wpedantic.
index 88ef1f14e93e894f9bb4206d37b68b933ffe2d0d..86a94162236cbcd74f426a1baf101dc65ee31154 100644 (file)
@@ -1242,6 +1242,7 @@ cgraph_remove_node (struct cgraph_node *node)
          && (cgraph_global_info_ready
              && (TREE_ASM_WRITTEN (n->symbol.decl)
                  || DECL_EXTERNAL (n->symbol.decl)
+                 || !n->analyzed
                  || n->symbol.in_other_partition))))
     cgraph_release_function_body (node);
 
index a4c23b35ec5fdd6cff12174c7f29505f1bd4c952..de854f74b010b4145a594edd97004aa4567ed3b1 100644 (file)
@@ -1123,11 +1123,12 @@ cgraph_only_called_directly_or_aliased_p (struct cgraph_node *node)
 static inline bool
 varpool_can_remove_if_no_refs (struct varpool_node *node)
 {
+  if (DECL_EXTERNAL (node->symbol.decl))
+    return true;
   return (!node->symbol.force_output && !node->symbol.used_from_other_partition
          && (DECL_COMDAT (node->symbol.decl)
-         || !node->symbol.externally_visible
-         || DECL_HAS_VALUE_EXPR_P (node->symbol.decl)
-         || DECL_EXTERNAL (node->symbol.decl)));
+             || !node->symbol.externally_visible
+             || DECL_HAS_VALUE_EXPR_P (node->symbol.decl)));
 }
 
 /* Return true when all references to VNODE must be visible in ipa_ref_list.
index c21ddb84c2f00d244c3d32a70b8d5836ab923db7..97e810e5f2a3302f91449893704f8d7b55d5d964 100644 (file)
@@ -782,6 +782,10 @@ process_function_and_variable_attributes (struct cgraph_node *first,
        vnode = varpool_next_variable (vnode))
     {
       tree decl = vnode->symbol.decl;
+      if (DECL_EXTERNAL (decl)
+         && DECL_INITIAL (decl)
+         && const_value_known_p (decl))
+       varpool_finalize_decl (decl);
       if (DECL_PRESERVE_P (decl))
        vnode->symbol.force_output = true;
       else if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (decl)))
@@ -1161,6 +1165,8 @@ mark_functions_to_output (void)
          gcc_assert (node->global.inlined_to
                      || !gimple_has_body_p (decl)
                      || node->symbol.in_other_partition
+                     || node->clones
+                     || DECL_ARTIFICIAL (decl)
                      || DECL_EXTERNAL (decl));
 
        }
@@ -1760,12 +1766,13 @@ output_in_order (void)
     }
 
   FOR_EACH_DEFINED_VARIABLE (pv)
-    {
-      i = pv->symbol.order;
-      gcc_assert (nodes[i].kind == ORDER_UNDEFINED);
-      nodes[i].kind = ORDER_VAR;
-      nodes[i].u.v = pv;
-    }
+    if (!DECL_EXTERNAL (pv->symbol.decl))
+      {
+       i = pv->symbol.order;
+       gcc_assert (nodes[i].kind == ORDER_UNDEFINED);
+       nodes[i].kind = ORDER_VAR;
+       nodes[i].u.v = pv;
+      }
 
   for (pa = asm_nodes; pa; pa = pa->next)
     {
index b6f01430bb1c93e29b7c9567791cbbbe1d17e008..dbe1b838c5baf64423c9cfee2f3090ab41cde331 100644 (file)
@@ -62,18 +62,11 @@ can_refer_decl_in_current_unit_p (tree decl)
   if (!TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
     return true;
   /* External flag is set, so we deal with C++ reference
-     to static object from other file.  */
+     to static object from other file.
+     We also may see weakref that is always safe.  */
   if (DECL_EXTERNAL (decl) && TREE_STATIC (decl)
       && TREE_CODE (decl) == VAR_DECL)
-    {
-      /* Just be sure it is not big in frontend setting
-        flags incorrectly.  Those variables should never
-        be finalized.  */
-      gcc_checking_assert (!(vnode = varpool_get_node (decl))
-                          || vnode->alias
-                          || !vnode->finalized);
-      return false;
-    }
+    return lookup_attribute ("weakref", DECL_ATTRIBUTES (decl)) != NULL;
   /* When function is public, we always can introduce new reference.
      Exception are the COMDAT functions where introducing a direct
      reference imply need to include function body in the curren tunit.  */
index a107c6f0ec518dd9d859708ebc6603530ddc6f85..cafa7a11f2a96b60ccc40975b5a38664a11f1e6d 100644 (file)
--- a/gcc/ipa.c
+++ b/gcc/ipa.c
@@ -100,7 +100,10 @@ process_references (struct ipa_ref_list *list,
        {
          struct varpool_node *node = ipa_ref_varpool_node (ref);
 
-         if (node->analyzed)
+         if (node->analyzed
+             && (!DECL_EXTERNAL (node->symbol.decl)
+                 || node->alias
+                 || before_inlining_p))
            pointer_set_insert (reachable, node);
          enqueue_node ((symtab_node) node, first, reachable);
        }
@@ -187,6 +190,12 @@ has_addr_references_p (struct cgraph_node *node,
      reshape callgraph and preserve body when offline copy of function or
      inline clone is being removed.
 
+   - C++ virtual tables keyed to other unit are represented as DECL_EXTERNAL
+     variables with DECL_INITIAL set.  We finalize these and keep reachable
+     ones around for constant folding purposes.  After inlining we however
+     stop walking their references to let everything static referneced by them
+     to be removed when it is otherwise unreachable.
+
    We maintain queue of both reachable symbols (i.e. defined symbols that needs
    to stay) and symbols that are in boundary (i.e. external symbols referenced
    by reachable symbols or origins of clones).  The queue is represented
@@ -323,6 +332,19 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
                }
            }
        }
+      /* When we see constructor of external variable, keep referred nodes in the
+        boundary.  This will also hold initializers of the external vars NODE
+        reffers to.  */
+      if (symtab_variable_p (node)
+         && DECL_EXTERNAL (node->symbol.decl)
+         && !varpool (node)->alias
+         && in_boundary_p)
+        {
+         int i;
+         struct ipa_ref *ref;
+         for (i = 0; ipa_ref_list_reference_iterate (&node->symbol.ref_list, i, ref); i++)
+           enqueue_node (ref->referred, &first, reachable);
+        }
     }
 
   /* Remove unreachable functions.   */
@@ -347,7 +369,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
              changed = true;
            }
          if (!pointer_set_contains (body_needed_for_clonning, node->symbol.decl)
-             && !DECL_ARTIFICIAL (node->symbol.decl))
+             && (node->local.finalized || !DECL_ARTIFICIAL (node->symbol.decl)))
            cgraph_release_function_body (node);
          node->analyzed = false;
        }
@@ -627,6 +649,9 @@ varpool_externally_visible_p (struct varpool_node *vnode, bool aliased)
   if (vnode->alias && DECL_EXTERNAL (vnode->symbol.decl))
     return true;
 
+  if (DECL_EXTERNAL (vnode->symbol.decl))
+    return true;
+
   if (!DECL_COMDAT (vnode->symbol.decl) && !TREE_PUBLIC (vnode->symbol.decl))
     return false;
 
index 2563489904784de9274b32ba806d896f736c56f8..447948f75a93f14b971087986c38bf0bb8bd5517 100644 (file)
@@ -440,7 +440,7 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
      Cherry-picked nodes:  These are nodes we pulled from other
      translation units into SET during IPA-inlining.  We make them as
      local static nodes to prevent clashes with other local statics.  */
-  if (boundary_p && node->analyzed)
+  if (boundary_p && node->analyzed && !DECL_EXTERNAL (node->symbol.decl))
     {
       /* Inline clones can not be part of boundary.  
          gcc_assert (!node->global.inlined_to);  
@@ -575,6 +575,7 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node
      FIXME: Alternatively at -Os we may want to avoid generating for them the local
      labels and share them across LTRANS partitions.  */
   if (DECL_IN_CONSTANT_POOL (node->symbol.decl)
+      && !DECL_EXTERNAL (node->symbol.decl)
       && !DECL_COMDAT (node->symbol.decl))
     {
       bp_pack_value (&bp, 0, 1);  /* used_from_other_parition.  */
@@ -585,7 +586,8 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node
       bp_pack_value (&bp, node->analyzed
                     && referenced_from_other_partition_p (&node->symbol.ref_list,
                                                           set, vset), 1);
-      bp_pack_value (&bp, boundary_p, 1);  /* in_other_partition.  */
+      bp_pack_value (&bp, boundary_p && !DECL_EXTERNAL (node->symbol.decl), 1);
+         /* in_other_partition.  */
     }
   streamer_write_bitpack (&bp);
   if (node->alias_of)
index 9a54f1900ffaf930cffa48c6d68c045a9d917704..a4b28422664ab03ebd388ee722ee55adea76d0b6 100644 (file)
@@ -353,11 +353,10 @@ lto_write_tree (struct output_block *ob, tree expr, bool ref_p)
 
          varpool_encoder = ob->decl_state->varpool_node_encoder;
          vnode = varpool_get_node (expr);
-         if (!vnode)
+         if (!vnode
+             || !lto_varpool_encoder_encode_initializer_p (varpool_encoder,
+                                                           vnode))
            initial = error_mark_node;
-         else if (!lto_varpool_encoder_encode_initializer_p (varpool_encoder,
-                                                             vnode))
-           initial = NULL;
        }
 
       stream_write_tree (ob, initial, ref_p);
index a371c0a7f111d02848bfe033857c57df1246dbac..c5efb7f0156ed430d9fbfa1089a96b59290e9832 100644 (file)
@@ -489,7 +489,21 @@ lto_symtab_resolve_symbols (void **slot)
       /* From variables that can prevail choose the largest one.  */
       if (!prevailing
          || tree_int_cst_lt (DECL_SIZE (prevailing->decl),
-                             DECL_SIZE (e->decl)))
+                             DECL_SIZE (e->decl))
+         /* When variables are equivalent try to chose one that has useful
+            DECL_INITIAL.  This makes sense for keyed vtables that are
+            DECL_EXTERNAL but initialized.  In units that do not need them
+            we replace the initializer by error_mark_node to conserve
+            memory.
+
+            We know that the vtable is keyed outside the LTO unit - otherwise
+            the keyed instance would prevail.  We still can preserve useful
+            info in the initializer.  */
+         || (DECL_SIZE (prevailing->decl) == DECL_SIZE (e->decl)
+             && (DECL_INITIAL (e->decl)
+                 && DECL_INITIAL (e->decl) != error_mark_node)
+             && (!DECL_INITIAL (prevailing->decl)
+                 || DECL_INITIAL (prevailing->decl) == error_mark_node)))
        prevailing = e;
     }
 
index 6edc2afbc823f923c9109106a50d31dd913bffa5..04d4d03ee5b8b843b2b93b3a0008c6c7dbe5a52f 100644 (file)
@@ -1,3 +1,9 @@
+2012-05-17  Jan Hubicka  <jh@suse.cz>
+
+       * lto-partition.c (add_references_to_partition): Handle external vars.
+       (partition_varpool_node_p): Likewise.
+       (lto_promote_cross_file_statics): Do not promote externals.
+
 2012-05-14  Bernd Schmidt  <bernds@codesourcery.com>
 
        * lto-lang.c (handle_fnspec_attribute): New static function.
index 5c931e682af65ae4490e3fcb3fbc44095d4974c2..602173dd94931f9bac3945c49fcb86224f22c35e 100644 (file)
@@ -83,6 +83,7 @@ add_references_to_partition (ltrans_partition part, struct ipa_ref_list *refs)
       else
         if (symtab_variable_p (ref->referred)
            && (DECL_COMDAT (ipa_ref_varpool_node (ref)->symbol.decl)
+               || DECL_EXTERNAL (ipa_ref_varpool_node (ref)->symbol.decl)
                || (ref->use == IPA_REF_ALIAS
                    && lookup_attribute
                         ("weakref",
@@ -287,6 +288,7 @@ partition_varpool_node_p (struct varpool_node *vnode)
     return false;
   /* Constant pool and comdat are always only in partitions they are needed.  */
   if (DECL_IN_CONSTANT_POOL (vnode->symbol.decl)
+      || DECL_EXTERNAL (vnode->symbol.decl)
       || (DECL_COMDAT (vnode->symbol.decl)
          && !vnode->symbol.force_output
          && !symtab_used_from_object_file_p ((symtab_node) vnode)))
@@ -843,6 +845,7 @@ lto_promote_cross_file_statics (void)
             be made global.  It is sensible to keep those ltrans local to
             allow better optimization.  */
          if (!DECL_IN_CONSTANT_POOL (vnode->symbol.decl)
+             && !DECL_EXTERNAL (vnode->symbol.decl)
              && !DECL_COMDAT (vnode->symbol.decl)
              && !vnode->symbol.externally_visible && vnode->analyzed
              && referenced_from_other_partition_p (&vnode->symbol.ref_list,
@@ -893,8 +896,11 @@ lto_promote_cross_file_statics (void)
 
                  /* Constant pool references use internal labels and thus
                     cannot be made global.  It is sensible to keep those
-                    ltrans local to allow better optimization.  */
-                 if (DECL_IN_CONSTANT_POOL (v->symbol.decl))
+                    ltrans local to allow better optimization.
+                    Similarly we ship external vars initializers into
+                    every ltrans unit possibly referring to it.  */
+                 if (DECL_IN_CONSTANT_POOL (v->symbol.decl)
+                     || DECL_EXTERNAL (v->symbol.decl))
                    {
                      if (!pointer_set_insert (inserted, vnode))
                        VEC_safe_push (varpool_node_ptr, heap,
index ef025670125915dd254a05e7d025de25c5d2ed14..ceb16f9bbcac7871378e1a590a82b4fe5a39fc69 100644 (file)
@@ -59,6 +59,14 @@ void
 varpool_remove_node (struct varpool_node *node)
 {
   symtab_unregister_node ((symtab_node)node);
+  if (DECL_INITIAL (node->symbol.decl)
+      && !DECL_IN_CONSTANT_POOL (node->symbol.decl)
+      /* Keep vtables for BINFO folding.  */
+      && !DECL_VIRTUAL_P (node->symbol.decl)
+      /* dbxout output constant initializers for readonly vars.  */
+      && (!host_integerp (DECL_INITIAL (node->symbol.decl), 0)
+         || !TREE_READONLY (node->symbol.decl)))
+    DECL_INITIAL (node->symbol.decl) = error_mark_node;
   ggc_free (node);
 }
 
@@ -118,17 +126,17 @@ varpool_node_for_asm (tree asmname)
 bool
 decide_is_variable_needed (struct varpool_node *node, tree decl)
 {
+  if (DECL_EXTERNAL (decl))
+    return false;
+
   /* If the user told us it is used, then it must be so.  */
   if (node->symbol.force_output)
     return true;
 
-  gcc_assert (!DECL_EXTERNAL (decl));
-
   /* Externally visible variables must be output.  The exception is
      COMDAT variables that must be output only when they are needed.  */
   if (TREE_PUBLIC (decl)
-      && !DECL_COMDAT (decl)
-      && !DECL_EXTERNAL (decl))
+      && !DECL_COMDAT (decl))
     return true;
 
   return false;
@@ -348,7 +356,8 @@ varpool_remove_unreferenced_decls (void)
          && (!varpool_can_remove_if_no_refs (node)
              /* We just expanded all function bodies.  See if any of
                 them needed the variable.  */
-             || DECL_RTL_SET_P (node->symbol.decl)))
+             || (!DECL_EXTERNAL (node->symbol.decl)
+                 && DECL_RTL_SET_P (node->symbol.decl))))
        {
          enqueue_node (node, &first);
           if (cgraph_dump_file)
@@ -372,6 +381,8 @@ varpool_remove_unreferenced_decls (void)
        }
       for (i = 0; ipa_ref_list_reference_iterate (&node->symbol.ref_list, i, ref); i++)
        if (symtab_variable_p (ref->referred)
+           && (!DECL_EXTERNAL (ref->referred->symbol.decl)
+               || varpool (ref->referred)->alias)
            && varpool (ref->referred)->analyzed)
          enqueue_node (varpool (ref->referred), &first);
     }