mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-23 21:21:31 +08:00
re PR lto/45721 (ICE: in function_and_variable_visibility, at ipa.c:673 with -flto)
PR lto/45721 PR lto/45375 * tree.h (symbol_alias_set_t): Move typedef here from varasm.c (symbol_alias_set_destroy, symbol_alias_set_contains, propagate_aliases_backward): Declare. * lto-streamer-out.c (struct sets): New sturcture. (trivally_defined_alias): New function. (output_alias_pair_p): Rewrite. (output_unreferenced_globals): Fix output of alias pairs. (produce_symtab): Likewise. * ipa.c (function_and_variable_visibility): Set weak alias destination as needed in lto. * varasm.c (symbol_alias_set_t): Remove. (symbol_alias_set_destroy): Export. (propagate_aliases_forward, propagate_aliases_backward): New functions based on ... (compute_visible_aliases): ... this one; remove. (trivially_visible_alias): New (trivially_defined_alias): New. (remove_unreachable_alias_pairs): Rewrite. (finish_aliases_1): Reorganize code checking if alias is defined. * passes.c (rest_of_decl_compilation): Do not call assemble_alias when in LTO mode. * lto.c (partition_cgraph_node_p, partition_varpool_node_p): Weakrefs are not partitioned. * testsuite/gcc.dg/lto/pr45721_1.c: New file. * testsuite/gcc.dg/lto/pr45721_0.c: New file. From-SVN: r168666
This commit is contained in:
parent
1b24890758
commit
6e70182270
@ -1,3 +1,29 @@
|
||||
2011-01-11 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
PR lto/45721
|
||||
PR lto/45375
|
||||
* tree.h (symbol_alias_set_t): Move typedef here from varasm.c
|
||||
(symbol_alias_set_destroy, symbol_alias_set_contains,
|
||||
propagate_aliases_backward): Declare.
|
||||
* lto-streamer-out.c (struct sets): New sturcture.
|
||||
(trivally_defined_alias): New function.
|
||||
(output_alias_pair_p): Rewrite.
|
||||
(output_unreferenced_globals): Fix output of alias pairs.
|
||||
(produce_symtab): Likewise.
|
||||
* ipa.c (function_and_variable_visibility): Set weak alias destination
|
||||
as needed in lto.
|
||||
* varasm.c (symbol_alias_set_t): Remove.
|
||||
(symbol_alias_set_destroy): Export.
|
||||
(propagate_aliases_forward, propagate_aliases_backward): New functions
|
||||
based on ...
|
||||
(compute_visible_aliases): ... this one; remove.
|
||||
(trivially_visible_alias): New
|
||||
(trivially_defined_alias): New.
|
||||
(remove_unreachable_alias_pairs): Rewrite.
|
||||
(finish_aliases_1): Reorganize code checking if alias is defined.
|
||||
* passes.c (rest_of_decl_compilation): Do not call assemble_alias when
|
||||
in LTO mode.
|
||||
|
||||
2011-01-11 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
PR tree-optimization/46076
|
||||
|
@ -2007,6 +2007,13 @@ output_function (struct cgraph_node *node)
|
||||
}
|
||||
|
||||
|
||||
/* Used to pass data to trivally_defined_alias callback. */
|
||||
struct sets {
|
||||
cgraph_node_set set;
|
||||
varpool_node_set vset;
|
||||
};
|
||||
|
||||
|
||||
/* Return true if alias pair P belongs to the set of cgraph nodes in
|
||||
SET. If P is a an alias for a VAR_DECL, it can always be emitted.
|
||||
However, for FUNCTION_DECL aliases, we should only output the pair
|
||||
@ -2016,16 +2023,51 @@ output_function (struct cgraph_node *node)
|
||||
the file processed by LTRANS. */
|
||||
|
||||
static bool
|
||||
output_alias_pair_p (alias_pair *p, cgraph_node_set set, varpool_node_set vset)
|
||||
trivally_defined_alias (tree decl ATTRIBUTE_UNUSED,
|
||||
tree target, void *data)
|
||||
{
|
||||
if (TREE_CODE (p->decl) == VAR_DECL)
|
||||
return varpool_node_in_set_p (varpool_node_for_asm (p->target), vset);
|
||||
struct sets *set = (struct sets *) data;
|
||||
struct cgraph_node *fnode = NULL;
|
||||
struct varpool_node *vnode = NULL;
|
||||
|
||||
/* Check if the assembler name for P->TARGET has its cgraph node in SET. */
|
||||
gcc_assert (TREE_CODE (p->decl) == FUNCTION_DECL);
|
||||
return cgraph_node_in_set_p (cgraph_node_for_asm (p->target), set);
|
||||
fnode = cgraph_node_for_asm (target);
|
||||
if (fnode)
|
||||
return cgraph_node_in_set_p (fnode, set->set);
|
||||
vnode = varpool_node_for_asm (target);
|
||||
return vnode && varpool_node_in_set_p (vnode, set->vset);
|
||||
}
|
||||
|
||||
/* Return true if alias pair P should be output in the current
|
||||
partition contains cgrpah nodes SET and varpool nodes VSET.
|
||||
DEFINED is set of all aliases whose targets are defined in
|
||||
the partition.
|
||||
|
||||
Normal aliases are output when they are defined, while WEAKREF
|
||||
aliases are output when they are used. */
|
||||
|
||||
static bool
|
||||
output_alias_pair_p (alias_pair *p, symbol_alias_set_t *defined,
|
||||
cgraph_node_set set, varpool_node_set vset)
|
||||
{
|
||||
struct cgraph_node *node;
|
||||
struct varpool_node *vnode;
|
||||
|
||||
if (lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl)))
|
||||
{
|
||||
if (TREE_CODE (p->decl) == VAR_DECL)
|
||||
{
|
||||
vnode = varpool_get_node (p->decl);
|
||||
return (vnode
|
||||
&& referenced_from_this_partition_p (&vnode->ref_list, set, vset));
|
||||
}
|
||||
node = cgraph_get_node (p->decl);
|
||||
return (node
|
||||
&& (referenced_from_this_partition_p (&node->ref_list, set, vset)
|
||||
|| reachable_from_this_partition_p (node, set)));
|
||||
}
|
||||
else
|
||||
return symbol_alias_set_contains (defined, p->decl);
|
||||
}
|
||||
|
||||
/* Output any unreferenced global symbol defined in SET, alias pairs
|
||||
and labels. */
|
||||
@ -2037,6 +2079,11 @@ output_unreferenced_globals (cgraph_node_set set, varpool_node_set vset)
|
||||
alias_pair *p;
|
||||
unsigned i;
|
||||
struct varpool_node *vnode;
|
||||
symbol_alias_set_t *defined;
|
||||
struct sets setdata;
|
||||
|
||||
setdata.set = set;
|
||||
setdata.vset = vset;
|
||||
|
||||
ob = create_output_block (LTO_section_static_initializer);
|
||||
ob->cgraph_node = NULL;
|
||||
@ -2070,15 +2117,20 @@ output_unreferenced_globals (cgraph_node_set set, varpool_node_set vset)
|
||||
|
||||
output_zero (ob);
|
||||
|
||||
/* We really need to propagate in both directoins:
|
||||
for normal aliases we propagate from first defined alias to
|
||||
all aliases defined based on it. For weakrefs we propagate in
|
||||
the oposite direction. */
|
||||
defined = propagate_aliases_backward (trivally_defined_alias, &setdata);
|
||||
|
||||
/* Emit the alias pairs for the nodes in SET. */
|
||||
FOR_EACH_VEC_ELT (alias_pair, alias_pairs, i, p)
|
||||
{
|
||||
if (output_alias_pair_p (p, set, vset))
|
||||
{
|
||||
lto_output_tree_ref (ob, p->decl);
|
||||
lto_output_tree_ref (ob, p->target);
|
||||
}
|
||||
}
|
||||
if (output_alias_pair_p (p, defined, set, vset))
|
||||
{
|
||||
lto_output_tree_ref (ob, p->decl);
|
||||
lto_output_tree_ref (ob, p->target);
|
||||
}
|
||||
symbol_alias_set_destroy (defined);
|
||||
|
||||
output_zero (ob);
|
||||
|
||||
@ -2476,6 +2528,11 @@ produce_symtab (struct output_block *ob,
|
||||
lto_cgraph_encoder_t encoder = ob->decl_state->cgraph_node_encoder;
|
||||
int i;
|
||||
alias_pair *p;
|
||||
struct sets setdata;
|
||||
symbol_alias_set_t *defined;
|
||||
|
||||
setdata.set = set;
|
||||
setdata.vset = vset;
|
||||
|
||||
lto_begin_section (section_name, false);
|
||||
free (section_name);
|
||||
@ -2553,9 +2610,11 @@ produce_symtab (struct output_block *ob,
|
||||
}
|
||||
|
||||
/* Write all aliases. */
|
||||
defined = propagate_aliases_backward (trivally_defined_alias, &setdata);
|
||||
FOR_EACH_VEC_ELT (alias_pair, alias_pairs, i, p)
|
||||
if (output_alias_pair_p (p, set, vset))
|
||||
if (output_alias_pair_p (p, defined, set, vset))
|
||||
write_symbol (cache, &stream, p->decl, seen, true);
|
||||
symbol_alias_set_destroy (defined);
|
||||
|
||||
lto_write_stream (&stream);
|
||||
pointer_set_destroy (seen);
|
||||
|
@ -1,3 +1,10 @@
|
||||
2011-01-11 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
PR lto/45721
|
||||
PR lto/45375
|
||||
* lto.c (partition_cgraph_node_p, partition_varpool_node_p): Weakrefs are
|
||||
not partitioned.
|
||||
|
||||
2010-12-22 Nathan Froyd <froydnj@codesourcery.com>
|
||||
|
||||
* lto-lang.c (handle_nonnull_attribute, handle_sentinel_attribute):
|
||||
|
@ -837,6 +837,8 @@ partition_cgraph_node_p (struct cgraph_node *node)
|
||||
|| (DECL_COMDAT (node->decl)
|
||||
&& !cgraph_used_from_object_file_p (node)))
|
||||
return false;
|
||||
if (lookup_attribute ("weakref", DECL_ATTRIBUTES (node->decl)))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -854,6 +856,8 @@ partition_varpool_node_p (struct varpool_node *vnode)
|
||||
&& !vnode->force_output
|
||||
&& !varpool_used_from_object_file_p (vnode)))
|
||||
return false;
|
||||
if (lookup_attribute ("weakref", DECL_ATTRIBUTES (vnode->decl)))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -144,6 +144,7 @@ rest_of_decl_compilation (tree decl,
|
||||
{
|
||||
/* We deferred calling assemble_alias so that we could collect
|
||||
other attributes such as visibility. Emit the alias now. */
|
||||
if (!in_lto_p)
|
||||
{
|
||||
tree alias;
|
||||
alias = lookup_attribute ("alias", DECL_ATTRIBUTES (decl));
|
||||
|
@ -1,3 +1,10 @@
|
||||
2011-01-11 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
PR lto/45721
|
||||
PR lto/45375
|
||||
* testsuite/gcc.dg/lto/pr45721_1.c: New file.
|
||||
* testsuite/gcc.dg/lto/pr45721_0.c: New file.
|
||||
|
||||
2011-01-11 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
PR tree-optimization/46076
|
||||
|
8
gcc/testsuite/gcc.dg/lto/pr45721_0.c
Normal file
8
gcc/testsuite/gcc.dg/lto/pr45721_0.c
Normal file
@ -0,0 +1,8 @@
|
||||
/* { dg-lto-do assemble } */
|
||||
void baz(void) {}
|
||||
void *y = (void *)baz;
|
||||
int main () { return 0; }
|
||||
/* { dg-lto-do assemble } */
|
||||
void baz(void) {}
|
||||
void *y = (void *)baz;
|
||||
int main () { return 0; }
|
4
gcc/testsuite/gcc.dg/lto/pr45721_1.c
Normal file
4
gcc/testsuite/gcc.dg/lto/pr45721_1.c
Normal file
@ -0,0 +1,4 @@
|
||||
static void bar(void) __attribute__ ((weakref("baz")));
|
||||
void *x = (void *)bar;
|
||||
static void bar(void) __attribute__ ((weakref("baz")));
|
||||
void *x = (void *)bar;
|
12
gcc/tree.h
12
gcc/tree.h
@ -5389,6 +5389,18 @@ extern void remove_unreachable_alias_pairs (void);
|
||||
extern bool decl_replaceable_p (tree);
|
||||
extern bool decl_binds_to_current_def_p (tree);
|
||||
|
||||
/* Derived type for use by compute_visible_aliases and callers. A symbol
|
||||
alias set is a pointer set into which we enter IDENTIFIER_NODES bearing
|
||||
the canonicalised assembler-level symbol names corresponding to decls
|
||||
and their aliases. */
|
||||
typedef struct pointer_set_t symbol_alias_set_t;
|
||||
|
||||
extern void symbol_alias_set_destroy (symbol_alias_set_t *);
|
||||
extern int symbol_alias_set_contains (const symbol_alias_set_t *, tree);
|
||||
extern symbol_alias_set_t * propagate_aliases_backward (bool (*)
|
||||
(tree, tree, void *),
|
||||
void *);
|
||||
|
||||
/* In stmt.c */
|
||||
extern void expand_computed_goto (tree);
|
||||
extern bool parse_output_constraint (const char **, int, int, int,
|
||||
|
148
gcc/varasm.c
148
gcc/varasm.c
@ -5504,12 +5504,6 @@ do_assemble_alias (tree decl, tree target)
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Derived type for use by compute_visible_aliases and callers. A symbol
|
||||
alias set is a pointer set into which we enter IDENTIFIER_NODES bearing
|
||||
the canonicalised assembler-level symbol names corresponding to decls
|
||||
and their aliases. */
|
||||
|
||||
typedef struct pointer_set_t symbol_alias_set_t;
|
||||
|
||||
/* Allocate and construct a symbol alias set. */
|
||||
|
||||
@ -5521,7 +5515,7 @@ symbol_alias_set_create (void)
|
||||
|
||||
/* Destruct and free a symbol alias set. */
|
||||
|
||||
static void
|
||||
void
|
||||
symbol_alias_set_destroy (symbol_alias_set_t *aset)
|
||||
{
|
||||
pointer_set_destroy (aset);
|
||||
@ -5529,7 +5523,7 @@ symbol_alias_set_destroy (symbol_alias_set_t *aset)
|
||||
|
||||
/* Test if a symbol alias set contains a given name. */
|
||||
|
||||
static int
|
||||
int
|
||||
symbol_alias_set_contains (const symbol_alias_set_t *aset, tree t)
|
||||
{
|
||||
/* We accept either a DECL or an IDENTIFIER directly. */
|
||||
@ -5551,40 +5545,110 @@ symbol_alias_set_insert (symbol_alias_set_t *aset, tree t)
|
||||
return pointer_set_insert (aset, t);
|
||||
}
|
||||
|
||||
/* Compute the set of indentifier nodes that is generated by aliases
|
||||
whose targets are reachable. */
|
||||
/* IN_SET_P is a predicate function assuming to be taken
|
||||
alias_pair->decl, alias_pair->target and DATA arguments.
|
||||
|
||||
Compute set of aliases by including everything where TRIVIALLY_VISIBLE
|
||||
predeicate is true and propagate across aliases such that when
|
||||
alias DECL is included, its TARGET is included too. */
|
||||
|
||||
static symbol_alias_set_t *
|
||||
compute_visible_aliases (void)
|
||||
propagate_aliases_forward (bool (*in_set_p)
|
||||
(tree decl, tree target, void *data),
|
||||
void *data)
|
||||
{
|
||||
symbol_alias_set_t *visible;
|
||||
symbol_alias_set_t *set;
|
||||
unsigned i;
|
||||
alias_pair *p;
|
||||
bool changed;
|
||||
|
||||
/* We have to compute the set of visible nodes including aliases
|
||||
themselves. */
|
||||
visible = symbol_alias_set_create ();
|
||||
set = symbol_alias_set_create ();
|
||||
for (i = 0; VEC_iterate (alias_pair, alias_pairs, i, p); ++i)
|
||||
if (in_set_p (p->decl, p->target, data))
|
||||
symbol_alias_set_insert (set, p->decl);
|
||||
do
|
||||
{
|
||||
changed = false;
|
||||
for (i = 0; VEC_iterate (alias_pair, alias_pairs, i, p); ++i)
|
||||
{
|
||||
struct cgraph_node *fnode = NULL;
|
||||
struct varpool_node *vnode = NULL;
|
||||
|
||||
fnode = cgraph_node_for_asm (p->target);
|
||||
vnode = (fnode == NULL) ? varpool_node_for_asm (p->target) : NULL;
|
||||
if ((fnode
|
||||
|| vnode
|
||||
|| symbol_alias_set_contains (visible, p->target))
|
||||
&& !symbol_alias_set_insert (visible, p->decl))
|
||||
changed = true;
|
||||
}
|
||||
if (symbol_alias_set_contains (set, p->decl)
|
||||
&& !symbol_alias_set_insert (set, p->target))
|
||||
changed = true;
|
||||
}
|
||||
while (changed);
|
||||
|
||||
return visible;
|
||||
return set;
|
||||
}
|
||||
|
||||
/* Like propagate_aliases_forward but do backward propagation. */
|
||||
|
||||
symbol_alias_set_t *
|
||||
propagate_aliases_backward (bool (*in_set_p)
|
||||
(tree decl, tree target, void *data),
|
||||
void *data)
|
||||
{
|
||||
symbol_alias_set_t *set;
|
||||
unsigned i;
|
||||
alias_pair *p;
|
||||
bool changed;
|
||||
|
||||
/* We have to compute the set of set nodes including aliases
|
||||
themselves. */
|
||||
set = symbol_alias_set_create ();
|
||||
for (i = 0; VEC_iterate (alias_pair, alias_pairs, i, p); ++i)
|
||||
if (in_set_p (p->decl, p->target, data))
|
||||
symbol_alias_set_insert (set, p->target);
|
||||
do
|
||||
{
|
||||
changed = false;
|
||||
for (i = 0; VEC_iterate (alias_pair, alias_pairs, i, p); ++i)
|
||||
if (symbol_alias_set_contains (set, p->target)
|
||||
&& !symbol_alias_set_insert (set, p->decl))
|
||||
changed = true;
|
||||
}
|
||||
while (changed);
|
||||
|
||||
return set;
|
||||
}
|
||||
/* See if the alias is trivially visible. This means
|
||||
1) alias is expoerted from the unit or
|
||||
2) alias is used in the code.
|
||||
We assume that unused cgraph/varpool nodes has been
|
||||
removed.
|
||||
Used as callback for propagate_aliases. */
|
||||
|
||||
static bool
|
||||
trivially_visible_alias (tree decl, tree target ATTRIBUTE_UNUSED,
|
||||
void *data ATTRIBUTE_UNUSED)
|
||||
{
|
||||
struct cgraph_node *fnode = NULL;
|
||||
struct varpool_node *vnode = NULL;
|
||||
|
||||
if (!TREE_PUBLIC (decl))
|
||||
{
|
||||
if (TREE_CODE (decl) == FUNCTION_DECL)
|
||||
fnode = cgraph_get_node (decl);
|
||||
else
|
||||
vnode = varpool_get_node (decl);
|
||||
return vnode || fnode;
|
||||
}
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
/* See if the target of alias is defined in this unit.
|
||||
Used as callback for propagate_aliases. */
|
||||
|
||||
static bool
|
||||
trivially_defined_alias (tree decl ATTRIBUTE_UNUSED,
|
||||
tree target,
|
||||
void *data ATTRIBUTE_UNUSED)
|
||||
{
|
||||
struct cgraph_node *fnode = NULL;
|
||||
struct varpool_node *vnode = NULL;
|
||||
|
||||
fnode = cgraph_node_for_asm (target);
|
||||
vnode = (fnode == NULL) ? varpool_node_for_asm (target) : NULL;
|
||||
return (fnode && fnode->analyzed) || (vnode && vnode->finalized);
|
||||
}
|
||||
|
||||
/* Remove the alias pairing for functions that are no longer in the call
|
||||
@ -5602,23 +5666,15 @@ remove_unreachable_alias_pairs (void)
|
||||
|
||||
/* We have to compute the set of visible nodes including aliases
|
||||
themselves. */
|
||||
visible = compute_visible_aliases ();
|
||||
visible = propagate_aliases_forward (trivially_visible_alias, NULL);
|
||||
|
||||
for (i = 0; VEC_iterate (alias_pair, alias_pairs, i, p); )
|
||||
{
|
||||
if (!DECL_EXTERNAL (p->decl))
|
||||
if (!DECL_EXTERNAL (p->decl)
|
||||
&& !symbol_alias_set_contains (visible, p->decl))
|
||||
{
|
||||
struct cgraph_node *fnode = NULL;
|
||||
struct varpool_node *vnode = NULL;
|
||||
fnode = cgraph_node_for_asm (p->target);
|
||||
vnode = (fnode == NULL) ? varpool_node_for_asm (p->target) : NULL;
|
||||
if (!fnode
|
||||
&& !vnode
|
||||
&& !symbol_alias_set_contains (visible, p->target))
|
||||
{
|
||||
VEC_unordered_remove (alias_pair, alias_pairs, i);
|
||||
continue;
|
||||
}
|
||||
VEC_unordered_remove (alias_pair, alias_pairs, i);
|
||||
continue;
|
||||
}
|
||||
|
||||
i++;
|
||||
@ -5634,16 +5690,16 @@ remove_unreachable_alias_pairs (void)
|
||||
void
|
||||
finish_aliases_1 (void)
|
||||
{
|
||||
symbol_alias_set_t *visible;
|
||||
symbol_alias_set_t *defined;
|
||||
unsigned i;
|
||||
alias_pair *p;
|
||||
|
||||
if (alias_pairs == NULL)
|
||||
return;
|
||||
|
||||
/* We have to compute the set of visible nodes including aliases
|
||||
/* We have to compute the set of defined nodes including aliases
|
||||
themselves. */
|
||||
visible = compute_visible_aliases ();
|
||||
defined = propagate_aliases_backward (trivially_defined_alias, NULL);
|
||||
|
||||
FOR_EACH_VEC_ELT (alias_pair, alias_pairs, i, p)
|
||||
{
|
||||
@ -5652,7 +5708,7 @@ finish_aliases_1 (void)
|
||||
target_decl = find_decl_and_mark_needed (p->decl, p->target);
|
||||
if (target_decl == NULL)
|
||||
{
|
||||
if (symbol_alias_set_contains (visible, p->target))
|
||||
if (symbol_alias_set_contains (defined, p->target))
|
||||
continue;
|
||||
|
||||
if (! (p->emitted_diags & ALIAS_DIAG_TO_UNDEF)
|
||||
@ -5678,7 +5734,7 @@ finish_aliases_1 (void)
|
||||
}
|
||||
}
|
||||
|
||||
symbol_alias_set_destroy (visible);
|
||||
symbol_alias_set_destroy (defined);
|
||||
}
|
||||
|
||||
/* Second pass of completing pending aliases. Emit the actual assembly.
|
||||
|
Loading…
x
Reference in New Issue
Block a user