OSDN Git Service

2010-10-08 Robert Dewar <dewar@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / ipa.c
index 48e331e..8eadd36 100644 (file)
--- a/gcc/ipa.c
+++ b/gcc/ipa.c
@@ -238,7 +238,12 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
 #endif
   varpool_reset_queue ();
   for (node = cgraph_nodes; node; node = node->next)
-    if (!cgraph_can_remove_if_no_direct_calls_and_refs_p (node)
+    if ((!cgraph_can_remove_if_no_direct_calls_and_refs_p (node)
+        /* Keep around virtual functions for possible devirtualization.  */
+        || (!before_inlining_p
+            && !node->global.inlined_to
+            && DECL_VIRTUAL_P (node->decl)
+            && (DECL_COMDAT (node->decl) || DECL_EXTERNAL (node->decl))))
        && ((!DECL_EXTERNAL (node->decl))
             || before_inlining_p))
       {
@@ -407,22 +412,26 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
                  if (!clone)
                    {
                      cgraph_release_function_body (node);
-                     node->analyzed = false;
                      node->local.inlinable = false;
+                     if (node->prev_sibling_clone)
+                       node->prev_sibling_clone->next_sibling_clone = node->next_sibling_clone;
+                     else if (node->clone_of)
+                       node->clone_of->clones = node->next_sibling_clone;
+                     if (node->next_sibling_clone)
+                       node->next_sibling_clone->prev_sibling_clone = node->prev_sibling_clone;
+#ifdef ENABLE_CHECKING
+                     if (node->clone_of)
+                       node->former_clone_of = node->clone_of->decl;
+#endif
+                     node->clone_of = NULL;
+                     node->next_sibling_clone = NULL;
+                     node->prev_sibling_clone = NULL;
                    }
                  else
                    gcc_assert (!clone->in_other_partition);
+                 node->analyzed = false;
                  cgraph_node_remove_callees (node);
                  ipa_remove_all_references (&node->ref_list);
-                 if (node->prev_sibling_clone)
-                   node->prev_sibling_clone->next_sibling_clone = node->next_sibling_clone;
-                 else if (node->clone_of)
-                   node->clone_of->clones = node->next_sibling_clone;
-                 if (node->next_sibling_clone)
-                   node->next_sibling_clone->prev_sibling_clone = node->prev_sibling_clone;
-                 node->clone_of = NULL;
-                 node->next_sibling_clone = NULL;
-                 node->prev_sibling_clone = NULL;
                }
              else
                cgraph_remove_node (node);
@@ -561,7 +570,6 @@ ipa_discover_readonly_nonaddressable_vars (void)
            if (dump_file)
              fprintf (dump_file, " %s (read-only)", varpool_node_name (vnode));
            TREE_READONLY (vnode->decl) = 1;
-           vnode->const_value_known |= varpool_decide_const_value_known (vnode);
          }
       }
   if (dump_file)
@@ -584,8 +592,13 @@ cgraph_externally_visible_p (struct cgraph_node *node, bool whole_program, bool
   if (aliased)
     return true;
 
+  /* If linker counts on us, we must preserve the function.  */
+  if (cgraph_used_from_object_file_p (node))
+    return true;
   /* When doing link time optimizations, hidden symbols become local.  */
-  if (in_lto_p && DECL_VISIBILITY (node->decl) == VISIBILITY_HIDDEN
+  if (in_lto_p
+      && (DECL_VISIBILITY (node->decl) == VISIBILITY_HIDDEN
+         || DECL_VISIBILITY (node->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.  */
       && node->analyzed)
@@ -613,8 +626,6 @@ cgraph_externally_visible_p (struct cgraph_node *node, bool whole_program, bool
              return true;
        }
     }
-  if (node->local.used_from_object_file)
-    return true;
   if (DECL_PRESERVE_P (node->decl))
     return true;
   if (MAIN_NAME_P (DECL_NAME (node->decl)))
@@ -730,6 +741,7 @@ function_and_variable_visibility (bool whole_program)
           struct cgraph_node *alias;
          gcc_assert (whole_program || in_lto_p || !TREE_PUBLIC (node->decl));
          cgraph_make_decl_local (node->decl);
+         node->resolution = LDPR_PREVAILING_DEF_IRONLY;
          for (alias = node->same_body; alias; alias = alias->next)
            cgraph_make_decl_local (alias->decl);
          if (node->same_comdat_group)
@@ -768,9 +780,6 @@ function_and_variable_visibility (bool whole_program)
              || ! (ADDR_SPACE_GENERIC_P
                    (TYPE_ADDR_SPACE (TREE_TYPE (vnode->decl))))))
        DECL_COMMON (vnode->decl) = 0;
-     /* Even extern variables might have initializers known.
-       See, for example testsuite/g++.dg/opt/static3.C  */
-     vnode->const_value_known |= varpool_decide_const_value_known (vnode);
     }
   for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed)
     {
@@ -788,12 +797,13 @@ function_and_variable_visibility (bool whole_program)
               /* When doing linktime optimizations, all hidden symbols will
                  become local.  */
               && (!in_lto_p
-                  || DECL_VISIBILITY (vnode->decl) != VISIBILITY_HIDDEN
+                  || (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)
-              || vnode->used_from_object_file
+              || varpool_used_from_object_file_p (vnode)
              || pointer_set_contains (aliased_vnodes, vnode)
              || lookup_attribute ("externally_visible",
                                   DECL_ATTRIBUTES (vnode->decl))))
@@ -804,8 +814,8 @@ function_and_variable_visibility (bool whole_program)
        {
          gcc_assert (in_lto_p || whole_program || !TREE_PUBLIC (vnode->decl));
          cgraph_make_decl_local (vnode->decl);
+         vnode->resolution = LDPR_PREVAILING_DEF_IRONLY;
        }
-     vnode->const_value_known |= varpool_decide_const_value_known (vnode);
      gcc_assert (TREE_STATIC (vnode->decl));
     }
   pointer_set_destroy (aliased_nodes);