aboutsummaryrefslogtreecommitdiff
path: root/gcc/varasm.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/varasm.c')
-rw-r--r--gcc/varasm.c146
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.