diff options
Diffstat (limited to 'gcc/varasm.c')
-rw-r--r-- | gcc/varasm.c | 146 |
1 files changed, 101 insertions, 45 deletions
diff --git a/gcc/varasm.c b/gcc/varasm.c index cc05c18..bbebd87 100644 --- a/gcc/varasm.c +++ b/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 + 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) + if (symbol_alias_set_contains (set, p->decl) + && !symbol_alias_set_insert (set, p->target)) + changed = true; + } + while (changed); + + 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. */ - 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->target); 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->target) + && !symbol_alias_set_insert (set, p->decl)) + changed = true; } while (changed); - return visible; + 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. |