aboutsummaryrefslogtreecommitdiff
path: root/gcc/ipa.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ipa.c')
-rw-r--r--gcc/ipa.c88
1 files changed, 64 insertions, 24 deletions
diff --git a/gcc/ipa.c b/gcc/ipa.c
index fccfb6a..7db27f3 100644
--- a/gcc/ipa.c
+++ b/gcc/ipa.c
@@ -607,6 +607,11 @@ cgraph_externally_visible_p (struct cgraph_node *node, bool whole_program, bool
/* If linker counts on us, we must preserve the function. */
if (cgraph_used_from_object_file_p (node))
return true;
+ if (DECL_PRESERVE_P (node->decl))
+ return true;
+ if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (node->decl)))
+ return true;
+
/* When doing link time optimizations, hidden symbols become local. */
if (in_lto_p
&& (DECL_VISIBILITY (node->decl) == VISIBILITY_HIDDEN
@@ -638,11 +643,64 @@ cgraph_externally_visible_p (struct cgraph_node *node, bool whole_program, bool
return true;
}
}
- if (DECL_PRESERVE_P (node->decl))
- return true;
+
if (MAIN_NAME_P (DECL_NAME (node->decl)))
return true;
- if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (node->decl)))
+
+ return false;
+}
+
+/* Return true when variable VNODE should be considered externally visible. */
+
+static bool
+varpool_externally_visible_p (struct varpool_node *vnode, bool aliased)
+{
+ if (!DECL_COMDAT (vnode->decl) && !TREE_PUBLIC (vnode->decl))
+ return false;
+
+ /* Do not even try to be smart about aliased nodes. Until we properly
+ represent everything by same body alias, these are just evil. */
+ if (aliased)
+ return true;
+
+ /* If linker counts on us, we must preserve the function. */
+ if (varpool_used_from_object_file_p (vnode))
+ return true;
+
+ if (DECL_PRESERVE_P (vnode->decl))
+ return true;
+ if (lookup_attribute ("externally_visible",
+ DECL_ATTRIBUTES (vnode->decl)))
+ return true;
+
+ /* See if we have linker information about symbol not being used or
+ if we need to make guess based on the declaration.
+
+ Even if the linker clams the symbol is unused, never bring internal
+ symbols that are declared by user as used or externally visible.
+ This is needed for i.e. references from asm statements. */
+ if (varpool_used_from_object_file_p (vnode))
+ return true;
+
+ /* When doing link time optimizations, hidden symbols become local. */
+ if (in_lto_p
+ && (DECL_VISIBILITY (vnode->decl) == VISIBILITY_HIDDEN
+ || DECL_VISIBILITY (vnode->decl) == VISIBILITY_INTERNAL)
+ /* Be sure that node is defined in IR file, not in other object
+ file. In that case we don't set used_from_other_object_file. */
+ && vnode->finalized)
+ ;
+ else if (!flag_whole_program)
+ return true;
+
+ /* Do not attempt to privatize COMDATS by default.
+ This would break linking with C++ libraries sharing
+ inline definitions.
+
+ FIXME: We can do so for readonly vars with no address taken and
+ possibly also for vtables since no direct pointer comparsion is done.
+ It might be interesting to do so to reduce linking overhead. */
+ if (DECL_COMDAT (vnode->decl) || DECL_WEAK (vnode->decl))
return true;
return false;
}
@@ -798,27 +856,9 @@ function_and_variable_visibility (bool whole_program)
if (!vnode->finalized)
continue;
if (vnode->needed
- && (DECL_COMDAT (vnode->decl) || TREE_PUBLIC (vnode->decl))
- && (((!whole_program
- /* We can privatize comdat readonly variables whose address is
- not taken, but doing so is not going to bring us
- optimization oppurtunities until we start reordering
- datastructures. */
- || DECL_COMDAT (vnode->decl)
- || DECL_WEAK (vnode->decl))
- /* When doing linktime optimizations, all hidden symbols will
- become local. */
- && (!in_lto_p
- || (DECL_VISIBILITY (vnode->decl) != VISIBILITY_HIDDEN
- && DECL_VISIBILITY (vnode->decl) != VISIBILITY_INTERNAL)
- /* We can get prevailing decision in other object file.
- In this case we do not sed used_from_object_file. */
- || !vnode->finalized))
- || DECL_PRESERVE_P (vnode->decl)
- || varpool_used_from_object_file_p (vnode)
- || pointer_set_contains (aliased_vnodes, vnode)
- || lookup_attribute ("externally_visible",
- DECL_ATTRIBUTES (vnode->decl))))
+ && varpool_externally_visible_p
+ (vnode,
+ pointer_set_contains (aliased_vnodes, vnode)))
vnode->externally_visible = true;
else
vnode->externally_visible = false;