OSDN Git Service

* lto.c (globalize_cross_file_statics): When function has address taken,
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 21 Apr 2010 14:41:03 +0000 (14:41 +0000)
committerMasaki Muranaka <monaka@monami-software.com>
Sun, 23 May 2010 01:08:17 +0000 (10:08 +0900)
it needs to be public.
* varpool.c (decide_is_variable_needed): Variable is always needed
during ltrans.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@158609 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/lto/ChangeLog
gcc/lto/lto.c
gcc/varpool.c

index 1fe4172..13ac239 100644 (file)
@@ -1,5 +1,10 @@
 2010-04-21  Jan Hubicka  <jh@suse.cz>
 
+       * varpool.c (decide_is_variable_needed): Variable is always needed
+       during ltrans.
+
+2010-04-21  Jan Hubicka  <jh@suse.cz>
+
        * opts.c (decode_options): Enable pure-const pass for whopr.
 
 2010-04-21  Jan Hubicka  <jh@suse.cz>
index 9118e00..a97314c 100644 (file)
@@ -1,3 +1,8 @@
+2010-04-21  Jan Hubicka  <jh@suse.cz>
+
+       * lto.c (globalize_cross_file_statics): When function has address taken,
+       it needs to be public.
+
 2010-04-20  Jan Hubicka  <jh@suse.cz>
 
        * lto.c (lto_add_inline_clones): Do not track inlined_decls.
index 1544f05..ea8f03a 100644 (file)
@@ -760,7 +760,8 @@ globalize_cross_file_statics (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
     }
   else if (TREE_CODE (t) == FUNCTION_DECL && !TREE_PUBLIC (t))
     {
-      if (!cgraph_node_in_set_p (cgraph_node (t), context->set))
+      if (!cgraph_node_in_set_p (cgraph_node (t), context->set)
+         || cgraph_node (t)->address_taken)
        {
          /* This file-scope static function is reachable from a set
             which does not contain the function DECL.  Make it global
index 73d39f3..40decfc 100644 (file)
@@ -105,22 +105,6 @@ eq_varpool_node (const void *p1, const void *p2)
   return DECL_UID (n1->decl) == DECL_UID (n2->decl);
 }
 
-/* Return varpool node assigned to DECL without creating new one.  */
-struct varpool_node *
-varpool_get_node (tree decl)
-{
-  struct varpool_node key, **slot;
-
-  gcc_assert (DECL_P (decl) && TREE_CODE (decl) != FUNCTION_DECL);
-
-  if (!varpool_hash)
-    return NULL;
-  key.decl = decl;
-  slot = (struct varpool_node **)
-    htab_find_slot (varpool_hash, &key, INSERT);
-  return *slot;
-}
-
 /* Return varpool node assigned to DECL.  Create new one when needed.  */
 struct varpool_node *
 varpool_node (tree decl)
@@ -141,77 +125,11 @@ varpool_node (tree decl)
   node->decl = decl;
   node->order = cgraph_order++;
   node->next = varpool_nodes;
-  ipa_empty_ref_list (&node->ref_list);
-  if (varpool_nodes)
-    varpool_nodes->prev = node;
   varpool_nodes = node;
   *slot = node;
   return node;
 }
 
-/* Remove node from the varpool.  */
-void
-varpool_remove_node (struct varpool_node *node)
-{
-  void **slot;
-  slot = htab_find_slot (varpool_hash, node, NO_INSERT);
-  gcc_assert (*slot == node);
-  htab_clear_slot (varpool_hash, slot);
-  gcc_assert (!varpool_assembled_nodes_queue);
-  if (!node->alias)
-    while (node->extra_name)
-      varpool_remove_node (node->extra_name);
-  if (node->next)
-    node->next->prev = node->prev;
-  if (node->prev)
-    node->prev->next = node->next;
-  else
-    {
-      if (node->alias && node->extra_name)
-       {
-          gcc_assert (node->extra_name->extra_name == node);
-         node->extra_name->extra_name = node->next;
-       }
-      else
-       {
-          gcc_assert (varpool_nodes == node);
-          varpool_nodes = node->next;
-       }
-    }
-  if (varpool_first_unanalyzed_node == node)
-    varpool_first_unanalyzed_node = node->next_needed;
-  if (node->next_needed)
-    node->next_needed->prev_needed = node->prev_needed;
-  else if (node->prev_needed)
-    {
-      gcc_assert (varpool_last_needed_node);
-      varpool_last_needed_node = node->prev_needed;
-    }
-  if (node->prev_needed)
-    node->prev_needed->next_needed = node->next_needed;
-  else if (node->next_needed)
-    {
-      gcc_assert (varpool_nodes_queue == node);
-      varpool_nodes_queue = node->next_needed;
-    }
-  if (node->same_comdat_group)
-    {
-      struct varpool_node *prev;
-      for (prev = node->same_comdat_group;
-          prev->same_comdat_group != node;
-          prev = prev->same_comdat_group)
-       ;
-      if (node->same_comdat_group == prev)
-       prev->same_comdat_group = NULL;
-      else
-       prev->same_comdat_group = node->same_comdat_group;
-      node->same_comdat_group = NULL;
-    }
-  ipa_remove_all_references (&node->ref_list);
-  ipa_remove_all_refering (&node->ref_list);
-  ggc_free (node);
-}
-
 /* Dump given cgraph node.  */
 void
 dump_varpool_node (FILE *f, struct varpool_node *node)
@@ -221,12 +139,8 @@ dump_varpool_node (FILE *f, struct varpool_node *node)
           cgraph_function_flags_ready
           ? cgraph_availability_names[cgraph_variable_initializer_availability (node)]
           : "not-ready");
-  if (DECL_ASSEMBLER_NAME_SET_P (node->decl))
-    fprintf (f, " (asm: %s)", IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl)));
   if (DECL_INITIAL (node->decl))
     fprintf (f, " initialized");
-  if (TREE_ASM_WRITTEN (node->decl))
-    fprintf (f, " (asm written)");
   if (node->needed)
     fprintf (f, " needed");
   if (node->analyzed)
@@ -237,15 +151,7 @@ dump_varpool_node (FILE *f, struct varpool_node *node)
     fprintf (f, " output");
   if (node->externally_visible)
     fprintf (f, " externally_visible");
-  if (node->in_other_partition)
-    fprintf (f, " in_other_partition");
-  else if (node->used_from_other_partition)
-    fprintf (f, " used_from_other_partition");
   fprintf (f, "\n");
-  fprintf (f, "  References: ");
-  ipa_dump_references (f, &node->ref_list);
-  fprintf (f, "  Refering this var: ");
-  ipa_dump_refering (f, &node->ref_list);
 }
 
 /* Dump the variable pool.  */
@@ -286,10 +192,7 @@ static void
 varpool_enqueue_needed_node (struct varpool_node *node)
 {
   if (varpool_last_needed_node)
-    {
-      varpool_last_needed_node->next_needed = node;
-      node->prev_needed = varpool_last_needed_node;
-    }
+    varpool_last_needed_node->next_needed = node;
   varpool_last_needed_node = node;
   node->next_needed = NULL;
   if (!varpool_nodes_queue)
@@ -313,7 +216,7 @@ varpool_mark_needed_node (struct varpool_node *node)
 }
 
 /* Reset the queue of needed nodes.  */
-void
+static void
 varpool_reset_queue (void)
 {
   varpool_last_needed_node = NULL;
@@ -327,13 +230,24 @@ varpool_reset_queue (void)
 bool
 decide_is_variable_needed (struct varpool_node *node, tree decl)
 {
-  if (node->used_from_other_partition)
+  /* We do not track variable references at all and thus have no idea if the
+     variable was referenced in some other partition or not.  
+     FIXME: We really need address taken edges in callgraph and varpool to
+     drive WPA and decide whether other partition might reference it or not.  */
+  if (flag_ltrans)
     return true;
   /* If the user told us it is used, then it must be so.  */
   if ((node->externally_visible && !DECL_COMDAT (decl))
       || node->force_output)
     return true;
 
+  /* ??? If the assembler name is set by hand, it is possible to assemble
+     the name later after finalizing the function and the fact is noticed
+     in assemble_name then.  This is arguably a bug.  */
+  if (DECL_ASSEMBLER_NAME_SET_P (decl)
+      && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
+    return true;
+
   /* Externally visible variables must be output.  The exception is
      COMDAT variables that must be output only when they are needed.  */
   if (TREE_PUBLIC (decl)
@@ -374,6 +288,17 @@ varpool_finalize_decl (tree decl)
 {
   struct varpool_node *node = varpool_node (decl);
 
+  /* FIXME: We don't really stream varpool datastructure and instead rebuild it
+     by varpool_finalize_decl.  This is not quite correct since this way we can't
+     attach any info to varpool.  Eventually we will want to stream varpool nodes
+     and the flags.
+
+     For the moment just prevent analysis of varpool nodes to happen again, so
+     we will re-try to compute "address_taken" flag of varpool that breaks
+     in presence of clones.  */
+  if (in_lto_p)
+    node->analyzed = true;
+
   /* The first declaration of a variable that comes through this function
      decides whether it is global (in C, has external linkage)
      or local (in C, has internal linkage).  So do nothing more
@@ -387,8 +312,6 @@ varpool_finalize_decl (tree decl)
   if (node->needed)
     varpool_enqueue_needed_node (node);
   node->finalized = true;
-  if (TREE_THIS_VOLATILE (decl) || DECL_PRESERVE_P (decl))
-    node->force_output = true;
 
   if (decide_is_variable_needed (node, decl))
     varpool_mark_needed_node (node);
@@ -425,13 +348,12 @@ bool
 varpool_analyze_pending_decls (void)
 {
   bool changed = false;
+  timevar_push (TV_CGRAPH);
 
-  timevar_push (TV_VARPOOL);
   while (varpool_first_unanalyzed_node)
     {
-      struct varpool_node *node = varpool_first_unanalyzed_node, *next;
-      tree decl = node->decl;
-      bool analyzed = node->analyzed;
+      tree decl = varpool_first_unanalyzed_node->decl;
+      bool analyzed = varpool_first_unanalyzed_node->analyzed;
 
       varpool_first_unanalyzed_node->analyzed = true;
 
@@ -442,23 +364,16 @@ varpool_analyze_pending_decls (void)
         We however don't want to re-analyze already analyzed nodes.  */
       if (!analyzed)
        {
-         gcc_assert (!in_lto_p || cgraph_function_flags_ready);
+         gcc_assert (!in_lto_p);
           /* Compute the alignment early so function body expanders are
             already informed about increased alignment.  */
           align_variable (decl, 0);
        }
       if (DECL_INITIAL (decl))
        record_references_in_initializer (decl, analyzed);
-      if (node->same_comdat_group)
-       {
-         for (next = node->same_comdat_group;
-              next != node;
-              next = next->same_comdat_group)
-           varpool_mark_needed_node (next);
-       }
       changed = true;
     }
-  timevar_pop (TV_VARPOOL);
+  timevar_pop (TV_CGRAPH);
   return changed;
 }
 
@@ -470,7 +385,6 @@ varpool_assemble_decl (struct varpool_node *node)
 
   if (!TREE_ASM_WRITTEN (decl)
       && !node->alias
-      && !node->in_other_partition
       && !DECL_EXTERNAL (decl)
       && (TREE_CODE (decl) != VAR_DECL || !DECL_HAS_VALUE_EXPR_P (decl)))
     {
@@ -480,9 +394,6 @@ varpool_assemble_decl (struct varpool_node *node)
          struct varpool_node *alias;
 
          node->next_needed = varpool_assembled_nodes_queue;
-         node->prev_needed = NULL;
-         if (varpool_assembled_nodes_queue)
-           varpool_assembled_nodes_queue->prev_needed = node;
          varpool_assembled_nodes_queue = node;
          node->finalized = 1;
 
@@ -552,7 +463,6 @@ varpool_assemble_pending_decls (void)
   if (errorcount || sorrycount)
     return false;
 
-  timevar_push (TV_VAROUT);
   /* EH might mark decls as needed during expansion.  This should be safe since
      we don't create references to new function, but it should not be used
      elsewhere.  */
@@ -566,15 +476,11 @@ varpool_assemble_pending_decls (void)
       if (varpool_assemble_decl (node))
        changed = true;
       else
-       {
-         node->prev_needed = NULL;
-          node->next_needed = NULL;
-       }
+        node->next_needed = NULL;
     }
   /* varpool_nodes_queue is now empty, clear the pointer to the last element
      in the queue.  */
   varpool_last_needed_node = NULL;
-  timevar_pop (TV_VAROUT);
   return changed;
 }
 
@@ -592,7 +498,6 @@ varpool_empty_needed_queue (void)
       struct varpool_node *node = varpool_nodes_queue;
       varpool_nodes_queue = varpool_nodes_queue->next_needed;
       node->next_needed = NULL;
-      node->prev_needed = NULL;
     }
   /* varpool_nodes_queue is now empty, clear the pointer to the last element
      in the queue.  */
@@ -654,9 +559,6 @@ varpool_extra_name_alias (tree alias, tree decl)
   alias_node->alias = 1;
   alias_node->extra_name = decl_node;
   alias_node->next = decl_node->extra_name;
-  ipa_empty_ref_list (&alias_node->ref_list);
-  if (decl_node->extra_name)
-    decl_node->extra_name->prev = alias_node;
   decl_node->extra_name = alias_node;
   *slot = alias_node;
   return true;