Commit 6649df51 by Jan Hubicka Committed by Jan Hubicka

lto-symtab.c (lto_symtab_resolve_symbols): Preffer decl with constructor over decl without.


	* lto-symtab.c (lto_symtab_resolve_symbols): Preffer decl with constructor
	over decl without.
	* cgraph.c (cgraph_remove_node): Clear also body of unanalyzed nodes.
	* cgraph.h (varpool_can_remove_if_no_refs): Handle external correctly.
	* cgraphunit.c (process_function_and_variable_attributes): Finalize 
	extrnal decls.
	(mark_functions_to_output): Also accept bodies for functions with clones.
	(output_in_order): Skip external vars.
	* lto-cgraph.c (lto_output_node): External functions are never in other
	partition.
	(lto_output_varpool_node): Likewise.
	* lto-streamer-out.c (lto_write_tree): Always use error_mark_nodes for
	forgotten initializers.
	* ipa.c (process_references): Handle external vars.
	(symtab_remove_unreachable_nodes): Update to handle external vars.
	(varpool_externally_visible_p): External vars are externally visible.
	* gimple-fold.c (can_refer_decl_in_current_unit_p): Update.
	* varpool.c (varpool_remove_node): Remove constructor.
	(decide_is_variable_needed): Handle externals.
	(varpool_remove_unreferenced_decls): Likewise.

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

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