lto-symtab.c (lto_cgraph_replace_node): Merge needed instead of force flags.
authorJan Hubicka <jh@suse.cz>
Fri, 20 Apr 2012 14:09:11 +0000 (16:09 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Fri, 20 Apr 2012 14:09:11 +0000 (14:09 +0000)
* lto-symtab.c (lto_cgraph_replace_node): Merge needed instead of force flags.
* cgraph.c (cgraph_add_thunk): Use mark_reachable_node.
(cgraph_remove_node): Update.
(cgraph_mark_needed_node): Remove.
(cgraph_mark_force_output_node): New.
(dump_cgraph_node): Do not dump needed flag.
(cgraph_node_cannot_be_local_p_1): Update.
(cgraph_can_remove_if_no_direct_calls_and_refs): Update.
* cgraph.h (symtab_node_base): Add force_output flag.
(cgraph_node): Remove needed flag.
(varpool_node): Remove force_output flag.
(cgraph_mark_needed_node): Remove.
(cgraph_mark_force_output_node): New.
(cgraph_only_called_directly_or_aliased_p,
varpool_can_remove_if_no_refs, varpool_all_refs_explicit_p): Update.
* ipa-cp.c (ipcp_generate_summary): Remove out of date assert.
* cgraphunit.c (cgraph_decide_is_function_needed): rewrite.
(cgraph_add_new_function); Update.
(cgraph_mark_if_needed); Update.
(verify_cgraph_node): Update.
(cgraph_analyze_function): Alias target is reachable.
(process_function_and_variable_attributes): Update: externally_visible
flag makes function reachable.
(cgraph_analyze_functions): Update dumping.
* lto-cgraph.c (lto_output_node, lto_output_varpool_node,
input_overwrite_node, input_varpool_node): Update streaming.
* lto-streamer-out.c (produce_symtab): Use force_output.
* ipa.c (process_references): Weakrefs must be processed.
(cgraph_remove_unreachable_nodes): Likewise; update for new
force_output flag.
(varpool_externally_visible_p); Weakrefs are externally visible
even if they are not.
(function_and_variable_visibility): Update; when processing alias
pair force the targets to be output.
(whole_program_function_and_variable_visility): Use mark_reachable_node.
* trans-mem.c (ipa_tm_mark_needed_node): Remove
(ipa_tm_mark_force_output_node): New function.
(ipa_tm_create_version_alias, ipa_tm_create_version): Update.
* gimple-fold.c (can_refer_decl_in_current_unit_p): Be lax about aliases.
* varasm.c (mark_decl_referenced): Update.
(find_decl_and_mark_needed): Remove.
(find_decl): New function.
(weak_finish, finish_aliases_1, assemble_alias): Update; do not mark
alias targets as needed.
(dump_tm_clone_pairs): Update.
* tree-inline.c (copy_bb): Update check.
* symtab.c (dump_symtab_base): Dump force_output.
* tree-ssa-structalias.c (ipa_pta_execute): Use force_output.
* passes.c (execute_todo): Fix dumping.
* varpool.c (decide_is_variable_needed, varpool_finalize_decl): Update.
(varpool_analyze_pending_decls): Alias target is reachable.
(varpool_create_variable_alias): Finalize weakrefs.

* class.c (make_local_function_alias): Do not mark symbol referenced.

* objc-acct.c (mark_referenced_methods); Use
cgraph_mark_force_output_node.

* gcc-interface/utils.c (gnat_write_global_declarations): Update for new
force_output placement.

* lto/lto-partition.c (partition_cgraph_node_p): Use force_output.

From-SVN: r186624

25 files changed:
gcc/ChangeLog
gcc/ada/ChangeLog
gcc/ada/gcc-interface/utils.c
gcc/cgraph.c
gcc/cgraph.h
gcc/cgraphunit.c
gcc/gimple-fold.c
gcc/ipa-cp.c
gcc/ipa.c
gcc/java/ChangeLog
gcc/java/class.c
gcc/lto-cgraph.c
gcc/lto-streamer-out.c
gcc/lto-symtab.c
gcc/lto/ChangeLog
gcc/lto/lto-partition.c
gcc/objc/ChangeLog
gcc/objc/objc-act.c
gcc/passes.c
gcc/symtab.c
gcc/trans-mem.c
gcc/tree-inline.c
gcc/tree-ssa-structalias.c
gcc/varasm.c
gcc/varpool.c

index ff0cc2c..557968c 100644 (file)
@@ -1,3 +1,58 @@
+2012-04-20  Jan Hubicka  <jh@suse.cz>
+
+       * lto-symtab.c (lto_cgraph_replace_node): Merge needed instead of force flags.
+       * cgraph.c (cgraph_add_thunk): Use mark_reachable_node.
+       (cgraph_remove_node): Update.
+       (cgraph_mark_needed_node): Remove.
+       (cgraph_mark_force_output_node): New.
+       (dump_cgraph_node): Do not dump needed flag.
+       (cgraph_node_cannot_be_local_p_1): Update.
+       (cgraph_can_remove_if_no_direct_calls_and_refs): Update.
+       * cgraph.h (symtab_node_base): Add force_output flag.
+       (cgraph_node): Remove needed flag.
+       (varpool_node): Remove force_output flag.
+       (cgraph_mark_needed_node): Remove.
+       (cgraph_mark_force_output_node): New.
+       (cgraph_only_called_directly_or_aliased_p,
+       varpool_can_remove_if_no_refs, varpool_all_refs_explicit_p): Update.
+       * ipa-cp.c (ipcp_generate_summary): Remove out of date assert.
+       * cgraphunit.c (cgraph_decide_is_function_needed): rewrite.
+       (cgraph_add_new_function); Update.
+       (cgraph_mark_if_needed); Update.
+       (verify_cgraph_node): Update.
+       (cgraph_analyze_function): Alias target is reachable.
+       (process_function_and_variable_attributes): Update: externally_visible
+       flag makes function reachable.
+       (cgraph_analyze_functions): Update dumping.
+       * lto-cgraph.c (lto_output_node, lto_output_varpool_node,
+       input_overwrite_node, input_varpool_node): Update streaming.
+       * lto-streamer-out.c (produce_symtab): Use force_output.
+       * ipa.c (process_references): Weakrefs must be processed.
+       (cgraph_remove_unreachable_nodes): Likewise; update for new
+       force_output flag.
+       (varpool_externally_visible_p); Weakrefs are externally visible
+       even if they are not.
+       (function_and_variable_visibility): Update; when processing alias
+       pair force the targets to be output.
+       (whole_program_function_and_variable_visility): Use mark_reachable_node.
+       * trans-mem.c (ipa_tm_mark_needed_node): Remove
+       (ipa_tm_mark_force_output_node): New function.
+       (ipa_tm_create_version_alias, ipa_tm_create_version): Update.
+       * gimple-fold.c (can_refer_decl_in_current_unit_p): Be lax about aliases.
+       * varasm.c (mark_decl_referenced): Update.
+       (find_decl_and_mark_needed): Remove.
+       (find_decl): New function.
+       (weak_finish, finish_aliases_1, assemble_alias): Update; do not mark
+       alias targets as needed.
+       (dump_tm_clone_pairs): Update.
+       * tree-inline.c (copy_bb): Update check.
+       * symtab.c (dump_symtab_base): Dump force_output.
+       * tree-ssa-structalias.c (ipa_pta_execute): Use force_output.
+       * passes.c (execute_todo): Fix dumping.
+       * varpool.c (decide_is_variable_needed, varpool_finalize_decl): Update.
+       (varpool_analyze_pending_decls): Alias target is reachable.
+       (varpool_create_variable_alias): Finalize weakrefs.
+
 2012-04-20  Jakub Jelinek  <jakub@redhat.com>
 
        PR bootstrap/53021
index ef1214a..8fd284a 100644 (file)
@@ -1,3 +1,8 @@
+2012-04-20  Jan Hubicka  <jh@suse.cz>
+
+       * gcc-interface/utils.c (gnat_write_global_declarations): Update for new
+       force_output placement.
+
 2012-04-14  Jan Hubicka  <jh@suse.cz>
 
        * gcc-interface/trans.c (finalize_nrv): Update field referenced for new
index 1460a43..e95e967 100644 (file)
@@ -4859,7 +4859,7 @@ gnat_write_global_declarations (void)
       TREE_STATIC (dummy_global) = 1;
       TREE_ASM_WRITTEN (dummy_global) = 1;
       node = varpool_node (dummy_global);
-      node->force_output = 1;
+      node->symbol.force_output = 1;
       varpool_mark_needed_node (node);
 
       while (!VEC_empty (tree, types_used_by_cur_var_decl))
index 8ba9c36..4588249 100644 (file)
@@ -570,7 +570,7 @@ cgraph_add_thunk (struct cgraph_node *decl_node ATTRIBUTE_UNUSED,
   node->local.finalized = true;
 
   if (cgraph_decide_is_function_needed (node, decl))
-    cgraph_mark_needed_node (node);
+    cgraph_mark_reachable_node (node);
 
   if ((TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
       || (DECL_VIRTUAL_P (decl)
@@ -1362,7 +1362,7 @@ cgraph_remove_node (struct cgraph_node *node)
 
   /* Incremental inlining access removed nodes stored in the postorder list.
      */
-  node->needed = node->reachable = false;
+  node->symbol.force_output = node->reachable = false;
   for (n = node->nested; n; n = n->next_nested)
     n->origin = NULL;
   node->nested = NULL;
@@ -1518,9 +1518,9 @@ cgraph_mark_reachable_node (struct cgraph_node *node)
    external means.  */
 
 void
-cgraph_mark_needed_node (struct cgraph_node *node)
+cgraph_mark_force_output_node (struct cgraph_node *node)
 {
-  node->needed = 1;
+  node->symbol.force_output = 1;
   gcc_assert (!node->global.inlined_to);
   cgraph_mark_reachable_node (node);
 }
@@ -1642,8 +1642,6 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node)
             (HOST_WIDEST_INT)node->count);
   if (node->origin)
     fprintf (f, " nested in: %s", cgraph_node_asm_name (node->origin));
-  if (node->needed)
-    fprintf (f, " needed");
   else if (node->reachable)
     fprintf (f, " reachable");
   if (gimple_has_body_p (node->symbol.decl))
@@ -2134,7 +2132,7 @@ static bool
 cgraph_node_cannot_be_local_p_1 (struct cgraph_node *node,
                                 void *data ATTRIBUTE_UNUSED)
 {
-  return !(!node->needed
+  return !(!node->symbol.force_output
           && ((DECL_COMDAT (node->symbol.decl)
                && !node->symbol.same_comdat_group)
               || !node->symbol.externally_visible));
@@ -2570,7 +2568,7 @@ cgraph_can_remove_if_no_direct_calls_and_refs_p (struct cgraph_node *node)
   if (DECL_EXTERNAL (node->symbol.decl))
     return true;
   /* When function is needed, we can not remove it.  */
-  if (node->needed || node->symbol.used_from_other_partition)
+  if (node->symbol.force_output || node->symbol.used_from_other_partition)
     return false;
   if (DECL_STATIC_CONSTRUCTOR (node->symbol.decl)
       || DECL_STATIC_DESTRUCTOR (node->symbol.decl))
index 1fd42f1..5915a14 100644 (file)
@@ -77,6 +77,9 @@ struct GTY(()) symtab_node_base
   unsigned in_other_partition : 1;
   /* Set when function is visible by other units.  */
   unsigned externally_visible : 1;
+  /* Needed variables might become dead by optimization.  This flag
+     forces the variable to be output even if it appears dead otherwise.  */
+  unsigned force_output : 1;
 };
 
 enum availability
@@ -246,12 +249,6 @@ struct GTY(()) cgraph_node {
   /* Unique id of the node.  */
   int uid;
 
-  /* Set when function must be output for some reason.  The primary
-     use of this flag is to mark functions needed to be output for
-     non-standard reason.  Functions that are externally visible
-     or reachable from functions needed to be output are marked
-     by specialized flags.  */
-  unsigned needed : 1;
   /* Set when decl is an abstract function pointed to by the
      ABSTRACT_DECL_ORIGIN of a reachable function.  */
   unsigned abstract_and_needed : 1;
@@ -433,9 +430,6 @@ struct GTY(()) varpool_node {
   /* Set when function must be output - it is externally visible
      or its address is taken.  */
   unsigned needed : 1;
-  /* Needed variables might become dead by optimization.  This flag
-     forces the variable to be output even if it appears dead otherwise.  */
-  unsigned force_output : 1;
   /* Set once the variable has been instantiated and its callee
      lists created.  */
   unsigned analyzed : 1;
@@ -610,7 +604,7 @@ void cgraph_mark_if_needed (tree);
 void cgraph_analyze_function (struct cgraph_node *);
 void cgraph_finalize_compilation_unit (void);
 void cgraph_optimize (void);
-void cgraph_mark_needed_node (struct cgraph_node *);
+void cgraph_mark_force_output_node (struct cgraph_node *);
 void cgraph_mark_address_taken_node (struct cgraph_node *);
 void cgraph_mark_reachable_node (struct cgraph_node *);
 bool cgraph_inline_p (struct cgraph_edge *, cgraph_inline_failed_t *reason);
@@ -1118,7 +1112,7 @@ static inline bool
 cgraph_only_called_directly_or_aliased_p (struct cgraph_node *node)
 {
   gcc_assert (!node->global.inlined_to);
-  return (!node->needed && !node->symbol.address_taken
+  return (!node->symbol.force_output && !node->symbol.address_taken
          && !node->symbol.used_from_other_partition
          && !DECL_STATIC_CONSTRUCTOR (node->symbol.decl)
          && !DECL_STATIC_DESTRUCTOR (node->symbol.decl)
@@ -1131,9 +1125,10 @@ cgraph_only_called_directly_or_aliased_p (struct cgraph_node *node)
 static inline bool
 varpool_can_remove_if_no_refs (struct varpool_node *node)
 {
-  return (!node->force_output && !node->symbol.used_from_other_partition
+  return (!node->symbol.force_output && !node->symbol.used_from_other_partition
          && (DECL_COMDAT (node->symbol.decl)
-         || !node->symbol.externally_visible));
+         || !node->symbol.externally_visible
+         || DECL_EXTERNAL (node->symbol.decl)));
 }
 
 /* Return true when all references to VNODE must be visible in ipa_ref_list.
@@ -1147,7 +1142,7 @@ varpool_all_refs_explicit_p (struct varpool_node *vnode)
   return (vnode->analyzed
          && !vnode->symbol.externally_visible
          && !vnode->symbol.used_from_other_partition
-         && !vnode->force_output);
+         && !vnode->symbol.force_output);
 }
 
 /* Constant pool accessor function.  */
index 9de4233..3e07e50 100644 (file)
@@ -156,56 +156,36 @@ FILE *cgraph_dump_file;
 /* Used for vtable lookup in thunk adjusting.  */
 static GTY (()) tree vtable_entry_type;
 
-/* Determine if function DECL is needed.  That is, visible to something
-   either outside this translation unit, something magic in the system
-   configury.  */
+/* Determine if function DECL is trivially needed and should stay in the
+   compilation unit.  This is used at the symbol table construction time
+   and differs from later logic removing unnecesary functions that can
+   take into account results of analysis, whole program info etc.  */
 
 bool
 cgraph_decide_is_function_needed (struct cgraph_node *node, tree decl)
 {
   /* If the user told us it is used, then it must be so.  */
-  if (node->symbol.externally_visible)
+  if (node->symbol.force_output)
     return true;
 
-  /* ??? If the assembler name is set by hand, it is possible to assemble
-     the name later after finalizing the function and the fact is noticed
-     in assemble_name then.  This is arguably a bug.  */
-  if (DECL_ASSEMBLER_NAME_SET_P (decl)
-      && (!node->thunk.thunk_p && !node->same_body_alias)
-      && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
-    return true;
+  /* Double check that no one output the function into assembly file
+     early.  */
+  gcc_checking_assert (!DECL_ASSEMBLER_NAME_SET_P (decl)
+                      || (node->thunk.thunk_p || node->same_body_alias)
+                      ||  !TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)));
 
-  /* With -fkeep-inline-functions we are keeping all inline functions except
-     for extern inline ones.  */
-  if (flag_keep_inline_functions
-      && DECL_DECLARED_INLINE_P (decl)
-      && !DECL_EXTERNAL (decl)
-      && !DECL_DISREGARD_INLINE_LIMITS (decl))
-     return true;
 
-  /* If we decided it was needed before, but at the time we didn't have
-     the body of the function available, then it's still needed.  We have
-     to go back and re-check its dependencies now.  */
-  if (node->needed)
-    return true;
+  /* Keep constructors, destructors and virtual functions.  */
+  if (DECL_STATIC_CONSTRUCTOR (decl)
+      || DECL_STATIC_DESTRUCTOR (decl)
+      || (DECL_VIRTUAL_P (decl)
+         && optimize && (DECL_COMDAT (decl) || DECL_EXTERNAL (decl))))
+     return true;
 
   /* Externally visible functions must be output.  The exception is
-     COMDAT functions that must be output only when they are needed.
+     COMDAT functions that must be output only when they are needed.  */
 
-     When not optimizing, also output the static functions. (see
-     PR24561), but don't do so for always_inline functions, functions
-     declared inline and nested functions.  These were optimized out
-     in the original implementation and it is unclear whether we want
-     to change the behavior here.  */
-  if (((TREE_PUBLIC (decl)
-       || (!optimize
-           && !node->same_body_alias
-           && !DECL_DISREGARD_INLINE_LIMITS (decl)
-           && !DECL_DECLARED_INLINE_P (decl)
-           && !(DECL_CONTEXT (decl)
-                && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL)))
-       && !flag_whole_program
-       && !flag_lto)
+  if (TREE_PUBLIC (decl)
       && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
     return true;
 
@@ -337,22 +317,29 @@ cgraph_finalize_function (tree decl, bool nested)
   node->local.finalized = true;
   node->lowered = DECL_STRUCT_FUNCTION (decl)->cfg != NULL;
 
-  if (cgraph_decide_is_function_needed (node, decl))
-    cgraph_mark_needed_node (node);
+  /* With -fkeep-inline-functions we are keeping all inline functions except
+     for extern inline ones.  */
+  if (flag_keep_inline_functions
+      && DECL_DECLARED_INLINE_P (decl)
+      && !DECL_EXTERNAL (decl)
+      && !DECL_DISREGARD_INLINE_LIMITS (decl))
+    node->symbol.force_output = 1;
 
-  /* Since we reclaim unreachable nodes at the end of every language
-     level unit, we need to be conservative about possible entry points
-     there.  */
-  if ((TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
-      || DECL_STATIC_CONSTRUCTOR (decl)
-      || DECL_STATIC_DESTRUCTOR (decl)
-      /* COMDAT virtual functions may be referenced by vtable from
-        other compilation unit.  Still we want to devirtualize calls
-        to those so we need to analyze them.
-        FIXME: We should introduce may edges for this purpose and update
-        their handling in unreachable function removal and inliner too.  */
-      || (DECL_VIRTUAL_P (decl)
-         && optimize && (DECL_COMDAT (decl) || DECL_EXTERNAL (decl))))
+  /* When not optimizing, also output the static functions. (see
+     PR24561), but don't do so for always_inline functions, functions
+     declared inline and nested functions.  These were optimized out
+     in the original implementation and it is unclear whether we want
+     to change the behavior here.  */
+  if ((!optimize
+       && !node->same_body_alias
+       && !DECL_DISREGARD_INLINE_LIMITS (decl)
+       && !DECL_DECLARED_INLINE_P (decl)
+       && !(DECL_CONTEXT (decl)
+           && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL))
+      && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
+    node->symbol.force_output = 1;
+
+  if (cgraph_decide_is_function_needed (node, decl))
     cgraph_mark_reachable_node (node);
 
   /* If we've not yet emitted decl, tell the debug info about it.  */
@@ -402,7 +389,7 @@ cgraph_add_new_function (tree fndecl, bool lowered)
        node = cgraph_get_create_node (fndecl);
        node->local.local = false;
        node->local.finalized = true;
-       node->reachable = node->needed = true;
+       node->reachable = node->symbol.force_output = true;
        if (!lowered && cgraph_state == CGRAPH_STATE_EXPANSION)
          {
            push_cfun (DECL_STRUCT_FUNCTION (fndecl));
@@ -462,7 +449,7 @@ cgraph_mark_if_needed (tree decl)
 {
   struct cgraph_node *node = cgraph_get_node (decl);
   if (node->local.finalized && cgraph_decide_is_function_needed (node, decl))
-    cgraph_mark_needed_node (node);
+    cgraph_mark_reachable_node (node);
 }
 
 /* Return TRUE if NODE2 is equivalent to NODE or its clone.  */
@@ -601,9 +588,9 @@ verify_cgraph_node (struct cgraph_node *node)
       error ("inline clone with address taken");
       error_found = true;
     }
-  if (node->global.inlined_to && node->needed)
+  if (node->global.inlined_to && node->symbol.force_output)
     {
-      error ("inline clone is needed");
+      error ("inline clone is forced to output");
       error_found = true;
     }
   for (e = node->indirect_calls; e; e = e->next_callee)
@@ -901,6 +888,7 @@ cgraph_analyze_function (struct cgraph_node *node)
       if (!VEC_length (ipa_ref_t, node->symbol.ref_list.references))
         ipa_record_reference ((symtab_node)node, (symtab_node)tgt,
                              IPA_REF_ALIAS, NULL);
+      cgraph_mark_reachable_node (tgt);
       if (node->same_body_alias)
        { 
          DECL_VIRTUAL_P (node->symbol.decl) = DECL_VIRTUAL_P (node->thunk.alias);
@@ -940,7 +928,7 @@ cgraph_analyze_function (struct cgraph_node *node)
       if (node->symbol.address_taken)
        cgraph_mark_address_taken_node (cgraph_alias_aliased_node (node));
       if (cgraph_decide_is_function_needed (node, node->symbol.decl))
-       cgraph_mark_needed_node (node);
+       cgraph_mark_reachable_node (node);
     }
   else if (node->thunk.thunk_p)
     {
@@ -1061,13 +1049,13 @@ process_function_and_variable_attributes (struct cgraph_node *first,
     {
       tree decl = node->symbol.decl;
       if (DECL_PRESERVE_P (decl))
-       cgraph_mark_needed_node (node);
+       cgraph_mark_force_output_node (node);
       if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
          && lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl))
          && TREE_PUBLIC (node->symbol.decl))
        {
          if (node->local.finalized)
-           cgraph_mark_needed_node (node);
+           cgraph_mark_reachable_node (node);
        }
       else if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (decl)))
        {
@@ -1076,7 +1064,7 @@ process_function_and_variable_attributes (struct cgraph_node *first,
                        "%<externally_visible%>"
                        " attribute have effect only on public objects");
          else if (node->local.finalized)
-            cgraph_mark_needed_node (node);
+           cgraph_mark_reachable_node (node);
        }
       if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))
          && (node->local.finalized && !node->alias))
@@ -1104,7 +1092,7 @@ process_function_and_variable_attributes (struct cgraph_node *first,
       tree decl = vnode->symbol.decl;
       if (DECL_PRESERVE_P (decl))
        {
-         vnode->force_output = true;
+         vnode->symbol.force_output = true;
          if (vnode->finalized)
            varpool_mark_needed_node (vnode);
        }
@@ -1165,7 +1153,7 @@ cgraph_analyze_functions (void)
       fprintf (cgraph_dump_file, "Initial entry points:");
       for (node = cgraph_first_function (); node != first_analyzed;
           node = cgraph_next_function (node))
-       if (node->needed)
+       if (cgraph_decide_is_function_needed (node, node->symbol.decl))
          fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
       fprintf (cgraph_dump_file, "\n");
     }
@@ -1241,7 +1229,7 @@ cgraph_analyze_functions (void)
       fprintf (cgraph_dump_file, "Unit entry points:");
       for (node = cgraph_first_function (); node != first_analyzed;
           node = cgraph_next_function (node))
-       if (node->needed)
+       if (cgraph_decide_is_function_needed (node, node->symbol.decl))
          fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
       fprintf (cgraph_dump_file, "\n\nInitial ");
       dump_symtab (cgraph_dump_file);
index 049da57..49505ee 100644 (file)
@@ -70,6 +70,7 @@ can_refer_decl_in_current_unit_p (tree decl)
         flags incorrectly.  Those variables should never
         be finalized.  */
       gcc_checking_assert (!(vnode = varpool_get_node (decl))
+                          || vnode->alias
                           || !vnode->finalized);
       return false;
     }
index d0a6ee0..4826c58 100644 (file)
@@ -2494,8 +2494,6 @@ ipcp_generate_summary (void)
 
   FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
       {
-       /* Unreachable nodes should have been eliminated before ipcp.  */
-       gcc_assert (node->needed || node->reachable);
        node->local.versionable
          = tree_versionable_function_p (node->symbol.decl);
        ipa_analyze_node (node);
index 964b2b9..f4daf36 100644 (file)
--- a/gcc/ipa.c
+++ b/gcc/ipa.c
@@ -97,6 +97,7 @@ process_references (struct ipa_ref_list *list,
          if (!node->reachable
              && node->analyzed
              && (!DECL_EXTERNAL (node->symbol.decl)
+                 || node->alias
                  || before_inlining_p))
            node->reachable = true;
          enqueue_cgraph_node (node, first);
@@ -214,7 +215,7 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
     {
       vnode->next_needed = NULL;
       vnode->prev_needed = NULL;
-      if ((vnode->analyzed || vnode->force_output)
+      if ((vnode->analyzed || vnode->symbol.force_output)
          && !varpool_can_remove_if_no_refs (vnode))
        {
          vnode->needed = false;
@@ -254,6 +255,7 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
                      && node->analyzed
                      && (!e->inline_failed
                          || !DECL_EXTERNAL (e->callee->symbol.decl)
+                         || node->alias
                          || before_inlining_p))
                    e->callee->reachable = true;
                  enqueue_cgraph_node (e->callee, &first);
@@ -659,6 +661,12 @@ cgraph_externally_visible_p (struct cgraph_node *node,
 bool
 varpool_externally_visible_p (struct varpool_node *vnode, bool aliased)
 {
+  /* Do not touch weakrefs; while they are not externally visible,
+     dropping their DECL_EXTERNAL flags confuse most
+     of code handling them.  */
+  if (vnode->alias && DECL_EXTERNAL (vnode->symbol.decl))
+    return true;
+
   if (!DECL_COMDAT (vnode->symbol.decl) && !TREE_PUBLIC (vnode->symbol.decl))
     return false;
 
@@ -700,7 +708,7 @@ varpool_externally_visible_p (struct varpool_node *vnode, bool aliased)
      is faster for dynamic linking.  Also this match logic hidding vtables
      from LTO symbol tables.  */
   if ((in_lto_p || flag_whole_program)
-      && !vnode->force_output
+      && !vnode->symbol.force_output
       && DECL_COMDAT (vnode->symbol.decl) && DECL_VIRTUAL_P (vnode->symbol.decl))
     return false;
 
@@ -776,8 +784,7 @@ function_and_variable_visibility (bool whole_program)
         {
          if (!node->analyzed)
            continue;
-         cgraph_mark_needed_node (node);
-         gcc_assert (node->needed);
+         cgraph_mark_force_output_node (node);
          pointer_set_insert (aliased_nodes, node);
          if (dump_file)
            fprintf (dump_file, "  node %s/%i",
@@ -786,6 +793,7 @@ function_and_variable_visibility (bool whole_program)
       else if ((vnode = varpool_node_for_asm (p->target)) != NULL
               && !DECL_EXTERNAL (vnode->symbol.decl))
         {
+         vnode->symbol.force_output = 1;
          varpool_mark_needed_node (vnode);
          gcc_assert (vnode->needed);
          pointer_set_insert (aliased_vnodes, vnode);
@@ -813,9 +821,9 @@ function_and_variable_visibility (bool whole_program)
       /* Frontends and alias code marks nodes as needed before parsing is finished.
         We may end up marking as node external nodes where this flag is meaningless
         strip it.  */
-      if (node->needed
+      if (node->symbol.force_output
          && (DECL_EXTERNAL (node->symbol.decl) || !node->analyzed))
-       node->needed = 0;
+       node->symbol.force_output = 0;
 
       /* C++ FE on lack of COMDAT support create local COMDAT functions
         (that ought to be shared but can not due to object format
@@ -1017,7 +1025,7 @@ whole_program_function_and_variable_visibility (void)
   FOR_EACH_DEFINED_FUNCTION (node)
     if ((node->symbol.externally_visible && !DECL_COMDAT (node->symbol.decl))
         && node->local.finalized)
-      cgraph_mark_needed_node (node);
+      cgraph_mark_reachable_node (node);
   FOR_EACH_DEFINED_VARIABLE (vnode)
     if (vnode->symbol.externally_visible && !DECL_COMDAT (vnode->symbol.decl))
       varpool_mark_needed_node (vnode);
index 6f75740..14eb423 100644 (file)
@@ -1,3 +1,7 @@
+2012-04-20  Jan Hubicka  <jh@suse.cz>
+
+       * class.c (make_local_function_alias): Do not mark symbol referenced.
+
 2012-04-11  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
 
        * jcf-dump.c (print_constant): Cast JPOOL_USHORT2, JPOOL_USHORT1
index 3c34aba..145bb63 100644 (file)
@@ -1407,7 +1407,6 @@ make_local_function_alias (tree method)
   DECL_INITIAL (alias) = error_mark_node;
   TREE_ADDRESSABLE (alias) = 1;
   TREE_USED (alias) = 1;
-  TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (alias)) = 1;
   if (!flag_syntax_only)
     assemble_alias (alias, DECL_ASSEMBLER_NAME (method));
   return alias;
index 18152a8..c0398b4 100644 (file)
@@ -503,7 +503,7 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
   bp_pack_value (&bp, node->local.versionable, 1);
   bp_pack_value (&bp, node->local.can_change_signature, 1);
   bp_pack_value (&bp, node->local.redefined_extern_inline, 1);
-  bp_pack_value (&bp, node->needed, 1);
+  bp_pack_value (&bp, node->symbol.force_output, 1);
   bp_pack_value (&bp, node->symbol.address_taken, 1);
   bp_pack_value (&bp, node->abstract_and_needed, 1);
   bp_pack_value (&bp, tag == LTO_cgraph_analyzed_node
@@ -566,7 +566,7 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node
   lto_output_var_decl_index (ob->decl_state, ob->main_stream, node->symbol.decl);
   bp = bitpack_create (ob->main_stream);
   bp_pack_value (&bp, node->symbol.externally_visible, 1);
-  bp_pack_value (&bp, node->force_output, 1);
+  bp_pack_value (&bp, node->symbol.force_output, 1);
   bp_pack_value (&bp, node->finalized, 1);
   bp_pack_value (&bp, node->alias, 1);
   bp_pack_value (&bp, node->alias_of != NULL, 1);
@@ -911,7 +911,7 @@ input_overwrite_node (struct lto_file_decl_data *file_data,
   node->local.versionable = bp_unpack_value (bp, 1);
   node->local.can_change_signature = bp_unpack_value (bp, 1);
   node->local.redefined_extern_inline = bp_unpack_value (bp, 1);
-  node->needed = bp_unpack_value (bp, 1);
+  node->symbol.force_output = bp_unpack_value (bp, 1);
   node->symbol.address_taken = bp_unpack_value (bp, 1);
   node->abstract_and_needed = bp_unpack_value (bp, 1);
   node->symbol.used_from_other_partition = bp_unpack_value (bp, 1);
@@ -1075,7 +1075,7 @@ input_varpool_node (struct lto_file_decl_data *file_data,
 
   bp = streamer_read_bitpack (ib);
   node->symbol.externally_visible = bp_unpack_value (&bp, 1);
-  node->force_output = bp_unpack_value (&bp, 1);
+  node->symbol.force_output = bp_unpack_value (&bp, 1);
   node->finalized = bp_unpack_value (&bp, 1);
   node->alias = bp_unpack_value (&bp, 1);
   non_null_aliasof = bp_unpack_value (&bp, 1);
index fa6a3dc..89850f0 100644 (file)
@@ -1456,7 +1456,7 @@ produce_symtab (struct output_block *ob,
         in the LTO symbol table to prevent linker from forcing them
         into the output. */
       if (DECL_COMDAT (vnode->symbol.decl)
-         && !vnode->force_output
+         && !vnode->symbol.force_output
          && vnode->finalized 
          && DECL_VIRTUAL_P (vnode->symbol.decl))
        continue;
@@ -1470,7 +1470,7 @@ produce_symtab (struct output_block *ob,
       if (!DECL_EXTERNAL (vnode->symbol.decl))
        continue;
       if (DECL_COMDAT (vnode->symbol.decl)
-         && !vnode->force_output
+         && !vnode->symbol.force_output
          && vnode->finalized 
          && DECL_VIRTUAL_P (vnode->symbol.decl))
        continue;
index bbb9d1b..ed8a651 100644 (file)
@@ -223,8 +223,8 @@ lto_cgraph_replace_node (struct cgraph_node *node,
     }
 
   /* Merge node flags.  */
-  if (node->needed)
-    cgraph_mark_needed_node (prevailing_node);
+  if (node->symbol.force_output)
+    cgraph_mark_force_output_node (prevailing_node);
   if (node->reachable)
     cgraph_mark_reachable_node (prevailing_node);
   if (node->symbol.address_taken)
index 96a8c97..6b86475 100644 (file)
@@ -1,3 +1,7 @@
+2012-04-20  Jan Hubicka  <jh@suse.cz>
+
+       * lto-partition.c (partition_cgraph_node_p): Use force_output.
+
 2012-04-18  Jan Hubicka  <jh@suse.cz>
 
        * lto-partition.c (add_references_to_partition, lto_balanced_map):
index 6fe672f..8287f8f 100644 (file)
@@ -269,6 +269,7 @@ partition_cgraph_node_p (struct cgraph_node *node)
   /* Extern inlines and comdat are always only in partitions they are needed.  */
   if (DECL_EXTERNAL (node->symbol.decl)
       || (DECL_COMDAT (node->symbol.decl)
+         && !node->symbol.force_output
          && !cgraph_used_from_object_file_p (node)))
     return false;
   if (lookup_attribute ("weakref", DECL_ATTRIBUTES (node->symbol.decl)))
@@ -287,7 +288,7 @@ partition_varpool_node_p (struct varpool_node *vnode)
   /* Constant pool and comdat are always only in partitions they are needed.  */
   if (DECL_IN_CONSTANT_POOL (vnode->symbol.decl)
       || (DECL_COMDAT (vnode->symbol.decl)
-         && !vnode->force_output
+         && !vnode->symbol.force_output
          && !varpool_used_from_object_file_p (vnode)))
     return false;
   if (lookup_attribute ("weakref", DECL_ATTRIBUTES (vnode->symbol.decl)))
index 32f7b1a..6fed845 100644 (file)
@@ -1,3 +1,8 @@
+2012-04-20  Jan Hubicka  <jh@suse.cz>
+
+       * objc-acct.c (mark_referenced_methods); Use
+       cgraph_mark_force_output_node.
+
 2012-03-21  Steven Bosscher  <steven@gcc.gnu.org>
 
        * objc-act (objc_build_ivar_assignment): Do not call assemble_external.
index 78a3cee..ec07971 100644 (file)
@@ -4625,7 +4625,7 @@ mark_referenced_methods (void)
       chain = CLASS_CLS_METHODS (impent->imp_context);
       while (chain)
        {
-         cgraph_mark_needed_node (
+         cgraph_mark_force_output_node (
                           cgraph_get_create_node (METHOD_DEFINITION (chain)));
          chain = DECL_CHAIN (chain);
        }
@@ -4633,7 +4633,7 @@ mark_referenced_methods (void)
       chain = CLASS_NST_METHODS (impent->imp_context);
       while (chain)
        {
-         cgraph_mark_needed_node (
+         cgraph_mark_force_output_node (
                           cgraph_get_create_node (METHOD_DEFINITION (chain)));
          chain = DECL_CHAIN (chain);
        }
index fadb4d7..ed5da15 100644 (file)
@@ -1865,7 +1865,7 @@ execute_todo (unsigned int flags)
   if ((flags & TODO_dump_symtab) && dump_file && !current_function_decl)
     {
       gcc_assert (!cfun);
-      dump_cgraph (dump_file);
+      dump_symtab (dump_file);
       /* Flush the file.  If verification fails, we won't be able to
         close the file before aborting.  */
       fflush (dump_file);
index 458075c..75078b0 100644 (file)
@@ -378,6 +378,8 @@ dump_symtab_base (FILE *f, symtab_node node)
     fprintf (f, " in_other_partition");
   if (node->symbol.used_from_other_partition)
     fprintf (f, " used_from_other_partition");
+  if (node->symbol.force_output)
+    fprintf (f, " force_output");
   if (node->symbol.resolution != LDPR_UNKNOWN)
     fprintf (f, " %s",
             ld_plugin_symbol_resolution_names[(int)node->symbol.resolution]);
index 2a43585..b1dd2a0 100644 (file)
@@ -4267,9 +4267,9 @@ tm_mangle (tree old_asm_id)
 }
 
 static inline void
-ipa_tm_mark_needed_node (struct cgraph_node *node)
+ipa_tm_mark_force_output_node (struct cgraph_node *node)
 {
-  cgraph_mark_needed_node (node);
+  cgraph_mark_force_output_node (node);
   /* ??? function_and_variable_visibility will reset
      the needed bit, without actually checking.  */
   node->analyzed = 1;
@@ -4328,8 +4328,8 @@ ipa_tm_create_version_alias (struct cgraph_node *node, void *data)
 
   record_tm_clone_pair (old_decl, new_decl);
 
-  if (info->old_node->needed)
-    ipa_tm_mark_needed_node (new_node);
+  if (info->old_node->symbol.force_output)
+    ipa_tm_mark_force_output_node (new_node);
   return false;
 }
 
@@ -4381,8 +4381,8 @@ ipa_tm_create_version (struct cgraph_node *old_node)
   record_tm_clone_pair (old_decl, new_decl);
 
   cgraph_call_function_insertion_hooks (new_node);
-  if (old_node->needed)
-    ipa_tm_mark_needed_node (new_node);
+  if (old_node->symbol.force_output)
+    ipa_tm_mark_force_output_node (new_node);
 
   /* Do the same thing, but for any aliases of the original node.  */
   {
index a385c21..d0710c0 100644 (file)
@@ -1755,7 +1755,7 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale,
                     producing dead clone (for further cloning).  In all
                     other cases we hit a bug (incorrect node sharing is the
                     most common reason for missing edges).  */
-                 gcc_assert (dest->needed || !dest->analyzed
+                 gcc_assert (!dest->analyzed
                              || dest->symbol.address_taken
                              || !id->src_node->analyzed
                              || !id->dst_node->analyzed);
index 28d2312..09642a0 100644 (file)
@@ -6928,7 +6928,7 @@ ipa_pta_execute (void)
         constraints for parameters.  */
       if (node->symbol.used_from_other_partition
          || node->symbol.externally_visible
-         || node->needed)
+         || node->symbol.force_output)
        {
          intra_create_variable_infos ();
 
index dbcb1bf..d506b31 100644 (file)
@@ -2249,7 +2249,7 @@ mark_decl_referenced (tree decl)
       struct cgraph_node *node = cgraph_get_create_node (decl);
       if (!DECL_EXTERNAL (decl)
          && !node->local.finalized)
-       cgraph_mark_needed_node (node);
+       cgraph_mark_force_output_node (node);
     }
   else if (TREE_CODE (decl) == VAR_DECL)
     {
@@ -2257,7 +2257,7 @@ mark_decl_referenced (tree decl)
       varpool_mark_needed_node (node);
       /* C++ frontend use mark_decl_references to force COMDAT variables
          to be output that might appear dead otherwise.  */
-      node->force_output = true;
+      node->symbol.force_output = true;
     }
   /* else do nothing - we can get various sorts of CST nodes here,
      which do not need to be marked.  */
@@ -5271,13 +5271,20 @@ weak_finish_1 (tree decl)
 #endif
 }
 
+/* Fiven an assembly name, find the decl it is associated with.  */
+static tree
+find_decl (tree target)
+{
+  symtab_node node = symtab_node_for_asm (target);
+  if (node)
+    return node->symbol.decl;
+  return NULL_TREE;
+}
+
 /* This TREE_LIST contains weakref targets.  */
 
 static GTY(()) tree weakref_targets;
 
-/* Forward declaration.  */
-static tree find_decl_and_mark_needed (tree decl, tree target);
-
 /* Emit any pending weak declarations.  */
 
 void
@@ -5303,7 +5310,7 @@ weak_finish (void)
 # if defined ASM_WEAKEN_LABEL && ! defined ASM_WEAKEN_DECL
          ASM_WEAKEN_LABEL (asm_out_file, IDENTIFIER_POINTER (target));
 # else
-         tree decl = find_decl_and_mark_needed (alias_decl, target);
+         tree decl = find_decl (target);
 
          if (! decl)
            {
@@ -5406,43 +5413,6 @@ globalize_decl (tree decl)
 
 VEC(alias_pair,gc) *alias_pairs;
 
-/* Given an assembly name, find the decl it is associated with.  At the
-   same time, mark it needed for cgraph.  */
-
-static tree
-find_decl_and_mark_needed (tree decl, tree target)
-{
-  struct cgraph_node *fnode = NULL;
-  struct varpool_node *vnode = NULL;
-
-  if (TREE_CODE (decl) == FUNCTION_DECL)
-    {
-      fnode = cgraph_node_for_asm (target);
-      if (fnode == NULL)
-       vnode = varpool_node_for_asm (target);
-    }
-  else
-    {
-      vnode = varpool_node_for_asm (target);
-      if (vnode == NULL)
-       fnode = cgraph_node_for_asm (target);
-    }
-
-  if (fnode)
-    {
-      cgraph_mark_needed_node (fnode);
-      return fnode->symbol.decl;
-    }
-  else if (vnode)
-    {
-      varpool_mark_needed_node (vnode);
-      vnode->force_output = 1;
-      return vnode->symbol.decl;
-    }
-  else
-    return NULL_TREE;
-}
-
 /* Output the assembler code for a define (equate) using ASM_OUTPUT_DEF
    or ASM_OUTPUT_DEF_FROM_DECLS.  The function defines the symbol whose
    tree node is DECL to have the value of the tree node TARGET.  */
@@ -5748,7 +5718,7 @@ finish_aliases_1 (void)
     {
       tree target_decl;
 
-      target_decl = find_decl_and_mark_needed (p->decl, p->target);
+      target_decl = find_decl (p->target);
       if (target_decl == NULL)
        {
          if (symbol_alias_set_contains (defined, p->target))
@@ -5854,7 +5824,7 @@ assemble_alias (tree decl, tree target)
   /* If the target has already been emitted, we don't have to queue the
      alias.  This saves a tad of memory.  */
   if (cgraph_global_info_ready)
-    target_decl = find_decl_and_mark_needed (decl, target);
+    target_decl = find_decl (target);
   else
     target_decl= NULL;
   if (target_decl && TREE_ASM_WRITTEN (target_decl))
@@ -5960,12 +5930,12 @@ dump_tm_clone_pairs (VEC(tm_alias_pair,heap) *tm_alias_pairs)
         TM_GETTMCLONE.  If neither of these are true, we didn't generate
         a clone, and we didn't call it indirectly... no sense keeping it
         in the clone table.  */
-      if (!dst_n || !dst_n->needed)
+      if (!dst_n || !dst_n->analyzed)
        continue;
 
       /* This covers the case where we have optimized the original
         function away, and only access the transactional clone.  */
-      if (!src_n || !src_n->needed)
+      if (!src_n || !src_n->analyzed)
        continue;
 
       if (!switched)
index 5748eff..2423ee8 100644 (file)
@@ -214,7 +214,7 @@ bool
 decide_is_variable_needed (struct varpool_node *node, tree decl)
 {
   /* If the user told us it is used, then it must be so.  */
-  if (node->force_output)
+  if (node->symbol.force_output)
     return true;
 
   gcc_assert (!DECL_EXTERNAL (decl));
@@ -298,7 +298,7 @@ varpool_finalize_decl (tree decl)
         optimizing and when not doing toplevel reoder.  */
       || (!flag_toplevel_reorder && !DECL_COMDAT (node->symbol.decl)
          && !DECL_ARTIFICIAL (node->symbol.decl)))
-    node->force_output = true;
+    node->symbol.force_output = true;
 
   if (decide_is_variable_needed (node, decl))
     varpool_mark_needed_node (node);
@@ -410,6 +410,7 @@ varpool_analyze_pending_decls (void)
                    }
                }
            }
+         varpool_mark_needed_node (tgt);
        }
       else if (DECL_INITIAL (decl))
        record_references_in_initializer (decl, analyzed);
@@ -621,8 +622,7 @@ varpool_create_variable_alias (tree alias, tree decl)
   gcc_assert (TREE_CODE (alias) == VAR_DECL);
   alias_node = varpool_node (alias);
   alias_node->alias = 1;
-  if (!DECL_EXTERNAL (alias))
-    alias_node->finalized = 1;
+  alias_node->finalized = 1;
   alias_node->alias_of = decl;
   if ((!DECL_EXTERNAL (alias)
        && decide_is_variable_needed (alias_node, alias))