OSDN Git Service

* matrix-reorg.c (analyze_matrix_allocation_site): Remove unused
[pf3gnuchains/gcc-fork.git] / gcc / ipa.c
index b082efe..1b68a7a 100644 (file)
--- a/gcc/ipa.c
+++ b/gcc/ipa.c
@@ -114,13 +114,14 @@ update_inlined_to_pointer (struct cgraph_node *node, struct cgraph_node *inlined
 
 /* Perform reachability analysis and reclaim all unreachable nodes.
    If BEFORE_INLINING_P is true this function is called before inlining
-   decisions has been made.  If BEFORE_INLINING_P is false this function also 
+   decisions has been made.  If BEFORE_INLINING_P is false this function also
    removes unneeded bodies of extern inline functions.  */
 
 bool
 cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
 {
   struct cgraph_node *first = (struct cgraph_node *) (void *) 1;
+  struct cgraph_node *processed = (struct cgraph_node *) (void *) 2;
   struct cgraph_node *node, *next;
   bool changed = false;
 
@@ -135,16 +136,20 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
 #endif
   for (node = cgraph_nodes; node; node = node->next)
     if (!cgraph_can_remove_if_no_direct_calls_p (node)
-       && ((!DECL_EXTERNAL (node->decl)) 
+       && ((!DECL_EXTERNAL (node->decl))
             || !node->analyzed
             || before_inlining_p))
       {
         gcc_assert (!node->global.inlined_to);
        node->aux = first;
        first = node;
+       node->reachable = true;
       }
     else
-      gcc_assert (!node->aux);
+      {
+        gcc_assert (!node->aux);
+       node->reachable = false;
+      }
 
   /* Perform reachability analysis.  As a special case do not consider
      extern inline functions not inlined as live because we won't output
@@ -154,17 +159,26 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
       struct cgraph_edge *e;
       node = first;
       first = (struct cgraph_node *) first->aux;
-
-      for (e = node->callees; e; e = e->next_callee)
-       if (!e->callee->aux
-           && node->analyzed
-           && (!e->inline_failed || !e->callee->analyzed
-               || (!DECL_EXTERNAL (e->callee->decl))
-                || before_inlining_p))
-         {
-           e->callee->aux = first;
-           first = e->callee;
-         }
+      node->aux = processed;
+
+      if (node->reachable)
+        for (e = node->callees; e; e = e->next_callee)
+         if (!e->callee->reachable
+             && node->analyzed
+             && (!e->inline_failed || !e->callee->analyzed
+                 || (!DECL_EXTERNAL (e->callee->decl))
+                  || before_inlining_p))
+           {
+             bool prev_reachable = e->callee->reachable;
+             e->callee->reachable |= node->reachable;
+             if (!e->callee->aux
+                 || (e->callee->aux == processed
+                     && prev_reachable != e->callee->reachable))
+               {
+                 e->callee->aux = first;
+                 first = e->callee;
+               }
+           }
       while (node->clone_of && !node->clone_of->aux && !gimple_has_body_p (node->decl))
         {
          node = node->clone_of;
@@ -184,13 +198,18 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
   for (node = cgraph_nodes; node; node = next)
     {
       next = node->next;
+      if (node->aux && !node->reachable)
+        {
+         cgraph_node_remove_callees (node);
+         node->analyzed = false;
+         node->local.inlinable = false;
+       }
       if (!node->aux)
        {
           node->global.inlined_to = NULL;
          if (file)
            fprintf (file, " %s", cgraph_node_name (node));
-         if (!node->analyzed || !DECL_EXTERNAL (node->decl)
-             || before_inlining_p)
+         if (!node->analyzed || !DECL_EXTERNAL (node->decl) || before_inlining_p)
            cgraph_remove_node (node);
          else
            {
@@ -219,6 +238,12 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
                      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;
                }
              else
                cgraph_remove_node (node);
@@ -292,6 +317,14 @@ function_and_variable_visibility (bool whole_program)
 
   for (node = cgraph_nodes; node; node = node->next)
     {
+      /* C++ FE on lack of COMDAT support create local COMDAT functions
+        (that ought to be shared but can not due to object format
+        limitations).  It is neccesary to keep the flag to make rest of C++ FE
+        happy.  Clear the flag here to avoid confusion in middle-end.  */
+      if (DECL_COMDAT (node->decl) && !TREE_PUBLIC (node->decl))
+        DECL_COMDAT (node->decl) = 0;
+      gcc_assert ((!DECL_WEAK (node->decl) && !DECL_COMDAT (node->decl))
+                 || TREE_PUBLIC (node->decl) || DECL_EXTERNAL (node->decl));
       if (cgraph_externally_visible_p (node, whole_program))
         {
          gcc_assert (!node->global.inlined_to);
@@ -316,9 +349,16 @@ function_and_variable_visibility (bool whole_program)
     {
       if (!vnode->finalized)
         continue;
+      gcc_assert ((!DECL_WEAK (vnode->decl) && !DECL_COMMON (vnode->decl))
+                 || TREE_PUBLIC (vnode->decl) || DECL_EXTERNAL (vnode->decl));
       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)
              || lookup_attribute ("externally_visible",
                                   DECL_ATTRIBUTES (vnode->decl))))
        vnode->externally_visible = true;
@@ -328,6 +368,7 @@ function_and_variable_visibility (bool whole_program)
        {
          gcc_assert (whole_program || !TREE_PUBLIC (vnode->decl));
          TREE_PUBLIC (vnode->decl) = 0;
+         DECL_COMMON (vnode->decl) = 0;
        }
      gcc_assert (TREE_STATIC (vnode->decl));
     }
@@ -344,6 +385,11 @@ function_and_variable_visibility (bool whole_program)
        if (node->local.externally_visible)
          fprintf (dump_file, " %s", cgraph_node_name (node));
       fprintf (dump_file, "\n\n");
+      fprintf (dump_file, "\nMarking externally visible variables:");
+      for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed)
+       if (vnode->externally_visible)
+         fprintf (dump_file, " %s", varpool_node_name (vnode));
+      fprintf (dump_file, "\n\n");
     }
   cgraph_function_flags_ready = true;
   return 0;
@@ -358,7 +404,7 @@ local_function_and_variable_visibility (void)
   return function_and_variable_visibility (flag_whole_program && !flag_lto && !flag_whopr);
 }
 
-struct simple_ipa_opt_pass pass_ipa_function_and_variable_visibility = 
+struct simple_ipa_opt_pass pass_ipa_function_and_variable_visibility =
 {
  {
   SIMPLE_IPA_PASS,
@@ -396,11 +442,20 @@ whole_program_function_and_variable_visibility (void)
   function_and_variable_visibility (flag_whole_program);
 
   for (node = cgraph_nodes; node; node = node->next)
-    if (node->local.externally_visible && node->local.finalized)
+    if ((node->local.externally_visible && !DECL_COMDAT (node->decl))
+        && node->local.finalized)
       cgraph_mark_needed_node (node);
   for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed)
-    if (vnode->externally_visible)
+    if (vnode->externally_visible && !DECL_COMDAT (vnode->decl))
       varpool_mark_needed_node (vnode);
+  if (dump_file)
+    {
+      fprintf (dump_file, "\nNeeded variables:");
+      for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed)
+       if (vnode->needed)
+         fprintf (dump_file, " %s", varpool_node_name (vnode));
+      fprintf (dump_file, "\n\n");
+    }
   return 0;
 }
 
@@ -533,7 +588,7 @@ cgraph_node_set_remove (cgraph_node_set set, struct cgraph_node *node)
       VEC_replace (cgraph_node_ptr, set->nodes, last_element->index,
                   last_node);
     }
-  
+
   /* Remove element from hash table.  */
   htab_clear_slot (set->hashtab, slot);
   ggc_free (element);