OSDN Git Service

* cgraphbuild.c (record_reference_ctx): Add varpool_node.
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 6 May 2010 08:39:32 +0000 (08:39 +0000)
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 6 May 2010 08:39:32 +0000 (08:39 +0000)
(record_reference, mark_address, mark_load, mark_store): Record
references.
(record_references_in_initializer): Update call of record_references.
(rebuild_cgraph_edges): Remove all references before rebuiding.
* cgraph.c (cgraph_create_node): Clear ref list.
(cgraph_remove_node): Remove references.
(dump_cgraph_node): Dump references.
(cgraph_clone_node): Clone references.
* cgraph.h: Include ipa-ref.h and ipa-ref-inline.h
(struct cgraph_node, varpool_node): Add ref_lst.
* ipa-ref.c: New file.
* ipa-ref.h: New file.
* ipa-ref-inline.h: New file.
* lto-cgraph.c (output_varpool): Take cgrag node set argument.
(referenced_from_other_partition_p): New function.
(lto_output_varpool_node): Take set arugment; call
referenced_from_other_partition.
(lto_output_ref): New.
(add_references): New.
(output_refs): New.
(output_cgraph): Compute boundary based on references;
output refs.
(output_varpool): Accept cgraph_node_set argument.
(input_ref): New.
(input_refs): New.
(input_cgraph): Call input_refs.
* lto-section-in.c (lto_section_name): Add refs.
* Makefile.in: (cgraph.h): Include ipa-ref.h and ipa-ref-inline.h
(ipa-ref.o): New file.
* varpool.c (varpool_node): Clear ipa ref list.
(varpool_remove_node): Remove references.
(dump_varpool_node): Dump references.
(varpool_assemble_decl): Only compile finalized ones.
(varpool_extra_name_alias): Initialize ref list.
* lto-streamer.c (lto-get_section_name): Add .refs section.
* lto-streamer.h (lto_section_type): Add LTO_section_refs.
(referenced_from_other_partition_p): Declared.

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

16 files changed:
gcc/ChangeLog
gcc/Makefile.in
gcc/cgraph.c
gcc/cgraph.h
gcc/cgraphbuild.c
gcc/ipa-ref-inline.h
gcc/ipa-ref.c
gcc/ipa-ref.h
gcc/lto-cgraph.c
gcc/lto-section-in.c
gcc/lto-streamer.c
gcc/lto-streamer.h
gcc/lto-symtab.c
gcc/lto/ChangeLog
gcc/lto/lto.c
gcc/varpool.c

index cfc1629..3994866 100644 (file)
@@ -1,3 +1,44 @@
+2010-05-06  Jan Hubicka  <jh@suse.cz>
+
+       * cgraphbuild.c (record_reference_ctx): Add varpool_node.
+       (record_reference, mark_address, mark_load, mark_store): Record
+       references.
+       (record_references_in_initializer): Update call of record_references.
+       (rebuild_cgraph_edges): Remove all references before rebuiding.
+       * cgraph.c (cgraph_create_node): Clear ref list.
+       (cgraph_remove_node): Remove references.
+       (dump_cgraph_node): Dump references.
+       (cgraph_clone_node): Clone references.
+       * cgraph.h: Include ipa-ref.h and ipa-ref-inline.h
+       (struct cgraph_node, varpool_node): Add ref_lst.
+       * ipa-ref.c: New file.
+       * ipa-ref.h: New file.
+       * ipa-ref-inline.h: New file.
+       * lto-cgraph.c (output_varpool): Take cgrag node set argument.
+       (referenced_from_other_partition_p): New function.
+       (lto_output_varpool_node): Take set arugment; call
+       referenced_from_other_partition.
+       (lto_output_ref): New.
+       (add_references): New.
+       (output_refs): New.
+       (output_cgraph): Compute boundary based on references;
+       output refs.
+       (output_varpool): Accept cgraph_node_set argument.
+       (input_ref): New.
+       (input_refs): New.
+       (input_cgraph): Call input_refs.
+       * lto-section-in.c (lto_section_name): Add refs.
+       * Makefile.in: (cgraph.h): Include ipa-ref.h and ipa-ref-inline.h
+       (ipa-ref.o): New file.
+       * varpool.c (varpool_node): Clear ipa ref list.
+       (varpool_remove_node): Remove references.
+       (dump_varpool_node): Dump references.
+       (varpool_assemble_decl): Only compile finalized ones.
+       (varpool_extra_name_alias): Initialize ref list.
+       * lto-streamer.c (lto-get_section_name): Add .refs section.
+       * lto-streamer.h (lto_section_type): Add LTO_section_refs.
+       (referenced_from_other_partition_p): Declared.
+
 2010-05-06  Ira Rosen  <irar@il.ibm.com>
 
        PR tree-optimization/43901
index ce6e3a1..f19def7 100644 (file)
@@ -904,7 +904,7 @@ CFGLOOP_H = cfgloop.h $(BASIC_BLOCK_H) $(RTL_H) vecprim.h double-int.h
 IPA_UTILS_H = ipa-utils.h $(TREE_H) $(CGRAPH_H)
 IPA_REFERENCE_H = ipa-reference.h $(BITMAP_H) $(TREE_H)
 IPA_TYPE_ESCAPE_H = ipa-type-escape.h $(TREE_H)
-CGRAPH_H = cgraph.h $(TREE_H) $(BASIC_BLOCK_H) cif-code.def
+CGRAPH_H = cgraph.h $(TREE_H) $(BASIC_BLOCK_H) cif-code.def ipa-ref.h ipa-ref-inline.h
 DF_H = df.h $(BITMAP_H) $(BASIC_BLOCK_H) alloc-pool.h $(TIMEVAR_H)
 RESOURCE_H = resource.h hard-reg-set.h $(DF_H)
 DDG_H = ddg.h sbitmap.h $(DF_H)
@@ -1425,6 +1425,7 @@ OBJS-archive = \
        ipa-prop.o \
        ipa-pure-const.o \
        ipa-reference.o \
+       ipa-ref.o \
        ipa-struct-reorg.o \
        ipa-type-escape.o \
        ipa-utils.o \
@@ -2902,6 +2903,9 @@ ipa-prop.o : ipa-prop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
    langhooks.h $(GGC_H) $(TARGET_H) $(CGRAPH_H) $(IPA_PROP_H) $(DIAGNOSTIC_H) \
    $(TREE_FLOW_H) $(TM_H) $(TREE_PASS_H) $(FLAGS_H) $(TREE_H) \
    $(TREE_INLINE_H) $(TIMEVAR_H)
+ipa-ref.o : ipa-ref.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+   langhooks.h $(GGC_H) $(TARGET_H) $(CGRAPH_H)  $(TREE_H) $(TARGET_H) \
+   $(TREE_FLOW_H) $(TM_H) $(TREE_PASS_H) $(FLAGS_H) $(TREE_H) $(GGC_H) 
 ipa-cp.o : ipa-cp.c $(CONFIG_H) $(SYSTEM_H) coretypes.h  \
    $(TREE_H) $(TARGET_H) $(CGRAPH_H) $(IPA_PROP_H) $(TREE_FLOW_H) \
    $(TREE_PASS_H) $(FLAGS_H) $(TIMEVAR_H) $(DIAGNOSTIC_H) $(TREE_DUMP_H) \
@@ -3584,7 +3588,7 @@ GTFILES = $(CPP_ID_DATA_H) $(srcdir)/input.h $(srcdir)/coretypes.h \
   $(srcdir)/real.h $(srcdir)/function.h $(srcdir)/insn-addr.h $(srcdir)/hwint.h \
   $(srcdir)/fixed-value.h \
   $(srcdir)/ipa-reference.h $(srcdir)/output.h $(srcdir)/cfgloop.h \
-  $(srcdir)/cselib.h $(srcdir)/basic-block.h  $(srcdir)/cgraph.h \
+  $(srcdir)/cselib.h $(srcdir)/basic-block.h  $(srcdir)/ipa-ref.h $(srcdir)/cgraph.h \
   $(srcdir)/reload.h $(srcdir)/caller-save.c \
   $(srcdir)/alias.c $(srcdir)/bitmap.c $(srcdir)/cselib.c $(srcdir)/cgraph.c \
   $(srcdir)/ipa-prop.c $(srcdir)/ipa-cp.c $(srcdir)/ipa-inline.c $(srcdir)/matrix-reorg.c \
index 424c3f2..64a9c65 100644 (file)
@@ -463,6 +463,7 @@ cgraph_create_node (void)
   node->previous = NULL;
   node->global.estimated_growth = INT_MIN;
   node->frequency = NODE_FREQUENCY_NORMAL;
+  ipa_empty_ref_list (&node->ref_list);
   cgraph_nodes = node;
   cgraph_n_nodes++;
   return node;
@@ -1412,6 +1413,8 @@ cgraph_remove_node (struct cgraph_node *node)
   cgraph_call_node_removal_hooks (node);
   cgraph_node_remove_callers (node);
   cgraph_node_remove_callees (node);
+  ipa_remove_all_references (&node->ref_list);
+  ipa_remove_all_refering (&node->ref_list);
   VEC_free (ipa_opt_pass, heap,
             node->ipa_transforms_to_apply);
 
@@ -1853,6 +1856,10 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node)
        fprintf(f, "(can throw external) ");
     }
   fprintf (f, "\n");
+  fprintf (f, "  References: ");
+  ipa_dump_references (f, &node->ref_list);
+  fprintf (f, "  Refering this function: ");
+  ipa_dump_refering (f, &node->ref_list);
 
   for (edge = node->indirect_calls; edge; edge = edge->next_callee)
     indirect_calls_count++;
@@ -2081,6 +2088,7 @@ cgraph_clone_node (struct cgraph_node *n, gcov_type count, int freq,
   for (e = n->indirect_calls; e; e = e->next_callee)
     cgraph_clone_edge (e, new_node, e->call_stmt, e->lto_stmt_uid,
                       count_scale, freq, loop_nest, update_original);
+  ipa_clone_references (new_node, NULL, &n->ref_list);
 
   new_node->next_sibling_clone = n->clones;
   if (n->clones)
index 80594b1..93488c3 100644 (file)
@@ -23,6 +23,7 @@ along with GCC; see the file COPYING3.  If not see
 #define GCC_CGRAPH_H
 #include "tree.h"
 #include "basic-block.h"
+#include "ipa-ref.h"
 
 enum availability
 {
@@ -224,6 +225,7 @@ struct GTY((chain_next ("%h.next"), chain_prev ("%h.previous"))) cgraph_node {
      per-function in order to allow IPA passes to introduce new functions.  */
   VEC(ipa_opt_pass,heap) * GTY((skip)) ipa_transforms_to_apply;
 
+  struct ipa_ref_list ref_list;
   struct cgraph_local_info local;
   struct cgraph_global_info global;
   struct cgraph_rtl_info rtl;
@@ -427,7 +429,7 @@ DEF_VEC_ALLOC_P(cgraph_edge_p,heap);
 /* The varpool data structure.
    Each static variable decl has assigned varpool_node.  */
 
-struct GTY((chain_next ("%h.next"))) varpool_node {
+struct GTY((chain_next ("%h.next"), chain_prev ("%h.prev"))) varpool_node {
   tree decl;
   /* Pointer to the next function in varpool_nodes.  */
   struct varpool_node *next, *prev;
@@ -436,6 +438,7 @@ struct GTY((chain_next ("%h.next"))) varpool_node {
   /* For normal nodes a pointer to the first extra name alias.  For alias
      nodes a pointer to the normal node.  */
   struct varpool_node *extra_name;
+  struct ipa_ref_list ref_list;
   /* Ordering of all cgraph nodes.  */
   int order;
 
@@ -864,4 +867,6 @@ cgraph_can_remove_if_no_direct_calls_p (struct cgraph_node *node)
 /* Constant pool accessor function.  */
 htab_t constant_pool_htab (void);
 
+#include "ipa-ref-inline.h"
+
 #endif  /* GCC_CGRAPH_H  */
index 02c373a..ec190c7 100644 (file)
@@ -37,6 +37,7 @@ along with GCC; see the file COPYING3.  If not see
 struct record_reference_ctx
 {
   bool only_vars;
+  struct varpool_node *varpool_node;
 };
 
 /* Walk tree and record all calls and references to functions/variables.
@@ -63,15 +64,26 @@ record_reference (tree *tp, int *walk_subtrees, void *data)
       /* Record dereferences to the functions.  This makes the
         functions reachable unconditionally.  */
       decl = get_base_var (*tp);
-      if (TREE_CODE (decl) == FUNCTION_DECL && !ctx->only_vars)
-       cgraph_mark_address_taken_node (cgraph_node (decl));
+      if (TREE_CODE (decl) == FUNCTION_DECL)
+       {
+         if (!ctx->only_vars)
+         cgraph_mark_address_taken_node (cgraph_node (decl));
+         ipa_record_reference (NULL, ctx->varpool_node,
+                               cgraph_node (decl), NULL,
+                               IPA_REF_ADDR, NULL);
+       }
 
       if (TREE_CODE (decl) == VAR_DECL)
        {
-         gcc_assert (TREE_STATIC (decl) || DECL_EXTERNAL (decl));
+         struct varpool_node *vnode = varpool_node (decl);
          if (lang_hooks.callgraph.analyze_expr)
            lang_hooks.callgraph.analyze_expr (&decl, walk_subtrees);
-         varpool_mark_needed_node (varpool_node (decl));
+         varpool_mark_needed_node (vnode);
+         if (vnode->alias && vnode->extra_name)
+           vnode = vnode->extra_name;
+         ipa_record_reference (NULL, ctx->varpool_node,
+                               NULL, vnode,
+                               IPA_REF_ADDR, NULL);
        }
       *walk_subtrees = 0;
       break;
@@ -148,6 +160,9 @@ mark_address (gimple stmt ATTRIBUTE_UNUSED, tree addr,
     {
       struct cgraph_node *node = cgraph_node (addr);
       cgraph_mark_address_taken_node (node);
+      ipa_record_reference ((struct cgraph_node *)data, NULL,
+                           node, NULL,
+                           IPA_REF_ADDR, stmt);
     }
   else
     {
@@ -161,6 +176,11 @@ mark_address (gimple stmt ATTRIBUTE_UNUSED, tree addr,
          if (lang_hooks.callgraph.analyze_expr)
            lang_hooks.callgraph.analyze_expr (&addr, &walk_subtrees);
          varpool_mark_needed_node (vnode);
+         if (vnode->alias && vnode->extra_name)
+           vnode = vnode->extra_name;
+         ipa_record_reference ((struct cgraph_node *)data, NULL,
+                               NULL, vnode,
+                               IPA_REF_ADDR, stmt);
        }
     }
 
@@ -183,6 +203,11 @@ mark_load (gimple stmt ATTRIBUTE_UNUSED, tree t,
       if (lang_hooks.callgraph.analyze_expr)
        lang_hooks.callgraph.analyze_expr (&t, &walk_subtrees);
       varpool_mark_needed_node (vnode);
+      if (vnode->alias && vnode->extra_name)
+       vnode = vnode->extra_name;
+      ipa_record_reference ((struct cgraph_node *)data, NULL,
+                           NULL, vnode,
+                           IPA_REF_LOAD, stmt);
     }
   return false;
 }
@@ -203,6 +228,11 @@ mark_store (gimple stmt ATTRIBUTE_UNUSED, tree t,
       if (lang_hooks.callgraph.analyze_expr)
        lang_hooks.callgraph.analyze_expr (&t, &walk_subtrees);
       varpool_mark_needed_node (vnode);
+      if (vnode->alias && vnode->extra_name)
+       vnode = vnode->extra_name;
+      ipa_record_reference ((struct cgraph_node *)data, NULL,
+                           NULL, vnode,
+                           IPA_REF_STORE, NULL);
      }
   return false;
 }
@@ -299,8 +329,10 @@ void
 record_references_in_initializer (tree decl, bool only_vars)
 {
   struct pointer_set_t *visited_nodes = pointer_set_create ();
-  struct record_reference_ctx ctx = {false};
+  struct varpool_node *node = varpool_node (decl);
+  struct record_reference_ctx ctx = {false, NULL};
 
+  ctx.varpool_node = node;
   ctx.only_vars = only_vars;
   walk_tree (&DECL_INITIAL (decl), record_reference,
              &ctx, visited_nodes);
@@ -318,6 +350,7 @@ rebuild_cgraph_edges (void)
   gimple_stmt_iterator gsi;
 
   cgraph_node_remove_callees (node);
+  ipa_remove_all_references (&node->ref_list);
 
   node->count = ENTRY_BLOCK_PTR->count;
 
index e69de29..6ca9ba0 100644 (file)
@@ -0,0 +1,119 @@
+/* IPA reference lists.
+   Copyright (C) 2010
+   Free Software Foundation, Inc.
+   Contributed by Jan Hubicka
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+/* Return callgraph node REF is refering.  */
+static inline struct cgraph_node *
+ipa_ref_node (struct ipa_ref *ref)
+{
+  gcc_assert (ref->refered_type == IPA_REF_CGRAPH);
+  return ref->refered.cgraph_node;
+}
+
+/* Return varpool node REF is refering.  */
+
+static inline struct varpool_node *
+ipa_ref_varpool_node (struct ipa_ref *ref)
+{
+  gcc_assert (ref->refered_type == IPA_REF_VARPOOL);
+  return ref->refered.varpool_node;
+}
+
+/* Return cgraph node REF is in.  */
+
+static inline struct cgraph_node *
+ipa_ref_refering_node (struct ipa_ref *ref)
+{
+  gcc_assert (ref->refering_type == IPA_REF_CGRAPH);
+  return ref->refering.cgraph_node;
+}
+
+/* Return varpool node REF is in.  */
+
+static inline struct varpool_node *
+ipa_ref_refering_varpool_node (struct ipa_ref *ref)
+{
+  gcc_assert (ref->refering_type == IPA_REF_VARPOOL);
+  return ref->refering.varpool_node;
+}
+
+/* Return reference list REF is in.  */
+
+static inline struct ipa_ref_list *
+ipa_ref_refering_ref_list (struct ipa_ref *ref)
+{
+  if (ref->refering_type == IPA_REF_CGRAPH)
+    return &ipa_ref_refering_node (ref)->ref_list;
+  else
+    return &ipa_ref_refering_varpool_node (ref)->ref_list;
+}
+
+/* Return reference list REF is in.  */
+
+static inline struct ipa_ref_list *
+ipa_ref_refered_ref_list (struct ipa_ref *ref)
+{
+  if (ref->refered_type == IPA_REF_CGRAPH)
+    return &ipa_ref_node (ref)->ref_list;
+  else
+    return &ipa_ref_varpool_node (ref)->ref_list;
+}
+
+/* Return first reference in LIST or NULL if empty.  */
+
+static inline struct ipa_ref *
+ipa_ref_list_first_reference (struct ipa_ref_list *list)
+{
+  if (!VEC_length (ipa_ref_t, list->references))
+    return NULL;
+  return VEC_index (ipa_ref_t, list->references, 0);
+}
+
+/* Return first refering ref in LIST or NULL if empty.  */
+
+static inline struct ipa_ref *
+ipa_ref_list_first_refering (struct ipa_ref_list *list)
+{
+  if (!VEC_length (ipa_ref_ptr, list->refering))
+    return NULL;
+  return VEC_index (ipa_ref_ptr, list->refering, 0);
+}
+
+/* Clear reference list.  */
+
+static inline void
+ipa_empty_ref_list (struct ipa_ref_list *list)
+{
+  list->refering = NULL;
+  list->references = NULL;
+}
+
+/* Clear reference list.  */
+
+static inline unsigned int
+ipa_ref_list_nreferences (struct ipa_ref_list *list)
+{
+  return VEC_length (ipa_ref_t, list->references);
+}
+
+#define ipa_ref_list_reference_iterate(L,I,P) \
+   VEC_iterate(ipa_ref_t, (L)->references, (I), (P))
+#define ipa_ref_list_refering_iterate(L,I,P) \
+   VEC_iterate(ipa_ref_ptr, (L)->refering, (I), (P))
index e69de29..dd6b009 100644 (file)
@@ -0,0 +1,235 @@
+/* Interprocedural reference lists.
+   Copyright (C) 2010
+   Free Software Foundation, Inc.
+   Contributed by Jan Hubicka
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "ggc.h"
+#include "target.h"
+#include "cgraph.h"
+
+static const char *ipa_ref_use_name[] = {"read","write","addr"};
+
+/* Return ipa reference from REFERING_NODE or REFERING_VARPOOL_NODE
+   to REFERED_NODE or REFERED_VARPOOL_NODE. USE_TYPE specify type
+   of the use and STMT the statement (if it exists).  */
+
+struct ipa_ref *
+ipa_record_reference (struct cgraph_node *refering_node,
+                     struct varpool_node *refering_varpool_node,
+                     struct cgraph_node *refered_node,
+                     struct varpool_node *refered_varpool_node,
+                     enum ipa_ref_use use_type, gimple stmt)
+{
+  struct ipa_ref *ref;
+  struct ipa_ref_list *list, *list2;
+  VEC(ipa_ref_t,gc) *old_references;
+  gcc_assert ((!refering_node) ^ (!refering_varpool_node));
+  gcc_assert ((!refered_node) ^ (!refered_varpool_node));
+  gcc_assert (!stmt || refering_node);
+
+  list = (refering_node ? &refering_node->ref_list
+         : &refering_varpool_node->ref_list);
+  old_references = list->references;
+  VEC_safe_grow (ipa_ref_t, gc, list->references,
+                VEC_length (ipa_ref_t, list->references) + 1);
+  ref = VEC_last (ipa_ref_t, list->references);
+
+  list2 = (refered_node ? &refered_node->ref_list
+          : &refered_varpool_node->ref_list);
+  VEC_safe_push (ipa_ref_ptr, heap, list2->refering, ref);
+  ref->refered_index = VEC_length (ipa_ref_ptr, list2->refering) - 1;
+  if (refering_node)
+    {
+      ref->refering.cgraph_node = refering_node;
+      ref->refering_type = IPA_REF_CGRAPH;
+    }
+  else
+    {
+      ref->refering.varpool_node = refering_varpool_node;
+      ref->refering_type = IPA_REF_VARPOOL;
+      gcc_assert (use_type == IPA_REF_ADDR);
+    }
+  if (refered_node)
+    {
+      ref->refered.cgraph_node = refered_node;
+      ref->refered_type = IPA_REF_CGRAPH;
+      gcc_assert (use_type == IPA_REF_ADDR);
+    }
+  else
+    {
+      varpool_mark_needed_node (refered_varpool_node);
+      ref->refered.varpool_node = refered_varpool_node;
+      ref->refered_type = IPA_REF_VARPOOL;
+    }
+  ref->stmt = stmt;
+  ref->use = use_type;
+
+  /* If vector was moved in memory, update pointers.  */
+  if (old_references != list->references)
+    {
+      int i;
+      for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++)
+       VEC_replace (ipa_ref_ptr,
+                    ipa_ref_refered_ref_list (ref)->refering,
+                    ref->refered_index, ref);
+    }
+  return ref;
+}
+
+/* Remove reference REF.  */
+
+void
+ipa_remove_reference (struct ipa_ref *ref)
+{
+  struct ipa_ref_list *list = ipa_ref_refered_ref_list (ref);
+  struct ipa_ref_list *list2 = ipa_ref_refering_ref_list (ref);
+  VEC(ipa_ref_t,gc) *old_references = list2->references;
+  struct ipa_ref *last;
+
+  gcc_assert (VEC_index (ipa_ref_ptr, list->refering, ref->refered_index) == ref);
+  last = VEC_last (ipa_ref_ptr, list->refering);
+  if (ref != last)
+    {
+      VEC_replace (ipa_ref_ptr, list->refering,
+                  ref->refered_index,
+                  VEC_last (ipa_ref_ptr, list->refering));
+      VEC_index (ipa_ref_ptr, list->refering,
+                ref->refered_index)->refered_index = ref->refered_index;
+    }
+  VEC_pop (ipa_ref_ptr, list->refering);
+
+  last = VEC_last (ipa_ref_t, list2->references);
+  if (ref != last)
+    {
+      *ref = *last;
+      VEC_replace (ipa_ref_ptr,
+                  ipa_ref_refered_ref_list (ref)->refering,
+                  ref->refered_index, ref);
+    }
+  VEC_pop (ipa_ref_t, list2->references);
+  gcc_assert (list2->references == old_references);
+}
+
+/* Remove all references in ref list LIST.  */
+
+void
+ipa_remove_all_references (struct ipa_ref_list *list)
+{
+  while (VEC_length (ipa_ref_t, list->references))
+    ipa_remove_reference (VEC_last (ipa_ref_t, list->references));
+  VEC_free (ipa_ref_t, gc, list->references);
+  list->references = NULL;
+}
+
+/* Remove all references in ref list LIST.  */
+
+void
+ipa_remove_all_refering (struct ipa_ref_list *list)
+{
+  while (VEC_length (ipa_ref_ptr, list->refering))
+    ipa_remove_reference (VEC_last (ipa_ref_ptr, list->refering));
+  VEC_free (ipa_ref_ptr, heap, list->refering);
+  list->refering = NULL;
+}
+
+/* Dump references in LIST to FILE.  */
+
+void
+ipa_dump_references (FILE * file, struct ipa_ref_list *list)
+{
+  struct ipa_ref *ref;
+  int i;
+  for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++)
+    {
+      if (ref->refered_type == IPA_REF_CGRAPH)
+       {
+         fprintf (file, " fn:%s/%i (%s)", cgraph_node_name (ipa_ref_node (ref)),
+                  ipa_ref_node (ref)->uid,
+                  ipa_ref_use_name [ref->use]);
+       }
+      else
+       fprintf (file, " var:%s (%s)",
+                varpool_node_name (ipa_ref_varpool_node (ref)),
+                ipa_ref_use_name [ref->use]);
+    }
+  fprintf (file, "\n");
+}
+
+/* Dump refering in LIST to FILE.  */
+
+void
+ipa_dump_refering (FILE * file, struct ipa_ref_list *list)
+{
+  struct ipa_ref *ref;
+  int i;
+  for (i = 0; ipa_ref_list_refering_iterate (list, i, ref); i++)
+    {
+      if (ref->refering_type == IPA_REF_CGRAPH)
+       fprintf (file, " fn:%s/%i (%s)",
+                cgraph_node_name (ipa_ref_refering_node (ref)),
+                ipa_ref_refering_node (ref)->uid,
+                ipa_ref_use_name [ref->use]);
+      else
+       fprintf (file, " var:%s (%s)",
+                varpool_node_name (ipa_ref_refering_varpool_node (ref)),
+                ipa_ref_use_name [ref->use]);
+    }
+  fprintf (file, "\n");
+}
+
+/* Clone all references from SRC to DEST_NODE or DEST_VARPOL_NODE.  */
+
+void
+ipa_clone_references (struct cgraph_node *dest_node,
+                     struct varpool_node *dest_varpool_node,
+                     struct ipa_ref_list *src)
+{
+  struct ipa_ref *ref;
+  int i;
+  for (i = 0; ipa_ref_list_reference_iterate (src, i, ref); i++)
+    ipa_record_reference (dest_node, dest_varpool_node,
+                         ref->refered_type == IPA_REF_CGRAPH
+                         ? ipa_ref_node (ref) : NULL,
+                         ref->refered_type == IPA_REF_VARPOOL
+                         ? ipa_ref_varpool_node (ref) : NULL,
+                         ref->use, ref->stmt);
+}
+
+/* Clone all refering from SRC to DEST_NODE or DEST_VARPOL_NODE.  */
+
+void
+ipa_clone_refering (struct cgraph_node *dest_node,
+                   struct varpool_node *dest_varpool_node,
+                   struct ipa_ref_list *src)
+{
+  struct ipa_ref *ref;
+  int i;
+  for (i = 0; ipa_ref_list_refering_iterate (src, i, ref); i++)
+    ipa_record_reference (
+                         ref->refering_type == IPA_REF_CGRAPH
+                         ? ipa_ref_refering_node (ref) : NULL,
+                         ref->refering_type == IPA_REF_VARPOOL
+                         ? ipa_ref_refering_varpool_node (ref) : NULL,
+                         dest_node, dest_varpool_node,
+                         ref->use, ref->stmt);
+}
index e69de29..98912db 100644 (file)
@@ -0,0 +1,91 @@
+/* IPA reference lists.
+   Copyright (C) 2010
+   Free Software Foundation, Inc.
+   Contributed by Jan Hubicka
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+struct cgraph_node;
+struct varpool_node;
+
+/* How the reference is done.  */
+enum GTY(()) ipa_ref_use
+{
+  IPA_REF_LOAD,
+  IPA_REF_STORE,
+  IPA_REF_ADDR
+};
+
+/* Type of refering or refered type.  */
+enum GTY(()) ipa_ref_type
+{
+  IPA_REF_CGRAPH,
+  IPA_REF_VARPOOL
+};
+
+/* We can have references spanning both callgraph and varpool,
+   so all pointers needs to be of both types.  */
+union GTY(()) ipa_ref_ptr_u
+{
+  struct cgraph_node * GTY((tag ("IPA_REF_CGRAPH"))) cgraph_node;
+  struct varpool_node * GTY((tag ("IPA_REF_VARPOOL"))) varpool_node;
+};
+
+/* Record of reference in callgraph or varpool.  */
+struct GTY(()) ipa_ref
+{
+  union ipa_ref_ptr_u GTY ((desc ("%1.refering_type"))) refering;
+  union ipa_ref_ptr_u GTY ((desc ("%1.refered_type"))) refered;
+  gimple stmt;
+  unsigned int refered_index;
+  ENUM_BITFIELD (ipa_ref_type) refering_type:1;
+  ENUM_BITFIELD (ipa_ref_type) refered_type:1;
+  ENUM_BITFIELD (ipa_ref_use) use:2;
+};
+
+typedef struct ipa_ref ipa_ref_t;
+typedef struct ipa_ref *ipa_ref_ptr;
+
+DEF_VEC_O(ipa_ref_t);
+DEF_VEC_ALLOC_O(ipa_ref_t,gc);
+DEF_VEC_P(ipa_ref_ptr);
+DEF_VEC_ALLOC_P(ipa_ref_ptr,heap);
+
+/* List of references.  This is stored in both callgraph and varpool nodes.  */
+struct GTY(()) ipa_ref_list
+{
+  /* Store actual references in references vector.  */
+  VEC(ipa_ref_t,gc) *references;
+  /* Refering is vector of pointers to references.  It must not live in GGC space
+     or GGC will try to mark middle of references vectors.  */
+  VEC(ipa_ref_ptr,heap) * GTY((skip)) refering;
+};
+
+struct ipa_ref * ipa_record_reference (struct cgraph_node *,
+                                      struct varpool_node *,
+                                      struct cgraph_node *,
+                                      struct varpool_node *,
+                                      enum ipa_ref_use, gimple);
+
+void ipa_remove_reference (struct ipa_ref *);
+void ipa_remove_all_references (struct ipa_ref_list *);
+void ipa_remove_all_refering (struct ipa_ref_list *);
+void ipa_dump_references (FILE *, struct ipa_ref_list *);
+void ipa_dump_refering (FILE *, struct ipa_ref_list *);
+void ipa_clone_references (struct cgraph_node *, struct varpool_node *, struct ipa_ref_list *);
+void ipa_clone_refering (struct cgraph_node *, struct varpool_node *, struct ipa_ref_list *);
+
index 3e10954..5d05731 100644 (file)
@@ -46,7 +46,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "lto-streamer.h"
 #include "gcov-io.h"
 
-static void output_varpool (varpool_node_set);
+static void output_varpool (cgraph_node_set, varpool_node_set);
 
 /* Cgraph streaming is organized as set of record whose type
    is indicated by a tag.  */
@@ -286,6 +286,30 @@ lto_output_edge (struct lto_simple_output_block *ob, struct cgraph_edge *edge,
   bitpack_delete (bp);
 }
 
+/* Return if LIST contain references from other partitions.  */
+bool
+referenced_from_other_partition_p (struct ipa_ref_list *list, cgraph_node_set set,
+                                  varpool_node_set vset)
+{
+  int i;
+  struct ipa_ref *ref;
+  for (i = 0; ipa_ref_list_refering_iterate (list, i, ref); i++)
+    {
+      if (ref->refering_type == IPA_REF_CGRAPH)
+       {
+         if (!cgraph_node_in_set_p (ipa_ref_refering_node (ref), set))
+           return true;
+       }
+      else
+       {
+         if (!varpool_node_in_set_p (ipa_ref_refering_varpool_node (ref),
+                                     vset))
+           return true;
+       }
+    }
+  return false;
+}
+
 /* Return true when node is reachable from other partition.  */
 
 static bool
@@ -460,9 +484,9 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
 
 static void
 lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node *node,
-                        varpool_node_set set)
+                        cgraph_node_set set, varpool_node_set vset)
 {
-  bool boundary_p = !varpool_node_in_set_p (node, set) && node->analyzed;
+  bool boundary_p = !varpool_node_in_set_p (node, vset) && node->analyzed;
   struct bitpack_d *bp;
   struct varpool_node *alias;
   int count = 0;
@@ -486,9 +510,9 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node
     }
   else
     {
-      /* FIXME: We have no idea how we move references around.  For moment assume that
-        everything is used externally.  */
-      bp_pack_value (bp, flag_wpa, 1);  /* used_from_other_parition.  */
+      bp_pack_value (bp, node->analyzed
+                    && referenced_from_other_partition_p (&node->ref_list,
+                                                          set, vset), 1);
       bp_pack_value (bp, boundary_p, 1);  /* in_other_partition.  */
     }
   /* Also emit any extra name aliases.  */
@@ -506,6 +530,34 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node
     }
 }
 
+/* Output the varpool NODE to OB. 
+   If NODE is not in SET, then NODE is a boundary.  */
+
+static void
+lto_output_ref (struct lto_simple_output_block *ob, struct ipa_ref *ref,
+               lto_cgraph_encoder_t encoder,
+               lto_varpool_encoder_t varpool_encoder)
+{
+  struct bitpack_d *bp = bitpack_create ();
+  bp_pack_value (bp, ref->refered_type, 1);
+  bp_pack_value (bp, ref->use, 2);
+  lto_output_bitpack (ob->main_stream, bp);
+  bitpack_delete (bp);
+  if (ref->refered_type == IPA_REF_CGRAPH)
+    {
+      int nref = lto_cgraph_encoder_lookup (encoder, ipa_ref_node (ref));
+      gcc_assert (nref != LCC_NOT_FOUND);
+      lto_output_sleb128_stream (ob->main_stream, nref);
+    }
+  else
+    {
+      int nref = lto_varpool_encoder_lookup (varpool_encoder,
+                                            ipa_ref_varpool_node (ref));
+      gcc_assert (nref != LCC_NOT_FOUND);
+      lto_output_sleb128_stream (ob->main_stream, nref);
+    }
+}
+
 /* Stream out profile_summary to OB.  */
 
 static void
@@ -534,6 +586,25 @@ add_node_to (lto_cgraph_encoder_t encoder, struct cgraph_node *node)
   lto_cgraph_encoder_encode (encoder, node);
 }
 
+/* Add all references in LIST to encoders.  */
+
+static void
+add_references (lto_cgraph_encoder_t encoder,
+               lto_varpool_encoder_t varpool_encoder,
+               struct ipa_ref_list *list)
+{
+  int i;
+  struct ipa_ref *ref;
+  for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++)
+    if (ref->refered_type == IPA_REF_CGRAPH)
+      add_node_to (encoder, ipa_ref_node (ref));
+    else
+      {
+       struct varpool_node *vnode = ipa_ref_varpool_node (ref);
+        lto_varpool_encoder_encode (varpool_encoder, vnode);
+      }
+}
+
 /* Output all callees or indirect outgoing edges.  EDGE must be the first such
    edge.  */
 
@@ -555,6 +626,61 @@ output_outgoing_cgraph_edges (struct cgraph_edge *edge,
 
 /* Output the part of the cgraph in SET.  */
 
+static void
+output_refs (cgraph_node_set set, varpool_node_set vset,
+            lto_cgraph_encoder_t encoder,
+            lto_varpool_encoder_t varpool_encoder)
+{
+  cgraph_node_set_iterator csi;
+  varpool_node_set_iterator vsi;
+  struct lto_simple_output_block *ob;
+  int count;
+  struct ipa_ref *ref;
+  int i;
+
+  ob = lto_create_simple_output_block (LTO_section_refs);
+
+  for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi))
+    {
+      struct cgraph_node *node = csi_node (csi);
+
+      count = ipa_ref_list_nreferences (&node->ref_list);
+      if (count)
+       {
+         lto_output_uleb128_stream (ob->main_stream, count);
+         lto_output_uleb128_stream (ob->main_stream,
+                                    lto_cgraph_encoder_lookup (encoder, node));
+         for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list, i, ref); i++)
+           lto_output_ref (ob, ref, encoder, varpool_encoder);
+       }
+    }
+
+  lto_output_uleb128_stream (ob->main_stream, 0);
+
+  for (vsi = vsi_start (vset); !vsi_end_p (vsi); vsi_next (&vsi))
+    {
+      struct varpool_node *node = vsi_node (vsi);
+
+      count = ipa_ref_list_nreferences (&node->ref_list);
+      if (count)
+       {
+         lto_output_uleb128_stream (ob->main_stream, count);
+         lto_output_uleb128_stream (ob->main_stream,
+                                    lto_varpool_encoder_lookup (varpool_encoder,
+                                                                node));
+         for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list, i, ref); i++)
+           lto_output_ref (ob, ref, encoder, varpool_encoder);
+       }
+    }
+
+  lto_output_uleb128_stream (ob->main_stream, 0);
+
+  lto_destroy_simple_output_block (ob);
+}
+
+
+/* Output the part of the cgraph in SET.  */
+
 void
 output_cgraph (cgraph_node_set set, varpool_node_set vset)
 {
@@ -591,6 +717,7 @@ output_cgraph (cgraph_node_set set, varpool_node_set vset)
     {
       node = csi_node (csi);
       add_node_to (encoder, node);
+      add_references (encoder, varpool_encoder, &node->ref_list);
     }
   for (vsi = vsi_start (vset); !vsi_end_p (vsi); vsi_next (&vsi))
     {
@@ -598,9 +725,10 @@ output_cgraph (cgraph_node_set set, varpool_node_set vset)
       gcc_assert (!vnode->alias);
       lto_varpool_encoder_encode (varpool_encoder, vnode);
       lto_set_varpool_encoder_encode_initializer (varpool_encoder, vnode);
+      add_references (encoder, varpool_encoder, &vnode->ref_list);
     }
-  /* FIXME: We do not track references, so for now we need to include all possibly
-     used variables in the encoder set.  */
+  /* FIXME: We can not currenlty remove any varpool nodes or we get ICE merging
+     binfos.  */
   for (vnode = varpool_nodes; vnode; vnode = vnode->next)
     if (vnode->needed)
       lto_varpool_encoder_encode (varpool_encoder, vnode);
@@ -617,6 +745,7 @@ output_cgraph (cgraph_node_set set, varpool_node_set vset)
              ||  TREE_READONLY (vnode->decl)))
        {
          lto_set_varpool_encoder_encode_initializer (varpool_encoder, vnode);
+         add_references (encoder, varpool_encoder, &vnode->ref_list);
        }
     }
 
@@ -672,7 +801,8 @@ output_cgraph (cgraph_node_set set, varpool_node_set vset)
   lto_output_uleb128_stream (ob->main_stream, 0);
 
   lto_destroy_simple_output_block (ob);
-  output_varpool (vset);
+  output_varpool (set, vset);
+  output_refs (set, vset, encoder, varpool_encoder);
 }
 
 /* Overwrite the information in NODE based on FILE_DATA, TAG, FLAGS,
@@ -727,7 +857,7 @@ input_overwrite_node (struct lto_file_decl_data *file_data,
 /* Output the part of the cgraph in SET.  */
 
 static void
-output_varpool (varpool_node_set vset)
+output_varpool (cgraph_node_set set, varpool_node_set vset)
 {
   struct lto_simple_output_block *ob = lto_create_simple_output_block (LTO_section_varpool);
   lto_varpool_encoder_t varpool_encoder = ob->decl_state->varpool_node_encoder;
@@ -741,7 +871,7 @@ output_varpool (varpool_node_set vset)
   for (i = 0; i < len; i++)
     {
       lto_output_varpool_node (ob, lto_varpool_encoder_deref (varpool_encoder, i),
-                              vset);
+                              set, vset);
     }
 
   lto_destroy_simple_output_block (ob);
@@ -889,6 +1019,33 @@ input_varpool_node (struct lto_file_decl_data *file_data,
   return node;
 }
 
+/* Read a node from input_block IB.  TAG is the node's tag just read.
+   Return the node read or overwriten.  */
+
+static void
+input_ref (struct lto_input_block *ib,
+          struct cgraph_node *refering_node,
+          struct varpool_node *refering_varpool_node,
+          VEC(cgraph_node_ptr, heap) *nodes,
+          VEC(varpool_node_ptr, heap) *varpool_nodes)
+{
+  struct cgraph_node *node = NULL;
+  struct varpool_node *varpool_node = NULL;
+  struct bitpack_d *bp;
+  enum ipa_ref_type type;
+  enum ipa_ref_use use;
+
+  bp = lto_input_bitpack (ib);
+  type = (enum ipa_ref_type) bp_unpack_value (bp, 1);
+  use = (enum ipa_ref_use) bp_unpack_value (bp, 2);
+  bitpack_delete (bp);
+  if (type == IPA_REF_CGRAPH)
+    node = VEC_index (cgraph_node_ptr, nodes, lto_input_sleb128 (ib));
+  else
+    varpool_node = VEC_index (varpool_node_ptr, varpool_nodes, lto_input_sleb128 (ib));
+  ipa_record_reference (refering_node, refering_varpool_node,
+                       node, varpool_node, use, NULL);
+}
 
 /* Read an edge from IB.  NODES points to a vector of previously read nodes for
    decoding caller and callee of the edge to be read.  If INDIRECT is true, the
@@ -1036,6 +1193,44 @@ input_varpool_1 (struct lto_file_decl_data *file_data,
   return varpool;
 }
 
+/* Input ipa_refs.  */
+
+static void
+input_refs (struct lto_input_block *ib,
+           VEC(cgraph_node_ptr, heap) *nodes,
+           VEC(varpool_node_ptr, heap) *varpool)
+{
+  int count;
+  int idx;
+  while (true)
+    {
+      struct cgraph_node *node;
+      count = lto_input_uleb128 (ib);
+      if (!count)
+       break;
+      idx = lto_input_uleb128 (ib);
+      node = VEC_index (cgraph_node_ptr, nodes, idx);
+      while (count)
+       {
+         input_ref (ib, node, NULL, nodes, varpool);
+         count--;
+       }
+    }
+  while (true)
+    {
+      struct varpool_node *node;
+      count = lto_input_uleb128 (ib);
+      if (!count)
+       break;
+      node = VEC_index (varpool_node_ptr, varpool, lto_input_uleb128 (ib));
+      while (count)
+       {
+         input_ref (ib, NULL, node, nodes, varpool);
+         count--;
+       }
+    }
+}
+           
 
 static struct gcov_ctr_summary lto_gcov_summary;
 
@@ -1100,6 +1295,11 @@ input_cgraph (void)
       lto_destroy_simple_input_block (file_data, LTO_section_varpool,
                                      ib, data, len);
 
+      ib = lto_create_simple_input_block (file_data, LTO_section_refs,
+                                         &data, &len);
+      input_refs (ib, nodes, varpool);
+      lto_destroy_simple_input_block (file_data, LTO_section_refs,
+                                     ib, data, len);
       VEC_free (cgraph_node_ptr, heap, nodes);
       VEC_free (varpool_node_ptr, heap, varpool);
     }
index 8c2df96..44b3e1c 100644 (file)
@@ -53,6 +53,7 @@ const char *lto_section_name[LTO_N_SECTION_TYPES] =
   "static_initializer",
   "cgraph",
   "varpool",
+  "refs",
   "jump_funcs"
   "ipa_pure_const",
   "ipa_reference",
index ec2a308..01703f1 100644 (file)
@@ -163,6 +163,9 @@ lto_get_section_name (int section_type, const char *name)
     case LTO_section_varpool:
       return concat (LTO_SECTION_NAME_PREFIX, ".vars", NULL);
 
+    case LTO_section_refs:
+      return concat (LTO_SECTION_NAME_PREFIX, ".refs", NULL);
+
     case LTO_section_jump_functions:
       return concat (LTO_SECTION_NAME_PREFIX, ".jmpfuncs", NULL);
 
index 3d8617b..4f3d60d 100644 (file)
@@ -257,6 +257,7 @@ enum lto_section_type
   LTO_section_static_initializer,
   LTO_section_cgraph,
   LTO_section_varpool,
+  LTO_section_refs,
   LTO_section_jump_functions,
   LTO_section_ipa_pure_const,
   LTO_section_ipa_reference,
@@ -855,6 +856,9 @@ bool lto_varpool_encoder_encode_initializer_p (lto_varpool_encoder_t,
                                               struct varpool_node *);
 void output_cgraph (cgraph_node_set, varpool_node_set);
 void input_cgraph (void);
+bool referenced_from_other_partition_p (struct ipa_ref_list *,
+                                       cgraph_node_set,
+                                       varpool_node_set vset);
 
 
 /* In lto-symtab.c.  */
index c9ec62e..83a64bb 100644 (file)
@@ -214,6 +214,8 @@ lto_cgraph_replace_node (struct cgraph_node *node,
       next = e->next_caller;
       cgraph_redirect_edge_callee (e, prevailing_node);
     }
+  /* Redirect incomming references.  */
+  ipa_clone_refering (prevailing_node, NULL, &node->ref_list);
 
   if (node->same_body)
     {
@@ -273,6 +275,12 @@ lto_varpool_replace_node (struct varpool_node *vnode,
   gcc_assert (!vnode->finalized || prevailing_node->finalized);
   gcc_assert (!vnode->analyzed || prevailing_node->analyzed);
 
+  /* When replacing by an alias, the references goes to the original
+     variable.  */
+  if (prevailing_node->alias && prevailing_node->extra_name)
+    prevailing_node = prevailing_node->extra_name;
+  ipa_clone_refering (NULL, prevailing_node, &vnode->ref_list);
+
   /* Finally remove the replaced node.  */
   varpool_remove_node (vnode);
 }
index 72a8028..304bf6e 100644 (file)
@@ -1,5 +1,9 @@
 2010-05-05  Jan Hubicka  <jh@suse.cz>
 
+       * lto.c (lto_promote_cross_file_statics): Compute boundary based on refs.
+
+2010-05-05  Jan Hubicka  <jh@suse.cz>
+
        * lto.c (lto_1_to_1_map): Partition only needed nodes.
 
 2010-04-30  Jan Hubicka  <jh@suse.cz>
index d653b04..44b4a84 100644 (file)
@@ -718,36 +718,30 @@ lto_promote_cross_file_statics (void)
   struct varpool_node *vnode;
   unsigned i, n_sets;
   cgraph_node_set set;
+  varpool_node_set vset;
   cgraph_node_set_iterator csi;
+  varpool_node_set_iterator vsi;
 
   gcc_assert (flag_wpa);
 
-  /* At moment we make no attempt to figure out who is refering the variables,
-     so all must become global.  
-
-     Constant pool references use internal labels and thus can not be made global.
-     It is sensible to keep those ltrans local to allow better optimization.  */
-  for (vnode = varpool_nodes; vnode; vnode = vnode->next)
-    if (!vnode->externally_visible && vnode->analyzed
-       && !DECL_IN_CONSTANT_POOL (vnode->decl))
-       {
-         TREE_PUBLIC (vnode->decl) = 1;
-         DECL_VISIBILITY (vnode->decl) = VISIBILITY_HIDDEN;
-       }
   n_sets = VEC_length (cgraph_node_set, lto_cgraph_node_sets);
   for (i = 0; i < n_sets; i++)
     {
       set = VEC_index (cgraph_node_set, lto_cgraph_node_sets, i);
+      vset = VEC_index (varpool_node_set, lto_varpool_node_sets, i);
 
       /* If node has either address taken (and we have no clue from where)
         or it is called from other partition, it needs to be globalized.  */
       for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi))
        {
          struct cgraph_node *node = csi_node (csi);
-         bool globalize = node->address_taken || node->local.vtable_method;
+         bool globalize = node->local.vtable_method;
          struct cgraph_edge *e;
          if (node->local.externally_visible)
            continue;
+         if (!globalize
+             && referenced_from_other_partition_p (&node->ref_list, set, vset))
+           globalize = true;
          for (e = node->callers; e && !globalize; e = e->next_caller)
            {
              struct cgraph_node *caller = e->caller;
@@ -758,6 +752,7 @@ lto_promote_cross_file_statics (void)
            }
          if (globalize)
             {
+               gcc_assert (flag_wpa);
                TREE_PUBLIC (node->decl) = 1;
                DECL_VISIBILITY (node->decl) = VISIBILITY_HIDDEN;
                if (node->same_body)
@@ -772,6 +767,21 @@ lto_promote_cross_file_statics (void)
                  }
             }
        }
+      for (vsi = vsi_start (vset); !vsi_end_p (vsi); vsi_next (&vsi))
+       {
+         vnode = vsi_node (vsi);
+         /* Constant pool references use internal labels and thus can not
+            be made global.  It is sensible to keep those ltrans local to
+            allow better optimization.  */
+         if (!DECL_IN_CONSTANT_POOL (vnode->decl)
+             && !vnode->externally_visible && vnode->analyzed
+             && referenced_from_other_partition_p (&vnode->ref_list, set, vset))
+           {
+             gcc_assert (flag_wpa);
+             TREE_PUBLIC (vnode->decl) = 1;
+             DECL_VISIBILITY (vnode->decl) = VISIBILITY_HIDDEN;
+           }
+       }
 
     }
 }
@@ -1457,7 +1467,7 @@ lto_fixup_tree (tree *tp, int *walk_subtrees, void *data)
 
   t = *tp;
   *walk_subtrees = 0;
-  if (pointer_set_contains (fixup_data->seen, t))
+  if (!t || pointer_set_contains (fixup_data->seen, t))
     return NULL;
 
   if (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == FUNCTION_DECL)
index 76d8f72..a540d03 100644 (file)
@@ -141,6 +141,7 @@ 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;
@@ -193,6 +194,8 @@ varpool_remove_node (struct varpool_node *node)
       gcc_assert (varpool_nodes_queue == node);
       varpool_nodes_queue = node->next_needed;
     }
+  ipa_remove_all_references (&node->ref_list);
+  ipa_remove_all_refering (&node->ref_list);
   if (DECL_INITIAL (node->decl))
     DECL_INITIAL (node->decl) = error_mark_node;
   ggc_free (node);
@@ -228,6 +231,10 @@ dump_varpool_node (FILE *f, struct varpool_node *node)
   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.  */
@@ -633,6 +640,7 @@ 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;