This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Symbol table 14/many: remove rest of reachability code


Hi,
this patch removes remaining traces of the code handling needed and
reachability flags and replaces last use of it in cgraph_mark_reachable_node by
pointer set.  It is nice to have 60k of patch that essentially just removes
things.

Bootstrapped/regtested x86_64-linux, will commit it after rebuilding Mozilla.

Honza

	* lto-symtab.c (lto_cgraph_replace_node): Do not call
	mark_reahcable_node.
	* cgraph.c (cgraph_remove_node): Do not clear reachable.
	(cgraph_mark_reachable_node): Remove.
	(cgraph_mark_force_output_node): Do not set reachable.
	(dump_cgraph_node): Do not dump reachable.
	(cgraph_create_virtual_clone): Do not set reachable.
	* cgraph.h (cgraph_node): Remove reachable flag.
	(varpool_node): Remove reachable flag.
	(cgraph_mark_if_needed): Remove.
	(cgraph_mark_reachable_node): Remove.
	* tree-emutls.c (ipa_lower_emutls): Do not check
	reachable.
	* cgraphunit.c (cgraph_finalize_function): Do not mark node as
	reachable.
	(cgraph_add_new_function): Likewise.
	(cgraph_mark_if_needed): Remove.
	(cgraph_analyze_function): Do not set target as reachable.
	(process_function_and_variable_attributes): Do not care about dllexport.
	(cgraph_analyze_functions): Do not set reachable flags.
	(cgraph_mark_functions_to_output): Do not check reachability.
	(cgraph_copy_node_for_versioning): Do not set reachable flag.
	(dbxout_expand_expr): Update.
	* c-decl.c (merge_decls): Do not track changed externs.
	* ipa.c: Include pointer-set.h
	(enqueue_cgraph_node): Use reachable pointer set.
	(process_references): Likewise.
	(cgraph_remove_unreachable_nodes): Likewise.
	(whole_program_function_and_variable_visibility): Do not recompute reachable.
	* trans-mem.c (ipa_tm_execute): Do not check reachable flag.
Index: lto-symtab.c
===================================================================
*** lto-symtab.c	(revision 186687)
--- lto-symtab.c	(working copy)
*************** lto_cgraph_replace_node (struct cgraph_n
*** 225,232 ****
    /* Merge node flags.  */
    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)
      {
        gcc_assert (!prevailing_node->global.inlined_to);
--- 225,230 ----
Index: cgraph.c
===================================================================
*** cgraph.c	(revision 186687)
--- cgraph.c	(working copy)
*************** cgraph_remove_node (struct cgraph_node *
*** 1344,1350 ****
  
    /* Incremental inlining access removed nodes stored in the postorder list.
       */
!   node->symbol.force_output = node->reachable = false;
    for (n = node->nested; n; n = n->next_nested)
      n->origin = NULL;
    node->nested = NULL;
--- 1344,1350 ----
  
    /* Incremental inlining access removed nodes stored in the postorder list.
       */
!   node->symbol.force_output = false;
    for (n = node->nested; n; n = n->next_nested)
      n->origin = NULL;
    node->nested = NULL;
*************** cgraph_remove_node_and_inline_clones (st
*** 1472,1498 ****
    return found;
  }
  
- /* Notify finalize_compilation_unit that given node is reachable.  */
- 
- void
- cgraph_mark_reachable_node (struct cgraph_node *node)
- {
-   if (!node->reachable && node->local.finalized)
-     {
-       if (cgraph_global_info_ready)
-         {
- 	  /* Verify that function does not appear to be needed out of blue
- 	     during the optimization process.  This can happen for extern
- 	     inlines when bodies was removed after inlining.  */
- 	  gcc_assert ((node->analyzed || node->symbol.in_other_partition
- 		       || DECL_EXTERNAL (node->symbol.decl)));
- 	}
-       else
-         notice_global_symbol (node->symbol.decl);
-       node->reachable = 1;
-     }
- }
- 
  /* Likewise indicate that a node is needed, i.e. reachable via some
     external means.  */
  
--- 1472,1477 ----
*************** cgraph_mark_force_output_node (struct cg
*** 1501,1507 ****
  {
    node->symbol.force_output = 1;
    gcc_assert (!node->global.inlined_to);
-   cgraph_mark_reachable_node (node);
  }
  
  /* Likewise indicate that a node is having address taken.  */
--- 1480,1485 ----
*************** void
*** 1510,1516 ****
  cgraph_mark_address_taken_node (struct cgraph_node *node)
  {
    gcc_assert (!node->global.inlined_to);
-   cgraph_mark_reachable_node (node);
    /* FIXME: address_taken flag is used both as a shortcut for testing whether
       IPA_REF_ADDR reference exists (and thus it should be set on node
       representing alias we take address of) and as a test whether address
--- 1488,1493 ----
*************** dump_cgraph_node (FILE *f, struct cgraph
*** 1621,1628 ****
  	     (HOST_WIDEST_INT)node->count);
    if (node->origin)
      fprintf (f, " nested in: %s", cgraph_node_asm_name (node->origin));
-   else if (node->reachable)
-     fprintf (f, " reachable");
    if (gimple_has_body_p (node->symbol.decl))
      fprintf (f, " body");
    if (node->process)
--- 1598,1603 ----
*************** cgraph_create_virtual_clone (struct cgra
*** 2048,2054 ****
    new_node->symbol.externally_visible = 0;
    new_node->local.local = 1;
    new_node->lowered = true;
-   new_node->reachable = true;
  
    cgraph_call_node_duplication_hooks (old_node, new_node);
  
--- 2023,2028 ----
Index: cgraph.h
===================================================================
*** cgraph.h	(revision 186687)
--- cgraph.h	(working copy)
*************** struct GTY(()) cgraph_node {
*** 248,260 ****
    /* Set when decl is an abstract function pointed to by the
       ABSTRACT_DECL_ORIGIN of a reachable function.  */
    unsigned abstract_and_needed : 1;
-   /* Set when function is reachable by call from other function
-      that is either reachable or needed.
-      This flag is computed at original cgraph construction and then
-      updated in cgraph_remove_unreachable_nodes.  Note that after
-      cgraph_remove_unreachable_nodes cgraph still can contain unreachable
-      nodes when they are needed for virtual clone instantiation.  */
-   unsigned reachable : 1;
    /* Set once the function is lowered (i.e. its CFG is built).  */
    unsigned lowered : 1;
    /* Set once the function has been instantiated and its callee
--- 248,253 ----
*************** struct GTY(()) varpool_node {
*** 416,424 ****
    /* For aliases points to declaration DECL is alias of.  */
    tree alias_of;
  
-   /* Set when function must be output - it is externally visible
-      or its address is taken.  */
-   unsigned needed : 1;
    /* Set once the variable has been instantiated and its callee
       lists created.  */
    unsigned analyzed : 1;
--- 409,414 ----
*************** VEC (cgraph_edge_p, heap) * collect_call
*** 589,601 ****
  /* In cgraphunit.c  */
  extern FILE *cgraph_dump_file;
  void cgraph_finalize_function (tree, bool);
- 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_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);
  bool cgraph_preserve_function_body_p (struct cgraph_node *);
  void verify_cgraph (void);
--- 579,589 ----
Index: tree-emutls.c
===================================================================
*** tree-emutls.c	(revision 186686)
--- tree-emutls.c	(working copy)
*************** ipa_lower_emutls (void)
*** 791,797 ****
  
    /* Adjust all uses of TLS variables within the function bodies.  */
    FOR_EACH_DEFINED_FUNCTION (func)
!     if (func->reachable && func->lowered)
        lower_emutls_function_body (func);
  
    /* Generate the constructor for any COMMON control variables created.  */
--- 791,797 ----
  
    /* Adjust all uses of TLS variables within the function bodies.  */
    FOR_EACH_DEFINED_FUNCTION (func)
!     if (func->lowered)
        lower_emutls_function_body (func);
  
    /* Generate the constructor for any COMMON control variables created.  */
Index: cgraphunit.c
===================================================================
*** cgraphunit.c	(revision 186687)
--- cgraphunit.c	(working copy)
*************** cgraph_finalize_function (tree decl, boo
*** 362,370 ****
        && !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.  */
    if (!TREE_ASM_WRITTEN (decl))
      (*debug_hooks->deferred_inline_function) (decl);
--- 362,367 ----
*************** cgraph_add_new_function (tree fndecl, bo
*** 416,422 ****
  	node = cgraph_get_create_node (fndecl);
  	node->local.local = false;
  	node->local.finalized = true;
! 	node->reachable = node->symbol.force_output = true;
  	if (!lowered && cgraph_state == CGRAPH_STATE_EXPANSION)
  	  {
  	    push_cfun (DECL_STRUCT_FUNCTION (fndecl));
--- 413,419 ----
  	node = cgraph_get_create_node (fndecl);
  	node->local.local = false;
  	node->local.finalized = true;
! 	node->symbol.force_output = true;
  	if (!lowered && cgraph_state == CGRAPH_STATE_EXPANSION)
  	  {
  	    push_cfun (DECL_STRUCT_FUNCTION (fndecl));
*************** cgraph_add_new_function (tree fndecl, bo
*** 468,485 ****
      DECL_FUNCTION_PERSONALITY (fndecl) = lang_hooks.eh_personality ();
  }
  
- /* C99 extern inline keywords allow changing of declaration after function
-    has been finalized.  We need to re-decide if we want to mark the function as
-    needed then.   */
- 
- void
- 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_reachable_node (node);
- }
- 
  /* Return TRUE if NODE2 is equivalent to NODE or its clone.  */
  static bool
  clone_of_p (struct cgraph_node *node, struct cgraph_node *node2)
--- 465,470 ----
*************** cgraph_analyze_function (struct cgraph_n
*** 916,922 ****
        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);
--- 901,906 ----
*************** cgraph_analyze_function (struct cgraph_n
*** 952,962 ****
  		}
  	    }
  	}
-       cgraph_mark_reachable_node (cgraph_alias_aliased_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_reachable_node (node);
      }
    else if (node->thunk.thunk_p)
      {
--- 936,943 ----
*************** process_function_and_variable_attributes
*** 1078,1098 ****
        tree decl = node->symbol.decl;
        if (DECL_PRESERVE_P (decl))
  	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_reachable_node (node);
- 	}
        else if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (decl)))
  	{
  	  if (! TREE_PUBLIC (node->symbol.decl))
  	    warning_at (DECL_SOURCE_LOCATION (node->symbol.decl), OPT_Wattributes,
  			"%<externally_visible%>"
  			" attribute have effect only on public objects");
- 	  else if (node->local.finalized)
- 	    cgraph_mark_reachable_node (node);
  	}
        if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))
  	  && (node->local.finalized && !node->alias))
--- 1059,1070 ----
*************** cgraph_analyze_functions (void)
*** 1280,1290 ****
  		cgraph_analyze_function (cnode);
  
  	      for (edge = cnode->callees; edge; edge = edge->next_callee)
! 		{
! 		  cgraph_mark_reachable_node (edge->callee);
! 		  if (edge->callee->local.finalized)
! 		    enqueue_node ((symtab_node)edge->callee);
! 		}
  
  	      /* If decl is a clone of an abstract function, mark that abstract
  		 function so that we don't release its body. The DECL_INITIAL() of that
--- 1252,1259 ----
  		cgraph_analyze_function (cnode);
  
  	      for (edge = cnode->callees; edge; edge = edge->next_callee)
! 		if (edge->callee->local.finalized)
! 		  enqueue_node ((symtab_node)edge->callee);
  
  	      /* If decl is a clone of an abstract function, mark that abstract
  		 function so that we don't release its body. The DECL_INITIAL() of that
*************** cgraph_analyze_functions (void)
*** 1300,1308 ****
  	    }
  	  else if (symtab_variable_p (node)
  		   && varpool (node)->finalized)
! 	    {
! 	      varpool_analyze_node (varpool (node));
! 	    }
  
  	  if (node->symbol.same_comdat_group)
  	    {
--- 1269,1275 ----
  	    }
  	  else if (symtab_variable_p (node)
  		   && varpool (node)->finalized)
! 	    varpool_analyze_node (varpool (node));
  
  	  if (node->symbol.same_comdat_group)
  	    {
*************** cgraph_mark_functions_to_output (void)
*** 1479,1487 ****
  	  && !node->thunk.thunk_p
  	  && !node->alias
  	  && !node->global.inlined_to
- 	  && (!cgraph_only_called_directly_p (node)
- 	      || ((e || ipa_ref_has_aliases_p (&node->symbol.ref_list))
- 		  && node->reachable))
  	  && !TREE_ASM_WRITTEN (decl)
  	  && !DECL_EXTERNAL (decl))
  	{
--- 1446,1451 ----
*************** cgraph_expand_all_functions (void)
*** 2085,2091 ****
        node = order[i];
        if (node->process)
  	{
- 	  gcc_assert (node->reachable);
  	  node->process = 0;
  	  cgraph_expand_function (node);
  	}
--- 2049,2054 ----
*************** cgraph_copy_node_for_versioning (struct 
*** 2370,2376 ****
     new_version->local.local = old_version->analyzed;
     new_version->global = old_version->global;
     new_version->rtl = old_version->rtl;
-    new_version->reachable = true;
     new_version->count = old_version->count;
  
     for (e = old_version->callees; e; e=e->next_callee)
--- 2333,2338 ----
Index: dbxout.c
===================================================================
*** dbxout.c	(revision 186686)
--- dbxout.c	(working copy)
*************** dbxout_expand_expr (tree expr)
*** 2483,2489 ****
  	     return NULL, otherwise stabs might reference an undefined
  	     symbol.  */
  	  struct varpool_node *node = varpool_get_node (expr);
! 	  if (!node || !node->needed)
  	    return NULL;
  	}
        /* FALLTHRU */
--- 2483,2489 ----
  	     return NULL, otherwise stabs might reference an undefined
  	     symbol.  */
  	  struct varpool_node *node = varpool_get_node (expr);
! 	  if (!node || !node->analyzed)
  	    return NULL;
  	}
        /* FALLTHRU */
Index: c-decl.c
===================================================================
*** c-decl.c	(revision 186686)
--- c-decl.c	(working copy)
*************** merge_decls (tree newdecl, tree olddecl,
*** 2172,2178 ****
  			   && prototype_p (TREE_TYPE (newdecl)));
    bool old_is_prototype = (TREE_CODE (olddecl) == FUNCTION_DECL
  			   && prototype_p (TREE_TYPE (olddecl)));
-   bool extern_changed = false;
  
    /* For real parm decl following a forward decl, rechain the old decl
       in its new location and clear TREE_ASM_WRITTEN (it's not a
--- 2172,2177 ----
*************** merge_decls (tree newdecl, tree olddecl,
*** 2443,2450 ****
  	}
      }
  
-   extern_changed = DECL_EXTERNAL (olddecl) && !DECL_EXTERNAL (newdecl);
- 
    /* Merge the USED information.  */
    if (TREE_USED (olddecl))
      TREE_USED (newdecl) = 1;
--- 2442,2447 ----
*************** merge_decls (tree newdecl, tree olddecl,
*** 2506,2518 ****
  	  || (TREE_CODE (olddecl) == VAR_DECL
  	      && TREE_STATIC (olddecl))))
      make_decl_rtl (olddecl);
- 
-   /* If we changed a function from DECL_EXTERNAL to !DECL_EXTERNAL,
-      and the definition is coming from the old version, cgraph needs
-      to be called again.  */
-   if (extern_changed && !new_is_definition
-       && TREE_CODE (olddecl) == FUNCTION_DECL && DECL_INITIAL (olddecl))
-     cgraph_mark_if_needed (olddecl);
  }
  
  /* Handle when a new declaration NEWDECL has the same name as an old
--- 2503,2508 ----
Index: ipa.c
===================================================================
*** ipa.c	(revision 186687)
--- ipa.c	(working copy)
*************** along with GCC; see the file COPYING3.  
*** 32,37 ****
--- 32,38 ----
  #include "target.h"
  #include "tree-iterator.h"
  #include "ipa-utils.h"
+ #include "pointer-set.h"
  
  /* Look for all functions inlined to NODE and update their inlined_to pointers
     to INLINED_TO.  */
*************** update_inlined_to_pointer (struct cgraph
*** 57,70 ****
     reachable.  */
  
  static void
! enqueue_cgraph_node (struct cgraph_node *node, struct cgraph_node **first)
  {
    /* Node is still in queue; do nothing.  */
    if (node->symbol.aux && node->symbol.aux != (void *) 2)
      return;
    /* Node was already processed as unreachable, re-enqueue
       only if it became reachable now.  */
!   if (node->symbol.aux == (void *)2 && !node->reachable)
      return;
    node->symbol.aux = *first;
    *first = node;
--- 58,72 ----
     reachable.  */
  
  static void
! enqueue_cgraph_node (struct cgraph_node *node, struct cgraph_node **first,
! 		     pointer_set_t *reachable)
  {
    /* Node is still in queue; do nothing.  */
    if (node->symbol.aux && node->symbol.aux != (void *) 2)
      return;
    /* Node was already processed as unreachable, re-enqueue
       only if it became reachable now.  */
!   if (node->symbol.aux == (void *)2 && !pointer_set_contains (reachable, node))
      return;
    node->symbol.aux = *first;
    *first = node;
*************** static void
*** 85,91 ****
  process_references (struct ipa_ref_list *list,
  		    struct cgraph_node **first,
  		    struct varpool_node **first_varpool,
! 		    bool before_inlining_p)
  {
    int i;
    struct ipa_ref *ref;
--- 87,94 ----
  process_references (struct ipa_ref_list *list,
  		    struct cgraph_node **first,
  		    struct varpool_node **first_varpool,
! 		    bool before_inlining_p,
! 		    pointer_set_t *reachable)
  {
    int i;
    struct ipa_ref *ref;
*************** process_references (struct ipa_ref_list 
*** 94,115 ****
        if (symtab_function_p (ref->referred))
  	{
  	  struct cgraph_node *node = ipa_ref_node (ref);
! 	  if (!node->reachable
! 	      && node->analyzed
  	      && (!DECL_EXTERNAL (node->symbol.decl)
  		  || node->alias
  	          || before_inlining_p))
! 	    node->reachable = true;
! 	  enqueue_cgraph_node (node, first);
  	}
        else
  	{
  	  struct varpool_node *node = ipa_ref_varpool_node (ref);
! 	  if (!node->needed)
! 	    {
! 	      node->needed = true;
! 	      enqueue_varpool_node (node, first_varpool);
! 	    }
  	}
      }
  }
--- 97,114 ----
        if (symtab_function_p (ref->referred))
  	{
  	  struct cgraph_node *node = ipa_ref_node (ref);
! 	  if (node->analyzed
  	      && (!DECL_EXTERNAL (node->symbol.decl)
  		  || node->alias
  	          || before_inlining_p))
! 	    pointer_set_insert (reachable, node);
! 	  enqueue_cgraph_node (node, first, reachable);
  	}
        else
  	{
  	  struct varpool_node *node = ipa_ref_varpool_node (ref);
! 	  if (!pointer_set_insert (reachable, node))
! 	    enqueue_varpool_node (node, first_varpool);
  	}
      }
  }
*************** cgraph_remove_unreachable_nodes (bool be
*** 175,180 ****
--- 174,180 ----
    struct cgraph_node *node, *next;
    struct varpool_node *vnode, *vnext;
    bool changed = false;
+   pointer_set_t *reachable = pointer_set_create ();
  
  #ifdef ENABLE_CHECKING
    verify_symtab ();
*************** cgraph_remove_unreachable_nodes (bool be
*** 200,213 ****
  		&& (DECL_COMDAT (node->symbol.decl) || DECL_EXTERNAL (node->symbol.decl)))))
        {
          gcc_assert (!node->global.inlined_to);
! 	enqueue_cgraph_node (node, &first);
! 	node->reachable = true;
        }
      else
!       {
!         gcc_assert (!node->symbol.aux);
! 	node->reachable = false;
!       }
  
    /* Mark variables that are obviously needed.  */
    FOR_EACH_VARIABLE (vnode)
--- 200,210 ----
  		&& (DECL_COMDAT (node->symbol.decl) || DECL_EXTERNAL (node->symbol.decl)))))
        {
          gcc_assert (!node->global.inlined_to);
! 	enqueue_cgraph_node (node, &first, reachable);
! 	pointer_set_insert (reachable, node);
        }
      else
!       gcc_assert (!node->symbol.aux);
  
    /* Mark variables that are obviously needed.  */
    FOR_EACH_VARIABLE (vnode)
*************** cgraph_remove_unreachable_nodes (bool be
*** 215,225 ****
        if ((vnode->analyzed || vnode->symbol.force_output)
  	  && !varpool_can_remove_if_no_refs (vnode))
  	{
! 	  vnode->needed = true;
  	  enqueue_varpool_node (vnode, &first_varpool);
  	}
-       else
- 	vnode->needed = false;
      }
  
    /* Perform reachability analysis.  As a special case do not consider
--- 212,220 ----
        if ((vnode->analyzed || vnode->symbol.force_output)
  	  && !varpool_can_remove_if_no_refs (vnode))
  	{
! 	  pointer_set_insert (reachable, vnode);
  	  enqueue_varpool_node (vnode, &first_varpool);
  	}
      }
  
    /* Perform reachability analysis.  As a special case do not consider
*************** cgraph_remove_unreachable_nodes (bool be
*** 237,280 ****
  	  struct cgraph_edge *e;
  	  node = first;
  	  first = (struct cgraph_node *) first->symbol.aux;
! 	  if (!node->reachable)
  	    node->symbol.aux = (void *)2;
- 
  	  /* If we found this node reachable, first mark on the callees
  	     reachable too, unless they are direct calls to extern inline functions
  	     we decided to not inline.  */
! 	  if (node->reachable)
  	    {
  	      for (e = node->callees; e; e = e->next_callee)
  		{
! 		  if (!e->callee->reachable
! 		      && 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);
  		}
  	      process_references (&node->symbol.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 (node->symbol.same_comdat_group
! 	      && node->reachable
! 	      && !node->global.inlined_to)
! 	    {
! 	      for (next = cgraph (node->symbol.same_comdat_group);
! 		   next != node;
! 		   next = cgraph (next->symbol.same_comdat_group))
! 		if (!next->reachable)
! 		  {
! 		    next->reachable = true;
! 		    enqueue_cgraph_node (next, &first);
! 		  }
  	    }
  
  	  /* We can freely remove inline clones even if they are cloned, however if
--- 232,270 ----
  	  struct cgraph_edge *e;
  	  node = first;
  	  first = (struct cgraph_node *) first->symbol.aux;
! 	  if (!pointer_set_contains (reachable, node))
  	    node->symbol.aux = (void *)2;
  	  /* If we found this node reachable, first mark on the callees
  	     reachable too, unless they are direct calls to extern inline functions
  	     we decided to not inline.  */
! 	  else 
  	    {
  	      for (e = node->callees; e; e = e->next_callee)
  		{
! 		  if (node->analyzed
  		      && (!e->inline_failed
  			  || !DECL_EXTERNAL (e->callee->symbol.decl)
  			  || node->alias
  			  || before_inlining_p))
! 		    pointer_set_insert (reachable, e->callee);
! 		  enqueue_cgraph_node (e->callee, &first, reachable);
  		}
  	      process_references (&node->symbol.ref_list, &first,
! 				  &first_varpool, before_inlining_p,
! 				  reachable);
  
! 	      /* If any function in a comdat group is reachable, force
! 		 all other functions in the same comdat group to be
! 		 also reachable.  */
! 	      if (node->symbol.same_comdat_group
! 		  && !node->global.inlined_to)
! 		{
! 		  for (next = cgraph (node->symbol.same_comdat_group);
! 		       next != node;
! 		       next = cgraph (next->symbol.same_comdat_group))
! 		    if (!pointer_set_insert (reachable, next))
! 		      enqueue_cgraph_node (next, &first, reachable);
! 		}
  	    }
  
  	  /* We can freely remove inline clones even if they are cloned, however if
*************** cgraph_remove_unreachable_nodes (bool be
*** 286,294 ****
  	    {
  	      bool noninline = node->clone_of->symbol.decl != node->symbol.decl;
  	      node = node->clone_of;
! 	      if (noninline && !node->reachable && !node->symbol.aux)
  	      	{
! 		  enqueue_cgraph_node (node, &first);
  		  break;
  		}
  	    }
--- 276,284 ----
  	    {
  	      bool noninline = node->clone_of->symbol.decl != node->symbol.decl;
  	      node = node->clone_of;
! 	      if (noninline && !pointer_set_insert (reachable, node) && !node->symbol.aux)
  	      	{
! 		  enqueue_cgraph_node (node, &first, reachable);
  		  break;
  		}
  	    }
*************** cgraph_remove_unreachable_nodes (bool be
*** 299,305 ****
  	  first_varpool = (struct varpool_node *)first_varpool->symbol.aux;
  	  vnode->symbol.aux = NULL;
  	  process_references (&vnode->symbol.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.  */
--- 289,296 ----
  	  first_varpool = (struct varpool_node *)first_varpool->symbol.aux;
  	  vnode->symbol.aux = NULL;
  	  process_references (&vnode->symbol.ref_list, &first,
! 			      &first_varpool, before_inlining_p,
! 			      reachable);
  	  /* If any function in a comdat group is reachable, force
  	     all other functions in the same comdat group to be
  	     also reachable.  */
*************** cgraph_remove_unreachable_nodes (bool be
*** 309,319 ****
  	      for (next = varpool (vnode->symbol.same_comdat_group);
  		   next != vnode;
  		   next = varpool (next->symbol.same_comdat_group))
! 		if (!next->needed)
! 		  {
! 		    next->needed = true;
! 		    enqueue_varpool_node (next, &first_varpool);
! 		  }
  	    }
  	}
      }
--- 300,307 ----
  	      for (next = varpool (vnode->symbol.same_comdat_group);
  		   next != vnode;
  		   next = varpool (next->symbol.same_comdat_group))
! 		if (!pointer_set_insert (reachable, next))
! 		  enqueue_varpool_node (next, &first_varpool);
  	    }
  	}
      }
*************** cgraph_remove_unreachable_nodes (bool be
*** 330,336 ****
    for (node = cgraph_first_function (); node; node = next)
      {
        next = cgraph_next_function (node);
!       if (node->symbol.aux && !node->reachable)
          {
  	  cgraph_node_remove_callees (node);
  	  ipa_remove_all_references (&node->symbol.ref_list);
--- 318,324 ----
    for (node = cgraph_first_function (); node; node = next)
      {
        next = cgraph_next_function (node);
!       if (node->symbol.aux && !pointer_set_contains (reachable, node))
          {
  	  cgraph_node_remove_callees (node);
  	  ipa_remove_all_references (&node->symbol.ref_list);
*************** cgraph_remove_unreachable_nodes (bool be
*** 348,363 ****
  	    fprintf (file, " %s", cgraph_node_name (node));
  	  /* See if there is reachable caller.  */
  	  for (e = node->callers; e && !found; e = e->next_caller)
! 	    if (e->caller->reachable)
  	      found = true;
  	  for (i = 0; (ipa_ref_list_referring_iterate (&node->symbol.ref_list,
  						      i, ref)
  		       && !found); i++)
! 	    if (symtab_function_p (ref->referring)
! 		&& ipa_ref_referring_node (ref)->reachable)
! 	      found = true;
! 	    else if (symtab_variable_p (ref->referring)
! 		     && ipa_ref_referring_varpool_node (ref)->needed)
  	      found = true;
  
  	  /* If so, we need to keep node in the callgraph.  */
--- 336,347 ----
  	    fprintf (file, " %s", cgraph_node_name (node));
  	  /* See if there is reachable caller.  */
  	  for (e = node->callers; e && !found; e = e->next_caller)
! 	    if (pointer_set_contains (reachable, e->caller))
  	      found = true;
  	  for (i = 0; (ipa_ref_list_referring_iterate (&node->symbol.ref_list,
  						      i, ref)
  		       && !found); i++)
! 	    if (pointer_set_contains (reachable, ref->referring))
  	      found = true;
  
  	  /* If so, we need to keep node in the callgraph.  */
*************** cgraph_remove_unreachable_nodes (bool be
*** 426,432 ****
    for (vnode = varpool_first_variable (); vnode; vnode = vnext)
      {
        vnext = varpool_next_variable (vnode);
!       if (!vnode->needed)
          {
  	  if (file)
  	    fprintf (file, " %s", varpool_node_name (vnode));
--- 410,416 ----
    for (vnode = varpool_first_variable (); vnode; vnode = vnext)
      {
        vnext = varpool_next_variable (vnode);
!       if (!pointer_set_contains (reachable, vnode))
          {
  	  if (file)
  	    fprintf (file, " %s", varpool_node_name (vnode));
*************** cgraph_remove_unreachable_nodes (bool be
*** 471,476 ****
--- 455,461 ----
    /* Reclaim alias pairs for functions that have disappeared from the
       call graph.  */
    remove_unreachable_alias_pairs ();
+   pointer_set_destroy (reachable);
  
    return changed;
  }
*************** gate_whole_program_function_and_variable
*** 1010,1023 ****
  static unsigned int
  whole_program_function_and_variable_visibility (void)
  {
-   struct cgraph_node *node;
- 
    function_and_variable_visibility (flag_whole_program);
- 
-   FOR_EACH_DEFINED_FUNCTION (node)
-     if ((node->symbol.externally_visible && !DECL_COMDAT (node->symbol.decl))
-         && node->local.finalized)
-       cgraph_mark_reachable_node (node);
    if (optimize)
      ipa_discover_readonly_nonaddressable_vars ();
    return 0;
--- 995,1001 ----
Index: trans-mem.c
===================================================================
*** trans-mem.c	(revision 186686)
--- trans-mem.c	(working copy)
*************** ipa_tm_execute (void)
*** 4779,4785 ****
  
    /* For all local reachable functions...  */
    FOR_EACH_DEFINED_FUNCTION (node)
!     if (node->reachable && node->lowered
  	&& cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE)
        {
  	/* ... marked tm_pure, record that fact for the runtime by
--- 4779,4785 ----
  
    /* For all local reachable functions...  */
    FOR_EACH_DEFINED_FUNCTION (node)
!     if (node->lowered
  	&& cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE)
        {
  	/* ... marked tm_pure, record that fact for the runtime by
*************** ipa_tm_execute (void)
*** 4947,4953 ****
    /* Now validate all tm_safe functions, and all atomic regions in
       other functions.  */
    FOR_EACH_DEFINED_FUNCTION (node)
!     if (node->reachable && node->lowered
  	&& cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE)
        {
  	d = get_cg_data (&node, true);
--- 4947,4953 ----
    /* Now validate all tm_safe functions, and all atomic regions in
       other functions.  */
    FOR_EACH_DEFINED_FUNCTION (node)
!     if (node->lowered
  	&& cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE)
        {
  	d = get_cg_data (&node, true);
*************** ipa_tm_execute (void)
*** 4995,5001 ****
  	}
      }
    FOR_EACH_DEFINED_FUNCTION (node)
!     if (node->reachable && node->lowered
  	&& cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE)
        {
  	d = get_cg_data (&node, true);
--- 4995,5001 ----
  	}
      }
    FOR_EACH_DEFINED_FUNCTION (node)
!     if (node->lowered
  	&& cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE)
        {
  	d = get_cg_data (&node, true);
Index: lto-symtab.c
===================================================================
*** lto-symtab.c	(revision 186687)
--- lto-symtab.c	(working copy)
*************** lto_cgraph_replace_node (struct cgraph_n
*** 225,232 ****
    /* Merge node flags.  */
    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)
      {
        gcc_assert (!prevailing_node->global.inlined_to);
--- 225,230 ----
Index: cgraph.c
===================================================================
*** cgraph.c	(revision 186687)
--- cgraph.c	(working copy)
*************** cgraph_remove_node (struct cgraph_node *
*** 1344,1350 ****
  
    /* Incremental inlining access removed nodes stored in the postorder list.
       */
!   node->symbol.force_output = node->reachable = false;
    for (n = node->nested; n; n = n->next_nested)
      n->origin = NULL;
    node->nested = NULL;
--- 1344,1350 ----
  
    /* Incremental inlining access removed nodes stored in the postorder list.
       */
!   node->symbol.force_output = false;
    for (n = node->nested; n; n = n->next_nested)
      n->origin = NULL;
    node->nested = NULL;
*************** cgraph_remove_node_and_inline_clones (st
*** 1472,1498 ****
    return found;
  }
  
- /* Notify finalize_compilation_unit that given node is reachable.  */
- 
- void
- cgraph_mark_reachable_node (struct cgraph_node *node)
- {
-   if (!node->reachable && node->local.finalized)
-     {
-       if (cgraph_global_info_ready)
-         {
- 	  /* Verify that function does not appear to be needed out of blue
- 	     during the optimization process.  This can happen for extern
- 	     inlines when bodies was removed after inlining.  */
- 	  gcc_assert ((node->analyzed || node->symbol.in_other_partition
- 		       || DECL_EXTERNAL (node->symbol.decl)));
- 	}
-       else
-         notice_global_symbol (node->symbol.decl);
-       node->reachable = 1;
-     }
- }
- 
  /* Likewise indicate that a node is needed, i.e. reachable via some
     external means.  */
  
--- 1472,1477 ----
*************** cgraph_mark_force_output_node (struct cg
*** 1501,1507 ****
  {
    node->symbol.force_output = 1;
    gcc_assert (!node->global.inlined_to);
-   cgraph_mark_reachable_node (node);
  }
  
  /* Likewise indicate that a node is having address taken.  */
--- 1480,1485 ----
*************** void
*** 1510,1516 ****
  cgraph_mark_address_taken_node (struct cgraph_node *node)
  {
    gcc_assert (!node->global.inlined_to);
-   cgraph_mark_reachable_node (node);
    /* FIXME: address_taken flag is used both as a shortcut for testing whether
       IPA_REF_ADDR reference exists (and thus it should be set on node
       representing alias we take address of) and as a test whether address
--- 1488,1493 ----
*************** dump_cgraph_node (FILE *f, struct cgraph
*** 1621,1628 ****
  	     (HOST_WIDEST_INT)node->count);
    if (node->origin)
      fprintf (f, " nested in: %s", cgraph_node_asm_name (node->origin));
-   else if (node->reachable)
-     fprintf (f, " reachable");
    if (gimple_has_body_p (node->symbol.decl))
      fprintf (f, " body");
    if (node->process)
--- 1598,1603 ----
*************** cgraph_create_virtual_clone (struct cgra
*** 2048,2054 ****
    new_node->symbol.externally_visible = 0;
    new_node->local.local = 1;
    new_node->lowered = true;
-   new_node->reachable = true;
  
    cgraph_call_node_duplication_hooks (old_node, new_node);
  
--- 2023,2028 ----
Index: cgraph.h
===================================================================
*** cgraph.h	(revision 186687)
--- cgraph.h	(working copy)
*************** struct GTY(()) cgraph_node {
*** 248,260 ****
    /* Set when decl is an abstract function pointed to by the
       ABSTRACT_DECL_ORIGIN of a reachable function.  */
    unsigned abstract_and_needed : 1;
-   /* Set when function is reachable by call from other function
-      that is either reachable or needed.
-      This flag is computed at original cgraph construction and then
-      updated in cgraph_remove_unreachable_nodes.  Note that after
-      cgraph_remove_unreachable_nodes cgraph still can contain unreachable
-      nodes when they are needed for virtual clone instantiation.  */
-   unsigned reachable : 1;
    /* Set once the function is lowered (i.e. its CFG is built).  */
    unsigned lowered : 1;
    /* Set once the function has been instantiated and its callee
--- 248,253 ----
*************** struct GTY(()) varpool_node {
*** 416,424 ****
    /* For aliases points to declaration DECL is alias of.  */
    tree alias_of;
  
-   /* Set when function must be output - it is externally visible
-      or its address is taken.  */
-   unsigned needed : 1;
    /* Set once the variable has been instantiated and its callee
       lists created.  */
    unsigned analyzed : 1;
--- 409,414 ----
*************** VEC (cgraph_edge_p, heap) * collect_call
*** 589,601 ****
  /* In cgraphunit.c  */
  extern FILE *cgraph_dump_file;
  void cgraph_finalize_function (tree, bool);
- 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_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);
  bool cgraph_preserve_function_body_p (struct cgraph_node *);
  void verify_cgraph (void);
--- 579,589 ----
Index: tree-emutls.c
===================================================================
*** tree-emutls.c	(revision 186686)
--- tree-emutls.c	(working copy)
*************** ipa_lower_emutls (void)
*** 791,797 ****
  
    /* Adjust all uses of TLS variables within the function bodies.  */
    FOR_EACH_DEFINED_FUNCTION (func)
!     if (func->reachable && func->lowered)
        lower_emutls_function_body (func);
  
    /* Generate the constructor for any COMMON control variables created.  */
--- 791,797 ----
  
    /* Adjust all uses of TLS variables within the function bodies.  */
    FOR_EACH_DEFINED_FUNCTION (func)
!     if (func->lowered)
        lower_emutls_function_body (func);
  
    /* Generate the constructor for any COMMON control variables created.  */
Index: cgraphunit.c
===================================================================
*** cgraphunit.c	(revision 186687)
--- cgraphunit.c	(working copy)
*************** cgraph_finalize_function (tree decl, boo
*** 362,370 ****
        && !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.  */
    if (!TREE_ASM_WRITTEN (decl))
      (*debug_hooks->deferred_inline_function) (decl);
--- 362,367 ----
*************** cgraph_add_new_function (tree fndecl, bo
*** 416,422 ****
  	node = cgraph_get_create_node (fndecl);
  	node->local.local = false;
  	node->local.finalized = true;
! 	node->reachable = node->symbol.force_output = true;
  	if (!lowered && cgraph_state == CGRAPH_STATE_EXPANSION)
  	  {
  	    push_cfun (DECL_STRUCT_FUNCTION (fndecl));
--- 413,419 ----
  	node = cgraph_get_create_node (fndecl);
  	node->local.local = false;
  	node->local.finalized = true;
! 	node->symbol.force_output = true;
  	if (!lowered && cgraph_state == CGRAPH_STATE_EXPANSION)
  	  {
  	    push_cfun (DECL_STRUCT_FUNCTION (fndecl));
*************** cgraph_add_new_function (tree fndecl, bo
*** 468,485 ****
      DECL_FUNCTION_PERSONALITY (fndecl) = lang_hooks.eh_personality ();
  }
  
- /* C99 extern inline keywords allow changing of declaration after function
-    has been finalized.  We need to re-decide if we want to mark the function as
-    needed then.   */
- 
- void
- 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_reachable_node (node);
- }
- 
  /* Return TRUE if NODE2 is equivalent to NODE or its clone.  */
  static bool
  clone_of_p (struct cgraph_node *node, struct cgraph_node *node2)
--- 465,470 ----
*************** cgraph_analyze_function (struct cgraph_n
*** 916,922 ****
        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);
--- 901,906 ----
*************** cgraph_analyze_function (struct cgraph_n
*** 952,962 ****
  		}
  	    }
  	}
-       cgraph_mark_reachable_node (cgraph_alias_aliased_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_reachable_node (node);
      }
    else if (node->thunk.thunk_p)
      {
--- 936,943 ----
*************** process_function_and_variable_attributes
*** 1078,1098 ****
        tree decl = node->symbol.decl;
        if (DECL_PRESERVE_P (decl))
  	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_reachable_node (node);
- 	}
        else if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (decl)))
  	{
  	  if (! TREE_PUBLIC (node->symbol.decl))
  	    warning_at (DECL_SOURCE_LOCATION (node->symbol.decl), OPT_Wattributes,
  			"%<externally_visible%>"
  			" attribute have effect only on public objects");
- 	  else if (node->local.finalized)
- 	    cgraph_mark_reachable_node (node);
  	}
        if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))
  	  && (node->local.finalized && !node->alias))
--- 1059,1070 ----
*************** cgraph_analyze_functions (void)
*** 1280,1290 ****
  		cgraph_analyze_function (cnode);
  
  	      for (edge = cnode->callees; edge; edge = edge->next_callee)
! 		{
! 		  cgraph_mark_reachable_node (edge->callee);
! 		  if (edge->callee->local.finalized)
! 		    enqueue_node ((symtab_node)edge->callee);
! 		}
  
  	      /* If decl is a clone of an abstract function, mark that abstract
  		 function so that we don't release its body. The DECL_INITIAL() of that
--- 1252,1259 ----
  		cgraph_analyze_function (cnode);
  
  	      for (edge = cnode->callees; edge; edge = edge->next_callee)
! 		if (edge->callee->local.finalized)
! 		  enqueue_node ((symtab_node)edge->callee);
  
  	      /* If decl is a clone of an abstract function, mark that abstract
  		 function so that we don't release its body. The DECL_INITIAL() of that
*************** cgraph_analyze_functions (void)
*** 1300,1308 ****
  	    }
  	  else if (symtab_variable_p (node)
  		   && varpool (node)->finalized)
! 	    {
! 	      varpool_analyze_node (varpool (node));
! 	    }
  
  	  if (node->symbol.same_comdat_group)
  	    {
--- 1269,1275 ----
  	    }
  	  else if (symtab_variable_p (node)
  		   && varpool (node)->finalized)
! 	    varpool_analyze_node (varpool (node));
  
  	  if (node->symbol.same_comdat_group)
  	    {
*************** cgraph_mark_functions_to_output (void)
*** 1479,1487 ****
  	  && !node->thunk.thunk_p
  	  && !node->alias
  	  && !node->global.inlined_to
- 	  && (!cgraph_only_called_directly_p (node)
- 	      || ((e || ipa_ref_has_aliases_p (&node->symbol.ref_list))
- 		  && node->reachable))
  	  && !TREE_ASM_WRITTEN (decl)
  	  && !DECL_EXTERNAL (decl))
  	{
--- 1446,1451 ----
*************** cgraph_expand_all_functions (void)
*** 2085,2091 ****
        node = order[i];
        if (node->process)
  	{
- 	  gcc_assert (node->reachable);
  	  node->process = 0;
  	  cgraph_expand_function (node);
  	}
--- 2049,2054 ----
*************** cgraph_copy_node_for_versioning (struct 
*** 2370,2376 ****
     new_version->local.local = old_version->analyzed;
     new_version->global = old_version->global;
     new_version->rtl = old_version->rtl;
-    new_version->reachable = true;
     new_version->count = old_version->count;
  
     for (e = old_version->callees; e; e=e->next_callee)
--- 2333,2338 ----
Index: dbxout.c
===================================================================
*** dbxout.c	(revision 186686)
--- dbxout.c	(working copy)
*************** dbxout_expand_expr (tree expr)
*** 2483,2489 ****
  	     return NULL, otherwise stabs might reference an undefined
  	     symbol.  */
  	  struct varpool_node *node = varpool_get_node (expr);
! 	  if (!node || !node->needed)
  	    return NULL;
  	}
        /* FALLTHRU */
--- 2483,2489 ----
  	     return NULL, otherwise stabs might reference an undefined
  	     symbol.  */
  	  struct varpool_node *node = varpool_get_node (expr);
! 	  if (!node || !node->analyzed)
  	    return NULL;
  	}
        /* FALLTHRU */
Index: c-decl.c
===================================================================
*** c-decl.c	(revision 186686)
--- c-decl.c	(working copy)
*************** merge_decls (tree newdecl, tree olddecl,
*** 2172,2178 ****
  			   && prototype_p (TREE_TYPE (newdecl)));
    bool old_is_prototype = (TREE_CODE (olddecl) == FUNCTION_DECL
  			   && prototype_p (TREE_TYPE (olddecl)));
-   bool extern_changed = false;
  
    /* For real parm decl following a forward decl, rechain the old decl
       in its new location and clear TREE_ASM_WRITTEN (it's not a
--- 2172,2177 ----
*************** merge_decls (tree newdecl, tree olddecl,
*** 2443,2450 ****
  	}
      }
  
-   extern_changed = DECL_EXTERNAL (olddecl) && !DECL_EXTERNAL (newdecl);
- 
    /* Merge the USED information.  */
    if (TREE_USED (olddecl))
      TREE_USED (newdecl) = 1;
--- 2442,2447 ----
*************** merge_decls (tree newdecl, tree olddecl,
*** 2506,2518 ****
  	  || (TREE_CODE (olddecl) == VAR_DECL
  	      && TREE_STATIC (olddecl))))
      make_decl_rtl (olddecl);
- 
-   /* If we changed a function from DECL_EXTERNAL to !DECL_EXTERNAL,
-      and the definition is coming from the old version, cgraph needs
-      to be called again.  */
-   if (extern_changed && !new_is_definition
-       && TREE_CODE (olddecl) == FUNCTION_DECL && DECL_INITIAL (olddecl))
-     cgraph_mark_if_needed (olddecl);
  }
  
  /* Handle when a new declaration NEWDECL has the same name as an old
--- 2503,2508 ----
Index: ipa.c
===================================================================
*** ipa.c	(revision 186687)
--- ipa.c	(working copy)
*************** along with GCC; see the file COPYING3.  
*** 32,37 ****
--- 32,38 ----
  #include "target.h"
  #include "tree-iterator.h"
  #include "ipa-utils.h"
+ #include "pointer-set.h"
  
  /* Look for all functions inlined to NODE and update their inlined_to pointers
     to INLINED_TO.  */
*************** update_inlined_to_pointer (struct cgraph
*** 57,70 ****
     reachable.  */
  
  static void
! enqueue_cgraph_node (struct cgraph_node *node, struct cgraph_node **first)
  {
    /* Node is still in queue; do nothing.  */
    if (node->symbol.aux && node->symbol.aux != (void *) 2)
      return;
    /* Node was already processed as unreachable, re-enqueue
       only if it became reachable now.  */
!   if (node->symbol.aux == (void *)2 && !node->reachable)
      return;
    node->symbol.aux = *first;
    *first = node;
--- 58,72 ----
     reachable.  */
  
  static void
! enqueue_cgraph_node (struct cgraph_node *node, struct cgraph_node **first,
! 		     pointer_set_t *reachable)
  {
    /* Node is still in queue; do nothing.  */
    if (node->symbol.aux && node->symbol.aux != (void *) 2)
      return;
    /* Node was already processed as unreachable, re-enqueue
       only if it became reachable now.  */
!   if (node->symbol.aux == (void *)2 && !pointer_set_contains (reachable, node))
      return;
    node->symbol.aux = *first;
    *first = node;
*************** static void
*** 85,91 ****
  process_references (struct ipa_ref_list *list,
  		    struct cgraph_node **first,
  		    struct varpool_node **first_varpool,
! 		    bool before_inlining_p)
  {
    int i;
    struct ipa_ref *ref;
--- 87,94 ----
  process_references (struct ipa_ref_list *list,
  		    struct cgraph_node **first,
  		    struct varpool_node **first_varpool,
! 		    bool before_inlining_p,
! 		    pointer_set_t *reachable)
  {
    int i;
    struct ipa_ref *ref;
*************** process_references (struct ipa_ref_list 
*** 94,115 ****
        if (symtab_function_p (ref->referred))
  	{
  	  struct cgraph_node *node = ipa_ref_node (ref);
! 	  if (!node->reachable
! 	      && node->analyzed
  	      && (!DECL_EXTERNAL (node->symbol.decl)
  		  || node->alias
  	          || before_inlining_p))
! 	    node->reachable = true;
! 	  enqueue_cgraph_node (node, first);
  	}
        else
  	{
  	  struct varpool_node *node = ipa_ref_varpool_node (ref);
! 	  if (!node->needed)
! 	    {
! 	      node->needed = true;
! 	      enqueue_varpool_node (node, first_varpool);
! 	    }
  	}
      }
  }
--- 97,114 ----
        if (symtab_function_p (ref->referred))
  	{
  	  struct cgraph_node *node = ipa_ref_node (ref);
! 	  if (node->analyzed
  	      && (!DECL_EXTERNAL (node->symbol.decl)
  		  || node->alias
  	          || before_inlining_p))
! 	    pointer_set_insert (reachable, node);
! 	  enqueue_cgraph_node (node, first, reachable);
  	}
        else
  	{
  	  struct varpool_node *node = ipa_ref_varpool_node (ref);
! 	  if (!pointer_set_insert (reachable, node))
! 	    enqueue_varpool_node (node, first_varpool);
  	}
      }
  }
*************** cgraph_remove_unreachable_nodes (bool be
*** 175,180 ****
--- 174,180 ----
    struct cgraph_node *node, *next;
    struct varpool_node *vnode, *vnext;
    bool changed = false;
+   pointer_set_t *reachable = pointer_set_create ();
  
  #ifdef ENABLE_CHECKING
    verify_symtab ();
*************** cgraph_remove_unreachable_nodes (bool be
*** 200,213 ****
  		&& (DECL_COMDAT (node->symbol.decl) || DECL_EXTERNAL (node->symbol.decl)))))
        {
          gcc_assert (!node->global.inlined_to);
! 	enqueue_cgraph_node (node, &first);
! 	node->reachable = true;
        }
      else
!       {
!         gcc_assert (!node->symbol.aux);
! 	node->reachable = false;
!       }
  
    /* Mark variables that are obviously needed.  */
    FOR_EACH_VARIABLE (vnode)
--- 200,210 ----
  		&& (DECL_COMDAT (node->symbol.decl) || DECL_EXTERNAL (node->symbol.decl)))))
        {
          gcc_assert (!node->global.inlined_to);
! 	enqueue_cgraph_node (node, &first, reachable);
! 	pointer_set_insert (reachable, node);
        }
      else
!       gcc_assert (!node->symbol.aux);
  
    /* Mark variables that are obviously needed.  */
    FOR_EACH_VARIABLE (vnode)
*************** cgraph_remove_unreachable_nodes (bool be
*** 215,225 ****
        if ((vnode->analyzed || vnode->symbol.force_output)
  	  && !varpool_can_remove_if_no_refs (vnode))
  	{
! 	  vnode->needed = true;
  	  enqueue_varpool_node (vnode, &first_varpool);
  	}
-       else
- 	vnode->needed = false;
      }
  
    /* Perform reachability analysis.  As a special case do not consider
--- 212,220 ----
        if ((vnode->analyzed || vnode->symbol.force_output)
  	  && !varpool_can_remove_if_no_refs (vnode))
  	{
! 	  pointer_set_insert (reachable, vnode);
  	  enqueue_varpool_node (vnode, &first_varpool);
  	}
      }
  
    /* Perform reachability analysis.  As a special case do not consider
*************** cgraph_remove_unreachable_nodes (bool be
*** 237,280 ****
  	  struct cgraph_edge *e;
  	  node = first;
  	  first = (struct cgraph_node *) first->symbol.aux;
! 	  if (!node->reachable)
  	    node->symbol.aux = (void *)2;
- 
  	  /* If we found this node reachable, first mark on the callees
  	     reachable too, unless they are direct calls to extern inline functions
  	     we decided to not inline.  */
! 	  if (node->reachable)
  	    {
  	      for (e = node->callees; e; e = e->next_callee)
  		{
! 		  if (!e->callee->reachable
! 		      && 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);
  		}
  	      process_references (&node->symbol.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 (node->symbol.same_comdat_group
! 	      && node->reachable
! 	      && !node->global.inlined_to)
! 	    {
! 	      for (next = cgraph (node->symbol.same_comdat_group);
! 		   next != node;
! 		   next = cgraph (next->symbol.same_comdat_group))
! 		if (!next->reachable)
! 		  {
! 		    next->reachable = true;
! 		    enqueue_cgraph_node (next, &first);
! 		  }
  	    }
  
  	  /* We can freely remove inline clones even if they are cloned, however if
--- 232,270 ----
  	  struct cgraph_edge *e;
  	  node = first;
  	  first = (struct cgraph_node *) first->symbol.aux;
! 	  if (!pointer_set_contains (reachable, node))
  	    node->symbol.aux = (void *)2;
  	  /* If we found this node reachable, first mark on the callees
  	     reachable too, unless they are direct calls to extern inline functions
  	     we decided to not inline.  */
! 	  else 
  	    {
  	      for (e = node->callees; e; e = e->next_callee)
  		{
! 		  if (node->analyzed
  		      && (!e->inline_failed
  			  || !DECL_EXTERNAL (e->callee->symbol.decl)
  			  || node->alias
  			  || before_inlining_p))
! 		    pointer_set_insert (reachable, e->callee);
! 		  enqueue_cgraph_node (e->callee, &first, reachable);
  		}
  	      process_references (&node->symbol.ref_list, &first,
! 				  &first_varpool, before_inlining_p,
! 				  reachable);
  
! 	      /* If any function in a comdat group is reachable, force
! 		 all other functions in the same comdat group to be
! 		 also reachable.  */
! 	      if (node->symbol.same_comdat_group
! 		  && !node->global.inlined_to)
! 		{
! 		  for (next = cgraph (node->symbol.same_comdat_group);
! 		       next != node;
! 		       next = cgraph (next->symbol.same_comdat_group))
! 		    if (!pointer_set_insert (reachable, next))
! 		      enqueue_cgraph_node (next, &first, reachable);
! 		}
  	    }
  
  	  /* We can freely remove inline clones even if they are cloned, however if
*************** cgraph_remove_unreachable_nodes (bool be
*** 286,294 ****
  	    {
  	      bool noninline = node->clone_of->symbol.decl != node->symbol.decl;
  	      node = node->clone_of;
! 	      if (noninline && !node->reachable && !node->symbol.aux)
  	      	{
! 		  enqueue_cgraph_node (node, &first);
  		  break;
  		}
  	    }
--- 276,284 ----
  	    {
  	      bool noninline = node->clone_of->symbol.decl != node->symbol.decl;
  	      node = node->clone_of;
! 	      if (noninline && !pointer_set_insert (reachable, node) && !node->symbol.aux)
  	      	{
! 		  enqueue_cgraph_node (node, &first, reachable);
  		  break;
  		}
  	    }
*************** cgraph_remove_unreachable_nodes (bool be
*** 299,305 ****
  	  first_varpool = (struct varpool_node *)first_varpool->symbol.aux;
  	  vnode->symbol.aux = NULL;
  	  process_references (&vnode->symbol.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.  */
--- 289,296 ----
  	  first_varpool = (struct varpool_node *)first_varpool->symbol.aux;
  	  vnode->symbol.aux = NULL;
  	  process_references (&vnode->symbol.ref_list, &first,
! 			      &first_varpool, before_inlining_p,
! 			      reachable);
  	  /* If any function in a comdat group is reachable, force
  	     all other functions in the same comdat group to be
  	     also reachable.  */
*************** cgraph_remove_unreachable_nodes (bool be
*** 309,319 ****
  	      for (next = varpool (vnode->symbol.same_comdat_group);
  		   next != vnode;
  		   next = varpool (next->symbol.same_comdat_group))
! 		if (!next->needed)
! 		  {
! 		    next->needed = true;
! 		    enqueue_varpool_node (next, &first_varpool);
! 		  }
  	    }
  	}
      }
--- 300,307 ----
  	      for (next = varpool (vnode->symbol.same_comdat_group);
  		   next != vnode;
  		   next = varpool (next->symbol.same_comdat_group))
! 		if (!pointer_set_insert (reachable, next))
! 		  enqueue_varpool_node (next, &first_varpool);
  	    }
  	}
      }
*************** cgraph_remove_unreachable_nodes (bool be
*** 330,336 ****
    for (node = cgraph_first_function (); node; node = next)
      {
        next = cgraph_next_function (node);
!       if (node->symbol.aux && !node->reachable)
          {
  	  cgraph_node_remove_callees (node);
  	  ipa_remove_all_references (&node->symbol.ref_list);
--- 318,324 ----
    for (node = cgraph_first_function (); node; node = next)
      {
        next = cgraph_next_function (node);
!       if (node->symbol.aux && !pointer_set_contains (reachable, node))
          {
  	  cgraph_node_remove_callees (node);
  	  ipa_remove_all_references (&node->symbol.ref_list);
*************** cgraph_remove_unreachable_nodes (bool be
*** 348,363 ****
  	    fprintf (file, " %s", cgraph_node_name (node));
  	  /* See if there is reachable caller.  */
  	  for (e = node->callers; e && !found; e = e->next_caller)
! 	    if (e->caller->reachable)
  	      found = true;
  	  for (i = 0; (ipa_ref_list_referring_iterate (&node->symbol.ref_list,
  						      i, ref)
  		       && !found); i++)
! 	    if (symtab_function_p (ref->referring)
! 		&& ipa_ref_referring_node (ref)->reachable)
! 	      found = true;
! 	    else if (symtab_variable_p (ref->referring)
! 		     && ipa_ref_referring_varpool_node (ref)->needed)
  	      found = true;
  
  	  /* If so, we need to keep node in the callgraph.  */
--- 336,347 ----
  	    fprintf (file, " %s", cgraph_node_name (node));
  	  /* See if there is reachable caller.  */
  	  for (e = node->callers; e && !found; e = e->next_caller)
! 	    if (pointer_set_contains (reachable, e->caller))
  	      found = true;
  	  for (i = 0; (ipa_ref_list_referring_iterate (&node->symbol.ref_list,
  						      i, ref)
  		       && !found); i++)
! 	    if (pointer_set_contains (reachable, ref->referring))
  	      found = true;
  
  	  /* If so, we need to keep node in the callgraph.  */
*************** cgraph_remove_unreachable_nodes (bool be
*** 426,432 ****
    for (vnode = varpool_first_variable (); vnode; vnode = vnext)
      {
        vnext = varpool_next_variable (vnode);
!       if (!vnode->needed)
          {
  	  if (file)
  	    fprintf (file, " %s", varpool_node_name (vnode));
--- 410,416 ----
    for (vnode = varpool_first_variable (); vnode; vnode = vnext)
      {
        vnext = varpool_next_variable (vnode);
!       if (!pointer_set_contains (reachable, vnode))
          {
  	  if (file)
  	    fprintf (file, " %s", varpool_node_name (vnode));
*************** cgraph_remove_unreachable_nodes (bool be
*** 471,476 ****
--- 455,461 ----
    /* Reclaim alias pairs for functions that have disappeared from the
       call graph.  */
    remove_unreachable_alias_pairs ();
+   pointer_set_destroy (reachable);
  
    return changed;
  }
*************** gate_whole_program_function_and_variable
*** 1010,1023 ****
  static unsigned int
  whole_program_function_and_variable_visibility (void)
  {
-   struct cgraph_node *node;
- 
    function_and_variable_visibility (flag_whole_program);
- 
-   FOR_EACH_DEFINED_FUNCTION (node)
-     if ((node->symbol.externally_visible && !DECL_COMDAT (node->symbol.decl))
-         && node->local.finalized)
-       cgraph_mark_reachable_node (node);
    if (optimize)
      ipa_discover_readonly_nonaddressable_vars ();
    return 0;
--- 995,1001 ----
Index: trans-mem.c
===================================================================
*** trans-mem.c	(revision 186686)
--- trans-mem.c	(working copy)
*************** ipa_tm_execute (void)
*** 4779,4785 ****
  
    /* For all local reachable functions...  */
    FOR_EACH_DEFINED_FUNCTION (node)
!     if (node->reachable && node->lowered
  	&& cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE)
        {
  	/* ... marked tm_pure, record that fact for the runtime by
--- 4779,4785 ----
  
    /* For all local reachable functions...  */
    FOR_EACH_DEFINED_FUNCTION (node)
!     if (node->lowered
  	&& cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE)
        {
  	/* ... marked tm_pure, record that fact for the runtime by
*************** ipa_tm_execute (void)
*** 4947,4953 ****
    /* Now validate all tm_safe functions, and all atomic regions in
       other functions.  */
    FOR_EACH_DEFINED_FUNCTION (node)
!     if (node->reachable && node->lowered
  	&& cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE)
        {
  	d = get_cg_data (&node, true);
--- 4947,4953 ----
    /* Now validate all tm_safe functions, and all atomic regions in
       other functions.  */
    FOR_EACH_DEFINED_FUNCTION (node)
!     if (node->lowered
  	&& cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE)
        {
  	d = get_cg_data (&node, true);
*************** ipa_tm_execute (void)
*** 4995,5001 ****
  	}
      }
    FOR_EACH_DEFINED_FUNCTION (node)
!     if (node->reachable && node->lowered
  	&& cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE)
        {
  	d = get_cg_data (&node, true);
--- 4995,5001 ----
  	}
      }
    FOR_EACH_DEFINED_FUNCTION (node)
!     if (node->lowered
  	&& cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE)
        {
  	d = get_cg_data (&node, true);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]