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]

Symtab cleanups 4/17


Hi,
this patch deals with C++ keyed methods and explicit instantiations. Currently
C++ calls mark_used that ultimately sets force_output on the functions.  This
is equivalent to attribute ((used)) on the function/variable and it is bit too
strong.

For example at LTO time we can ignore the C++ ABI as long as we see all uses of
the symbols (i.e. we have resolution info and the symbol is hidden).

This patch thus implements specific flag forced_by_abi. used for this purpose
and cleanups the code dealing with it.  This affects abour 3800 symbols on Firefox
turning them to regular non-forced symbols. This allows bit more unreachable code
removal and optimization across these.

Bootstrapped/regtested x86_64-linux on ppc64-linux (in bit earlier version) as well
as tested on LTO Firefox, comitted.

Honza

	* class.c (emit_register_classes_in_jcr_section): Use DECL_PRESERVE_P
	instead of mark_decl_referenced.

	* decl2.c (maybe_make_one_only): Use forced_by_abi instad of
	mark_decl_referenced.
	(mark_needed): Likewise.

	* cgraph.c (cgraph_remove_node): Clear forced_by_abi.
	(cgraph_node_cannot_be_local_p_1): Honnor symbol.forced_by_abi
	and symtab_used_from_object_file_p.
	(cgraph_make_node_local_1): Clear forced_by_abi.
	(cgraph_can_remove_if_no_direct_calls_and): Use forced_by_abi
	* cgraph.h (symtab_node_base): Add forced_by_abi.
	(decide_is_variable_needed): Remove.
	(varpool_can_remove_if_no_refs): Honnor symbol.forced_by_abi.
	* cgraphunit.c (cgraph_decide_is_function_needed): Rename to ..
	(decide_is_symbol_needed): ... this one; handle symbols in general;
	always analyze virtuals; honnor forced_by_abi.
	(cgraph_finalize_function): Update.
	(varpool_finalize_decl): Update.
	(symbol_defined_and_needed): Remove.
	(analyze_functions): Update.
	* lto-cgraph.c (lto_output_node, lto_output_varpool_node,
	output_refs, input_overwrite_node): Handle forced_by_abi.
	* ipa.c (cgraph_address_taken_from_non_vtable_p): Rename to ...
	(address_taken_from_non_vtable_p): ... this one.
	(comdat_can_be_unshared_p_1): New function.
	(cgraph_comdat_can_be_unshared_p): Rename to ...
	(comdat_can_be_unshared_p): ... this one; handle symbols in general.
	(varpool_externally_visible_p): Use comdat_can_be_unshared_p.
	(function_and_variable_visibility): Clear forced_by_abi as needed.
	* trans-mem.c (ipa_tm_mark_forced_by_abi_node): New functoin.
	(ipa_tm_create_version_alias, ipa_tm_create_version): Update.
	* varasm.c (mark_decl_referenced): Remove.
	* symtab.c (dump_symtab_base): Dump forced_by_abi.
	* varpool.c (decide_is_variable_needed): Remove.
Index: java/class.c
===================================================================
*** java/class.c	(revision 199608)
--- java/class.c	(working copy)
*************** emit_register_classes_in_jcr_section (vo
*** 2814,2823 ****
    TREE_CONSTANT (cdecl) = 1;
    DECL_ARTIFICIAL (cdecl) = 1;
    DECL_IGNORED_P (cdecl) = 1;
    pushdecl_top_level (cdecl);
    relayout_decl (cdecl);
    rest_of_decl_compilation (cdecl, 1, 0);
-   mark_decl_referenced (cdecl);
  #else
    /* A target has defined TARGET_USE_JCR_SECTION,
       but doesn't have a JCR_SECTION_NAME.  */
--- 2814,2823 ----
    TREE_CONSTANT (cdecl) = 1;
    DECL_ARTIFICIAL (cdecl) = 1;
    DECL_IGNORED_P (cdecl) = 1;
+   DECL_PRESERVE_P (cdecl) = 1;
    pushdecl_top_level (cdecl);
    relayout_decl (cdecl);
    rest_of_decl_compilation (cdecl, 1, 0);
  #else
    /* A target has defined TARGET_USE_JCR_SECTION,
       but doesn't have a JCR_SECTION_NAME.  */
Index: cgraph.c
===================================================================
*** cgraph.c	(revision 199608)
--- cgraph.c	(working copy)
*************** cgraph_remove_node (struct cgraph_node *
*** 1326,1331 ****
--- 1326,1332 ----
    /* Incremental inlining access removed nodes stored in the postorder list.
       */
    node->symbol.force_output = false;
+   node->symbol.forced_by_abi = false;
    for (n = node->nested; n; n = n->next_nested)
      n->origin = NULL;
    node->nested = NULL;
*************** cgraph_node_cannot_be_local_p_1 (struct
*** 1712,1717 ****
--- 1713,1720 ----
  {
    return !(!node->symbol.force_output
  	   && ((DECL_COMDAT (node->symbol.decl)
+ 		&& !node->symbol.forced_by_abi
+ 	        && !symtab_used_from_object_file_p ((symtab_node) node)
  		&& !node->symbol.same_comdat_group)
  	       || !node->symbol.externally_visible));
  }
*************** cgraph_make_node_local_1 (struct cgraph_
*** 1804,1809 ****
--- 1807,1813 ----
        symtab_make_decl_local (node->symbol.decl);
  
        node->symbol.externally_visible = false;
+       node->symbol.forced_by_abi = false;
        node->local.local = true;
        node->symbol.unique_name = (node->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY
  				  || node->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY_EXP);
*************** cgraph_can_remove_if_no_direct_calls_and
*** 2085,2090 ****
--- 2089,2095 ----
    /* Only COMDAT functions can be removed if externally visible.  */
    if (node->symbol.externally_visible
        && (!DECL_COMDAT (node->symbol.decl)
+ 	  || node->symbol.forced_by_abi
  	  || symtab_used_from_object_file_p ((symtab_node) node)))
      return false;
    return true;
Index: cgraph.h
===================================================================
*** cgraph.h	(revision 199608)
--- cgraph.h	(working copy)
*************** struct GTY(()) symtab_node_base
*** 72,80 ****
  
    /* 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;
    /* True when the name is known to be unique and thus it does not need mangling.  */
    unsigned unique_name : 1;
  
--- 72,84 ----
  
    /* Set when function is visible by other units.  */
    unsigned externally_visible : 1;
!   /* The symbol will be assumed to be used in an invisiable way (like 
!      by an toplevel asm statement).  */
    unsigned force_output : 1;
+   /* Like FORCE_OUTPUT, but in the case it is ABI requiring the symbol to be
+      exported.  Unlike FORCE_OUTPUT this flag gets cleared to symbols promoted
+      to static and it does not inhibit optimization.  */
+   unsigned forced_by_abi : 1;
    /* True when the name is known to be unique and thus it does not need mangling.  */
    unsigned unique_name : 1;
  
*************** void dump_varpool (FILE *);
*** 775,781 ****
  void dump_varpool_node (FILE *, struct varpool_node *);
  
  void varpool_finalize_decl (tree);
- bool decide_is_variable_needed (struct varpool_node *, tree);
  enum availability cgraph_variable_initializer_availability (struct varpool_node *);
  void cgraph_make_node_local (struct cgraph_node *);
  bool cgraph_node_can_be_local_p (struct cgraph_node *);
--- 779,784 ----
*************** varpool_can_remove_if_no_refs (struct va
*** 1216,1221 ****
--- 1219,1225 ----
      return true;
    return (!node->symbol.force_output && !node->symbol.used_from_other_partition
    	  && ((DECL_COMDAT (node->symbol.decl)
+ 	       && !node->symbol.forced_by_abi
  	       && !symtab_used_from_object_file_p ((symtab_node) node))
  	      || !node->symbol.externally_visible
  	      || DECL_HAS_VALUE_EXPR_P (node->symbol.decl)));
Index: cgraphunit.c
===================================================================
*** cgraphunit.c	(revision 199608)
--- cgraphunit.c	(working copy)
*************** static GTY(()) struct asm_node *asm_last
*** 216,251 ****
  /* Used for vtable lookup in thunk adjusting.  */
  static GTY (()) tree vtable_entry_type;
  
! /* 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 unnecessary functions that can
!    take into account results of analysis, whole program info etc.  */
! 
! static 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.force_output)
!     return true;
  
    /* Double check that no one output the function into assembly file
       early.  */
    gcc_checking_assert (!DECL_ASSEMBLER_NAME_SET_P (decl)
  	               || !TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)));
  
  
!   /* 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.  */
  
!   if (TREE_PUBLIC (decl)
!       && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
      return true;
  
    return false;
--- 216,260 ----
  /* Used for vtable lookup in thunk adjusting.  */
  static GTY (()) tree vtable_entry_type;
  
! /* Determine if symbol DECL is needed.  That is, visible to something
!    either outside this translation unit, something magic in the system
!    configury */
! bool
! decide_is_symbol_needed (symtab_node node)
  {
!   tree decl = node->symbol.decl;
  
    /* Double check that no one output the function into assembly file
       early.  */
    gcc_checking_assert (!DECL_ASSEMBLER_NAME_SET_P (decl)
  	               || !TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)));
  
+   if (!node->symbol.definition)
+     return false;
  
!   /* Devirtualization may access these.  */
!   if (DECL_VIRTUAL_P (decl) && optimize)
!     return true;
  
!   if (DECL_EXTERNAL (decl))
!     return false;
  
!   /* If the user told us it is used, then it must be so.  */
!   if (node->symbol.force_output)
!     return true;
! 
!   /* ABI forced symbols are needed when they are external.  */
!   if (node->symbol.forced_by_abi && TREE_PUBLIC (decl))
!     return true;
! 
!  /* Keep constructors, destructors and virtual functions.  */
!    if (TREE_CODE (decl) == FUNCTION_DECL
!        && (DECL_STATIC_CONSTRUCTOR (decl) || DECL_STATIC_DESTRUCTOR (decl)))
!     return true;
! 
!   /* Externally visible variables must be output.  The exception is
!      COMDAT variables that must be output only when they are needed.  */
!   if (TREE_PUBLIC (decl) && !DECL_COMDAT (decl))
      return true;
  
    return false;
*************** cgraph_finalize_function (tree decl, boo
*** 447,453 ****
      ggc_collect ();
  
    if (cgraph_state == CGRAPH_STATE_CONSTRUCTION
!       && (cgraph_decide_is_function_needed (node, decl)
  	  || referred_to_p ((symtab_node)node)))
      enqueue_node ((symtab_node)node);
  }
--- 456,462 ----
      ggc_collect ();
  
    if (cgraph_state == CGRAPH_STATE_CONSTRUCTION
!       && (decide_is_symbol_needed ((symtab_node) node)
  	  || referred_to_p ((symtab_node)node)))
      enqueue_node ((symtab_node)node);
  }
*************** varpool_finalize_decl (tree decl)
*** 798,804 ****
      node->symbol.force_output = true;
  
    if (cgraph_state == CGRAPH_STATE_CONSTRUCTION
!       && (decide_is_variable_needed (node, decl)
  	  || referred_to_p ((symtab_node)node)))
      enqueue_node ((symtab_node)node);
    if (cgraph_state >= CGRAPH_STATE_IPA_SSA)
--- 807,813 ----
      node->symbol.force_output = true;
  
    if (cgraph_state == CGRAPH_STATE_CONSTRUCTION
!       && (decide_is_symbol_needed ((symtab_node) node)
  	  || referred_to_p ((symtab_node)node)))
      enqueue_node ((symtab_node)node);
    if (cgraph_state >= CGRAPH_STATE_IPA_SSA)
*************** varpool_finalize_decl (tree decl)
*** 810,830 ****
  }
  
  
- /* Determine if a symbol NODE is finalized and needed.  */
- 
- inline static bool
- symbol_defined_and_needed (symtab_node node)
- {
-   if (cgraph_node *cnode = dyn_cast <cgraph_node> (node))
-     return cnode->symbol.definition
- 	   && cgraph_decide_is_function_needed (cnode, cnode->symbol.decl);
-   if (varpool_node *vnode = dyn_cast <varpool_node> (node))
-     return vnode->symbol.definition
- 	   && !DECL_EXTERNAL (vnode->symbol.decl)
- 	   && decide_is_variable_needed (vnode, vnode->symbol.decl);
-   return false;
- }
- 
  /* Discover all functions and variables that are trivially needed, analyze
     them as well as all functions and variables referred by them  */
  
--- 819,824 ----
*************** analyze_functions (void)
*** 866,872 ****
  	   node != (symtab_node)first_analyzed
  	   && node != (symtab_node)first_analyzed_var; node = node->symbol.next)
  	{
! 	  if (symbol_defined_and_needed (node))
  	    {
  	      enqueue_node (node);
  	      if (!changed && cgraph_dump_file)
--- 860,866 ----
  	   node != (symtab_node)first_analyzed
  	   && node != (symtab_node)first_analyzed_var; node = node->symbol.next)
  	{
! 	  if (decide_is_symbol_needed (node))
  	    {
  	      enqueue_node (node);
  	      if (!changed && cgraph_dump_file)
Index: cp/decl2.c
===================================================================
*** cp/decl2.c	(revision 199608)
--- cp/decl2.c	(working copy)
*************** maybe_make_one_only (tree decl)
*** 1703,1711 ****
  
        if (VAR_P (decl))
  	{
  	  DECL_COMDAT (decl) = 1;
  	  /* Mark it needed so we don't forget to emit it.  */
! 	  mark_decl_referenced (decl);
  	  TREE_USED (decl) = 1;
  	}
      }
--- 1703,1712 ----
  
        if (VAR_P (decl))
  	{
+           struct varpool_node *node = varpool_node_for_decl (decl);
  	  DECL_COMDAT (decl) = 1;
  	  /* Mark it needed so we don't forget to emit it.  */
!           node->symbol.forced_by_abi = true;
  	  TREE_USED (decl) = 1;
  	}
      }
*************** void
*** 1813,1819 ****
  mark_needed (tree decl)
  {
    TREE_USED (decl) = 1;
!   mark_decl_referenced (decl);
  }
  
  /* DECL is either a FUNCTION_DECL or a VAR_DECL.  This function
--- 1814,1835 ----
  mark_needed (tree decl)
  {
    TREE_USED (decl) = 1;
!   if (TREE_CODE (decl) == FUNCTION_DECL)
!     {
!       /* Extern inline functions don't become needed when referenced.
! 	 If we know a method will be emitted in other TU and no new
! 	 functions can be marked reachable, just use the external
! 	 definition.  */
!       struct cgraph_node *node = cgraph_get_create_node (decl);
!       node->symbol.forced_by_abi = true;
!     }
!   else if (TREE_CODE (decl) == VAR_DECL)
!     {
!       struct varpool_node *node = varpool_node_for_decl (decl);
!       /* C++ frontend use mark_decl_references to force COMDAT variables
!          to be output that might appear dead otherwise.  */
!       node->symbol.forced_by_abi = true;
!     }
  }
  
  /* DECL is either a FUNCTION_DECL or a VAR_DECL.  This function
Index: lto-cgraph.c
===================================================================
*** lto-cgraph.c	(revision 199608)
--- lto-cgraph.c	(working copy)
*************** lto_output_node (struct lto_simple_outpu
*** 469,474 ****
--- 469,475 ----
    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->symbol.force_output, 1);
+   bp_pack_value (&bp, node->symbol.forced_by_abi, 1);
    bp_pack_value (&bp, node->symbol.unique_name, 1);
    bp_pack_value (&bp, node->symbol.address_taken, 1);
    bp_pack_value (&bp, node->abstract_and_needed, 1);
*************** lto_output_varpool_node (struct lto_simp
*** 527,532 ****
--- 528,534 ----
    bp = bitpack_create (ob->main_stream);
    bp_pack_value (&bp, node->symbol.externally_visible, 1);
    bp_pack_value (&bp, node->symbol.force_output, 1);
+   bp_pack_value (&bp, node->symbol.forced_by_abi, 1);
    bp_pack_value (&bp, node->symbol.unique_name, 1);
    bp_pack_value (&bp, node->symbol.definition, 1);
    alias_p = node->symbol.alias && (!boundary_p || DECL_EXTERNAL (node->symbol.decl));
*************** output_refs (lto_symtab_encoder_t encode
*** 672,678 ****
        count = ipa_ref_list_nreferences (&node->symbol.ref_list);
        if (count)
  	{
! 	  streamer_write_uhwi_stream (ob->main_stream, count);
  	  streamer_write_uhwi_stream (ob->main_stream,
  				     lto_symtab_encoder_lookup (encoder, node));
  	  for (i = 0; ipa_ref_list_reference_iterate (&node->symbol.ref_list,
--- 674,680 ----
        count = ipa_ref_list_nreferences (&node->symbol.ref_list);
        if (count)
  	{
! 	  streamer_write_gcov_count_stream (ob->main_stream, count);
  	  streamer_write_uhwi_stream (ob->main_stream,
  				     lto_symtab_encoder_lookup (encoder, node));
  	  for (i = 0; ipa_ref_list_reference_iterate (&node->symbol.ref_list,
*************** input_overwrite_node (struct lto_file_de
*** 881,886 ****
--- 883,889 ----
    node->local.can_change_signature = bp_unpack_value (bp, 1);
    node->local.redefined_extern_inline = bp_unpack_value (bp, 1);
    node->symbol.force_output = bp_unpack_value (bp, 1);
+   node->symbol.forced_by_abi = bp_unpack_value (bp, 1);
    node->symbol.unique_name = bp_unpack_value (bp, 1);
    node->symbol.address_taken = bp_unpack_value (bp, 1);
    node->abstract_and_needed = bp_unpack_value (bp, 1);
*************** input_varpool_node (struct lto_file_decl
*** 1039,1044 ****
--- 1042,1048 ----
    bp = streamer_read_bitpack (ib);
    node->symbol.externally_visible = bp_unpack_value (&bp, 1);
    node->symbol.force_output = bp_unpack_value (&bp, 1);
+   node->symbol.forced_by_abi = bp_unpack_value (&bp, 1);
    node->symbol.unique_name = bp_unpack_value (&bp, 1);
    node->symbol.definition = bp_unpack_value (&bp, 1);
    node->symbol.alias = bp_unpack_value (&bp, 1);
Index: ipa.c
===================================================================
*** ipa.c	(revision 199608)
--- ipa.c	(working copy)
*************** ipa_discover_readonly_nonaddressable_var
*** 515,521 ****
  
  /* Return true when there is a reference to node and it is not vtable.  */
  static bool
! cgraph_address_taken_from_non_vtable_p (struct cgraph_node *node)
  {
    int i;
    struct ipa_ref *ref;
--- 519,525 ----
  
  /* Return true when there is a reference to node and it is not vtable.  */
  static bool
! address_taken_from_non_vtable_p (symtab_node node)
  {
    int i;
    struct ipa_ref *ref;
*************** cgraph_address_taken_from_non_vtable_p (
*** 533,538 ****
--- 537,574 ----
    return false;
  }
  
+ /* A helper for comdat_can_be_unshared_p.  */
+ 
+ static bool
+ comdat_can_be_unshared_p_1 (symtab_node node)
+ {
+   /* When address is taken, we don't know if equality comparison won't
+      break eventaully. Exception are virutal functions and vtables, where
+      this is not possible by language standard.  */
+   if (!DECL_VIRTUAL_P (node->symbol.decl)
+       && address_taken_from_non_vtable_p (node))
+     return false;
+ 
+   /* If the symbol is used in some weird way, better to not touch it.  */
+   if (node->symbol.force_output)
+     return false;
+ 
+   /* Explicit instantiations needs to be output when possibly
+      used externally.  */
+   if (node->symbol.forced_by_abi
+       && TREE_PUBLIC (node->symbol.decl)
+       && (node->symbol.resolution != LDPR_PREVAILING_DEF_IRONLY
+           && !flag_whole_program))
+     return false;
+ 
+   /* Non-readonly and volatile variables can not be duplicated.  */
+   if (is_a <varpool_node> (node)
+       && (!TREE_READONLY (node->symbol.decl)
+ 	  || TREE_THIS_VOLATILE (node->symbol.decl)))
+     return false;
+   return true;
+ }
+ 
  /* COMDAT functions must be shared only if they have address taken,
     otherwise we can produce our own private implementation with
     -fwhole-program.  
*************** cgraph_address_taken_from_non_vtable_p (
*** 543,566 ****
     but in C++ there is no way to compare their addresses for equality.  */
  
  static bool
! cgraph_comdat_can_be_unshared_p (struct cgraph_node *node)
  {
!   if ((cgraph_address_taken_from_non_vtable_p (node)
!        && !DECL_VIRTUAL_P (node->symbol.decl))
!       || !node->symbol.definition)
      return false;
    if (node->symbol.same_comdat_group)
      {
!       struct cgraph_node *next;
  
        /* If more than one function is in the same COMDAT group, it must
           be shared even if just one function in the comdat group has
           address taken.  */
!       for (next = cgraph (node->symbol.same_comdat_group);
! 	   next != node; next = cgraph (next->symbol.same_comdat_group))
! 	if (cgraph_address_taken_from_non_vtable_p (next)
! 	    && !DECL_VIRTUAL_P (next->symbol.decl))
! 	  return false;
      }
    return true;
  }
--- 578,598 ----
     but in C++ there is no way to compare their addresses for equality.  */
  
  static bool
! comdat_can_be_unshared_p (symtab_node node)
  {
!   if (!comdat_can_be_unshared_p_1 (node))
      return false;
    if (node->symbol.same_comdat_group)
      {
!       symtab_node next;
  
        /* If more than one function is in the same COMDAT group, it must
           be shared even if just one function in the comdat group has
           address taken.  */
!       for (next = node->symbol.same_comdat_group;
! 	   next != node; next = next->symbol.same_comdat_group)
!         if (!comdat_can_be_unshared_p_1 (next))
!           return false;
      }
    return true;
  }
*************** cgraph_externally_visible_p (struct cgra
*** 606,612 ****
        implementing same COMDAT)  */
    if ((in_lto_p || whole_program)
        && DECL_COMDAT (node->symbol.decl)
!       && cgraph_comdat_can_be_unshared_p (node))
      return false;
  
    /* When doing link time optimizations, hidden symbols become local.  */
--- 638,644 ----
        implementing same COMDAT)  */
    if ((in_lto_p || whole_program)
        && DECL_COMDAT (node->symbol.decl)
!       && comdat_can_be_unshared_p ((symtab_node) node))
      return false;
  
    /* When doing link time optimizations, hidden symbols become local.  */
*************** varpool_externally_visible_p (struct var
*** 676,683 ****
       is faster for dynamic linking.  Also this match logic hidding vtables
       from LTO symbol tables.  */
    if ((in_lto_p || flag_whole_program)
!       && !vnode->symbol.force_output
!       && DECL_COMDAT (vnode->symbol.decl) && DECL_VIRTUAL_P (vnode->symbol.decl))
      return false;
  
    /* When doing link time optimizations, hidden symbols become local.  */
--- 708,715 ----
       is faster for dynamic linking.  Also this match logic hidding vtables
       from LTO symbol tables.  */
    if ((in_lto_p || flag_whole_program)
!       && DECL_COMDAT (vnode->symbol.decl)
!       && comdat_can_be_unshared_p ((symtab_node) vnode))
      return false;
  
    /* When doing link time optimizations, hidden symbols become local.  */
*************** function_and_variable_visibility (bool w
*** 739,747 ****
        /* 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->symbol.force_output
! 	  && (DECL_EXTERNAL (node->symbol.decl) || !node->symbol.definition))
! 	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
--- 771,781 ----
        /* 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 (DECL_EXTERNAL (node->symbol.decl) || !node->symbol.definition)
! 	{
! 	  node->symbol.force_output = 0;
! 	  node->symbol.forced_by_abi = 0;
! 	}
  
        /* C++ FE on lack of COMDAT support create local COMDAT functions
  	 (that ought to be shared but can not due to object format
*************** function_and_variable_visibility (bool w
*** 776,782 ****
  	  node->symbol.externally_visible = true;
  	}
        else
! 	node->symbol.externally_visible = false;
        if (!node->symbol.externally_visible && node->symbol.definition
  	  && !DECL_EXTERNAL (node->symbol.decl))
  	{
--- 810,819 ----
  	  node->symbol.externally_visible = true;
  	}
        else
! 	{
! 	  node->symbol.externally_visible = false;
! 	  node->symbol.forced_by_abi = false;
! 	}
        if (!node->symbol.externally_visible && node->symbol.definition
  	  && !DECL_EXTERNAL (node->symbol.decl))
  	{
*************** function_and_variable_visibility (bool w
*** 855,861 ****
        if (varpool_externally_visible_p (vnode))
  	vnode->symbol.externally_visible = true;
        else
!         vnode->symbol.externally_visible = false;
        if (!vnode->symbol.externally_visible)
  	{
  	  gcc_assert (in_lto_p || whole_program || !TREE_PUBLIC (vnode->symbol.decl));
--- 892,901 ----
        if (varpool_externally_visible_p (vnode))
  	vnode->symbol.externally_visible = true;
        else
! 	{
!           vnode->symbol.externally_visible = false;
! 	  vnode->symbol.forced_by_abi = false;
! 	}
        if (!vnode->symbol.externally_visible)
  	{
  	  gcc_assert (in_lto_p || whole_program || !TREE_PUBLIC (vnode->symbol.decl));
Index: trans-mem.c
===================================================================
*** trans-mem.c	(revision 199608)
--- trans-mem.c	(working copy)
*************** ipa_tm_mark_force_output_node (struct cg
*** 4681,4686 ****
--- 4681,4693 ----
    node->symbol.analyzed = true;
  }
  
+ static inline void
+ ipa_tm_mark_forced_by_abi_node (struct cgraph_node *node)
+ {
+   node->symbol.forced_by_abi = true;
+   node->symbol.analyzed = true;
+ }
+ 
  /* Callback data for ipa_tm_create_version_alias.  */
  struct create_version_alias_info
  {
*************** ipa_tm_create_version_alias (struct cgra
*** 4737,4742 ****
--- 4744,4751 ----
    if (info->old_node->symbol.force_output
        || ipa_ref_list_first_referring (&info->old_node->symbol.ref_list))
      ipa_tm_mark_force_output_node (new_node);
+   if (info->old_node->symbol.forced_by_abi)
+     ipa_tm_mark_forced_by_abi_node (new_node);
    return false;
  }
  
*************** ipa_tm_create_version (struct cgraph_nod
*** 4792,4797 ****
--- 4801,4808 ----
    if (old_node->symbol.force_output
        || ipa_ref_list_first_referring (&old_node->symbol.ref_list))
      ipa_tm_mark_force_output_node (new_node);
+   if (old_node->symbol.forced_by_abi)
+     ipa_tm_mark_forced_by_abi_node (new_node);
  
    /* Do the same thing, but for any aliases of the original node.  */
    {
Index: varasm.c
===================================================================
*** varasm.c	(revision 199608)
--- varasm.c	(working copy)
*************** mark_referenced (tree id)
*** 2244,2276 ****
    TREE_SYMBOL_REFERENCED (id) = 1;
  }
  
- /* Set the symbol_referenced flag for DECL and notify callgraph.  */
- void
- mark_decl_referenced (tree decl)
- {
-   if (TREE_CODE (decl) == FUNCTION_DECL)
-     {
-       /* Extern inline functions don't become needed when referenced.
- 	 If we know a method will be emitted in other TU and no new
- 	 functions can be marked reachable, just use the external
- 	 definition.  */
-       struct cgraph_node *node = cgraph_get_create_node (decl);
-       if (!DECL_EXTERNAL (decl)
- 	  && !node->symbol.definition)
- 	cgraph_mark_force_output_node (node);
-     }
-   else if (TREE_CODE (decl) == VAR_DECL)
-     {
-       struct varpool_node *node = varpool_node_for_decl (decl);
-       /* C++ frontend use mark_decl_references to force COMDAT variables
-          to be output that might appear dead otherwise.  */
-       node->symbol.force_output = true;
-     }
-   /* else do nothing - we can get various sorts of CST nodes here,
-      which do not need to be marked.  */
- }
- 
- 
  /* Follow the IDENTIFIER_TRANSPARENT_ALIAS chain starting at *ALIAS
     until we find an identifier that is not itself a transparent alias.
     Modify the alias passed to it by reference (and all aliases on the
--- 2244,2249 ----
Index: symtab.c
===================================================================
*** symtab.c	(revision 199608)
--- symtab.c	(working copy)
*************** dump_symtab_base (FILE *f, symtab_node n
*** 496,501 ****
--- 496,503 ----
      fprintf (f, " used_from_other_partition");
    if (node->symbol.force_output)
      fprintf (f, " force_output");
+   if (node->symbol.forced_by_abi)
+     fprintf (f, " forced_by_abi");
    if (node->symbol.resolution != LDPR_UNKNOWN)
      fprintf (f, " %s",
   	     ld_plugin_symbol_resolution_names[(int)node->symbol.resolution]);
Index: varpool.c
===================================================================
*** varpool.c	(revision 199608)
--- varpool.c	(working copy)
*************** varpool_node_for_asm (tree asmname)
*** 130,157 ****
      return NULL;
  }
  
- /* Determine if variable DECL is needed.  That is, visible to something
-    either outside this translation unit, something magic in the system
-    configury */
- bool
- decide_is_variable_needed (struct varpool_node *node, tree decl)
- {
-   if (DECL_EXTERNAL (decl))
-     return false;
- 
-   /* If the user told us it is used, then it must be so.  */
-   if (node->symbol.force_output)
-     return true;
- 
-   /* Externally visible variables must be output.  The exception is
-      COMDAT variables that must be output only when they are needed.  */
-   if (TREE_PUBLIC (decl)
-       && !DECL_COMDAT (decl))
-     return true;
- 
-   return false;
- }
- 
  /* Return if DECL is constant and its initial value is known (so we can do
     constant folding using DECL_INITIAL (decl)).  */
  
--- 130,135 ----


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