This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Symtab cleanups 4/17
- From: Jan Hubicka <hubicka at ucw dot cz>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 5 Jun 2013 16:18:52 +0200
- Subject: 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 ----