ipa.c (cgraph_externally_visible_p): Handle externally visible and preserve flags...
authorJan Hubicka <jh@suse.cz>
Tue, 19 Oct 2010 00:12:07 +0000 (02:12 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Tue, 19 Oct 2010 00:12:07 +0000 (00:12 +0000)
* ipa.c (cgraph_externally_visible_p): Handle externally visible and
preserve flags before trying to guess on visibility.
(varpool_externally_visible_p): New function.
(function_and_variable_visibility): Use it.

From-SVN: r165669

gcc/ChangeLog
gcc/ipa.c

index edbf40a..9ee8309 100644 (file)
@@ -1,3 +1,10 @@
+2010-10-18  Jan Hubicka  <jh@suse.cz>
+
+       * ipa.c (cgraph_externally_visible_p): Handle externally visible and
+       preserve flags before trying to guess on visibility.
+       (varpool_externally_visible_p): New function.
+       (function_and_variable_visibility): Use it.
+
 2010-10-18  Nicola Pero  <nicola.pero@meta-innovation.com>
 
        Implemented parsing @synthesize and @dynamic for Objective-C.
index fccfb6a..7db27f3 100644 (file)
--- 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;