mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-24 16:30:53 +08:00
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
This commit is contained in:
parent
f9eead1f89
commit
6649df51ec
@ -1,3 +1,26 @@
|
||||
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>
|
||||
|
||||
* opts.c (common_handle_option): -pedantic-errors enables -Wpedantic.
|
||||
|
@ -1242,6 +1242,7 @@ cgraph_remove_node (struct cgraph_node *node)
|
||||
&& (cgraph_global_info_ready
|
||||
&& (TREE_ASM_WRITTEN (n->symbol.decl)
|
||||
|| DECL_EXTERNAL (n->symbol.decl)
|
||||
|| !n->analyzed
|
||||
|| n->symbol.in_other_partition))))
|
||||
cgraph_release_function_body (node);
|
||||
|
||||
|
@ -1123,11 +1123,12 @@ cgraph_only_called_directly_or_aliased_p (struct cgraph_node *node)
|
||||
static inline bool
|
||||
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
|
||||
&& (DECL_COMDAT (node->symbol.decl)
|
||||
|| !node->symbol.externally_visible
|
||||
|| DECL_HAS_VALUE_EXPR_P (node->symbol.decl)
|
||||
|| DECL_EXTERNAL (node->symbol.decl)));
|
||||
|| !node->symbol.externally_visible
|
||||
|| DECL_HAS_VALUE_EXPR_P (node->symbol.decl)));
|
||||
}
|
||||
|
||||
/* 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,
|
||||
vnode = varpool_next_variable (vnode))
|
||||
{
|
||||
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))
|
||||
vnode->symbol.force_output = true;
|
||||
else if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (decl)))
|
||||
@ -1161,6 +1165,8 @@ mark_functions_to_output (void)
|
||||
gcc_assert (node->global.inlined_to
|
||||
|| !gimple_has_body_p (decl)
|
||||
|| node->symbol.in_other_partition
|
||||
|| node->clones
|
||||
|| DECL_ARTIFICIAL (decl)
|
||||
|| DECL_EXTERNAL (decl));
|
||||
|
||||
}
|
||||
@ -1760,12 +1766,13 @@ output_in_order (void)
|
||||
}
|
||||
|
||||
FOR_EACH_DEFINED_VARIABLE (pv)
|
||||
{
|
||||
i = pv->symbol.order;
|
||||
gcc_assert (nodes[i].kind == ORDER_UNDEFINED);
|
||||
nodes[i].kind = ORDER_VAR;
|
||||
nodes[i].u.v = pv;
|
||||
}
|
||||
if (!DECL_EXTERNAL (pv->symbol.decl))
|
||||
{
|
||||
i = pv->symbol.order;
|
||||
gcc_assert (nodes[i].kind == ORDER_UNDEFINED);
|
||||
nodes[i].kind = ORDER_VAR;
|
||||
nodes[i].u.v = pv;
|
||||
}
|
||||
|
||||
for (pa = asm_nodes; pa; pa = pa->next)
|
||||
{
|
||||
|
@ -62,18 +62,11 @@ can_refer_decl_in_current_unit_p (tree decl)
|
||||
if (!TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
|
||||
return true;
|
||||
/* 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)
|
||||
&& TREE_CODE (decl) == VAR_DECL)
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
return lookup_attribute ("weakref", DECL_ATTRIBUTES (decl)) != NULL;
|
||||
/* When function is public, we always can introduce new reference.
|
||||
Exception are the COMDAT functions where introducing a direct
|
||||
reference imply need to include function body in the curren tunit. */
|
||||
|
29
gcc/ipa.c
29
gcc/ipa.c
@ -100,7 +100,10 @@ process_references (struct ipa_ref_list *list,
|
||||
{
|
||||
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);
|
||||
enqueue_node ((symtab_node) node, first, reachable);
|
||||
}
|
||||
@ -187,6 +190,12 @@ has_addr_references_p (struct cgraph_node *node,
|
||||
reshape callgraph and preserve body when offline copy of function or
|
||||
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
|
||||
to stay) and symbols that are in boundary (i.e. external symbols referenced
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
/* 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. */
|
||||
@ -347,7 +369,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
|
||||
changed = true;
|
||||
}
|
||||
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);
|
||||
node->analyzed = false;
|
||||
}
|
||||
@ -627,6 +649,9 @@ varpool_externally_visible_p (struct varpool_node *vnode, bool aliased)
|
||||
if (vnode->alias && DECL_EXTERNAL (vnode->symbol.decl))
|
||||
return true;
|
||||
|
||||
if (DECL_EXTERNAL (vnode->symbol.decl))
|
||||
return true;
|
||||
|
||||
if (!DECL_COMDAT (vnode->symbol.decl) && !TREE_PUBLIC (vnode->symbol.decl))
|
||||
return false;
|
||||
|
||||
|
@ -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
|
||||
translation units into SET during IPA-inlining. We make them as
|
||||
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.
|
||||
gcc_assert (!node->global.inlined_to);
|
||||
@ -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
|
||||
labels and share them across LTRANS partitions. */
|
||||
if (DECL_IN_CONSTANT_POOL (node->symbol.decl)
|
||||
&& !DECL_EXTERNAL (node->symbol.decl)
|
||||
&& !DECL_COMDAT (node->symbol.decl))
|
||||
{
|
||||
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
|
||||
bp_pack_value (&bp, node->analyzed
|
||||
&& referenced_from_other_partition_p (&node->symbol.ref_list,
|
||||
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);
|
||||
if (node->alias_of)
|
||||
|
@ -353,11 +353,10 @@ lto_write_tree (struct output_block *ob, tree expr, bool ref_p)
|
||||
|
||||
varpool_encoder = ob->decl_state->varpool_node_encoder;
|
||||
vnode = varpool_get_node (expr);
|
||||
if (!vnode)
|
||||
if (!vnode
|
||||
|| !lto_varpool_encoder_encode_initializer_p (varpool_encoder,
|
||||
vnode))
|
||||
initial = error_mark_node;
|
||||
else if (!lto_varpool_encoder_encode_initializer_p (varpool_encoder,
|
||||
vnode))
|
||||
initial = NULL;
|
||||
}
|
||||
|
||||
stream_write_tree (ob, initial, ref_p);
|
||||
|
@ -489,7 +489,21 @@ lto_symtab_resolve_symbols (void **slot)
|
||||
/* From variables that can prevail choose the largest one. */
|
||||
if (!prevailing
|
||||
|| 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;
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,9 @@
|
||||
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>
|
||||
|
||||
* 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)
|
||||
else
|
||||
if (symtab_variable_p (ref->referred)
|
||||
&& (DECL_COMDAT (ipa_ref_varpool_node (ref)->symbol.decl)
|
||||
|| DECL_EXTERNAL (ipa_ref_varpool_node (ref)->symbol.decl)
|
||||
|| (ref->use == IPA_REF_ALIAS
|
||||
&& lookup_attribute
|
||||
("weakref",
|
||||
@ -287,6 +288,7 @@ partition_varpool_node_p (struct varpool_node *vnode)
|
||||
return false;
|
||||
/* Constant pool and comdat are always only in partitions they are needed. */
|
||||
if (DECL_IN_CONSTANT_POOL (vnode->symbol.decl)
|
||||
|| DECL_EXTERNAL (vnode->symbol.decl)
|
||||
|| (DECL_COMDAT (vnode->symbol.decl)
|
||||
&& !vnode->symbol.force_output
|
||||
&& !symtab_used_from_object_file_p ((symtab_node) vnode)))
|
||||
@ -843,6 +845,7 @@ lto_promote_cross_file_statics (void)
|
||||
be made global. It is sensible to keep those ltrans local to
|
||||
allow better optimization. */
|
||||
if (!DECL_IN_CONSTANT_POOL (vnode->symbol.decl)
|
||||
&& !DECL_EXTERNAL (vnode->symbol.decl)
|
||||
&& !DECL_COMDAT (vnode->symbol.decl)
|
||||
&& !vnode->symbol.externally_visible && vnode->analyzed
|
||||
&& referenced_from_other_partition_p (&vnode->symbol.ref_list,
|
||||
@ -893,8 +896,11 @@ lto_promote_cross_file_statics (void)
|
||||
|
||||
/* Constant pool references use internal labels and thus
|
||||
cannot be made global. It is sensible to keep those
|
||||
ltrans local to allow better optimization. */
|
||||
if (DECL_IN_CONSTANT_POOL (v->symbol.decl))
|
||||
ltrans local to allow better optimization.
|
||||
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))
|
||||
VEC_safe_push (varpool_node_ptr, heap,
|
||||
|
@ -59,6 +59,14 @@ void
|
||||
varpool_remove_node (struct varpool_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);
|
||||
}
|
||||
|
||||
@ -118,17 +126,17 @@ varpool_node_for_asm (tree asmname)
|
||||
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;
|
||||
|
||||
gcc_assert (!DECL_EXTERNAL (decl));
|
||||
|
||||
/* 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)
|
||||
&& !DECL_EXTERNAL (decl))
|
||||
&& !DECL_COMDAT (decl))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
@ -348,7 +356,8 @@ varpool_remove_unreferenced_decls (void)
|
||||
&& (!varpool_can_remove_if_no_refs (node)
|
||||
/* We just expanded all function bodies. See if any of
|
||||
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);
|
||||
if (cgraph_dump_file)
|
||||
@ -372,6 +381,8 @@ varpool_remove_unreferenced_decls (void)
|
||||
}
|
||||
for (i = 0; ipa_ref_list_reference_iterate (&node->symbol.ref_list, i, ref); i++)
|
||||
if (symtab_variable_p (ref->referred)
|
||||
&& (!DECL_EXTERNAL (ref->referred->symbol.decl)
|
||||
|| varpool (ref->referred)->alias)
|
||||
&& varpool (ref->referred)->analyzed)
|
||||
enqueue_node (varpool (ref->referred), &first);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user