This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

IPA-ref infrastructure and WPA partitioning


Hi,
this is the remaining part of ipa-ref changes.  The datastructure itself, cgraphbuild
change to buid it, streaming in/out and new partitioning code in lto/lto.c and output_cgraph.
Bootstrapped/regtested x86_64-linux and tested on DLV/xalanbmk/spec200 GCC WHOR builds
OK?
Honza
	* 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.

	* lto/lto.c (lto_promote_cross_file_statics): Compute boundary based on refs.
	
Index: lto-symtab.c
===================================================================
*** lto-symtab.c	(revision 159061)
--- lto-symtab.c	(working copy)
*************** lto_cgraph_replace_node (struct cgraph_n
*** 214,219 ****
--- 214,221 ----
        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)
      {
*************** lto_varpool_replace_node (struct varpool
*** 273,278 ****
--- 275,286 ----
    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: cgraphbuild.c
===================================================================
*** cgraphbuild.c	(revision 159059)
--- cgraphbuild.c	(working copy)
*************** along with GCC; see the file COPYING3.  
*** 37,42 ****
--- 37,43 ----
  struct record_reference_ctx
  {
    bool only_vars;
+   struct varpool_node *varpool_node;
  };
  
  /* Walk tree and record all calls and references to functions/variables.
*************** record_reference (tree *tp, int *walk_su
*** 63,77 ****
        /* 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) == VAR_DECL)
  	{
! 	  gcc_assert (TREE_STATIC (decl) || DECL_EXTERNAL (decl));
  	  if (lang_hooks.callgraph.analyze_expr)
  	    lang_hooks.callgraph.analyze_expr (&decl, walk_subtrees);
! 	  varpool_mark_needed_node (varpool_node (decl));
  	}
        *walk_subtrees = 0;
        break;
--- 64,89 ----
        /* Record dereferences to the functions.  This makes the
  	 functions reachable unconditionally.  */
        decl = get_base_var (*tp);
!       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)
  	{
! 	  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 (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;
*************** mark_address (gimple stmt ATTRIBUTE_UNUS
*** 148,153 ****
--- 160,168 ----
      {
        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
      {
*************** mark_address (gimple stmt ATTRIBUTE_UNUS
*** 161,166 ****
--- 176,186 ----
  	  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);
  	}
      }
  
*************** mark_load (gimple stmt ATTRIBUTE_UNUSED,
*** 183,188 ****
--- 203,213 ----
        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;
  }
*************** mark_store (gimple stmt ATTRIBUTE_UNUSED
*** 203,208 ****
--- 228,238 ----
        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;
  }
*************** void
*** 299,306 ****
  record_references_in_initializer (tree decl, bool only_vars)
  {
    struct pointer_set_t *visited_nodes = pointer_set_create ();
!   struct record_reference_ctx ctx = {false};
  
    ctx.only_vars = only_vars;
    walk_tree (&DECL_INITIAL (decl), record_reference,
               &ctx, visited_nodes);
--- 329,338 ----
  record_references_in_initializer (tree decl, bool only_vars)
  {
    struct pointer_set_t *visited_nodes = pointer_set_create ();
!   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);
*************** rebuild_cgraph_edges (void)
*** 318,323 ****
--- 350,356 ----
    gimple_stmt_iterator gsi;
  
    cgraph_node_remove_callees (node);
+   ipa_remove_all_references (&node->ref_list);
  
    node->count = ENTRY_BLOCK_PTR->count;
  
Index: cgraph.c
===================================================================
*** cgraph.c	(revision 159059)
--- cgraph.c	(working copy)
*************** cgraph_create_node (void)
*** 463,468 ****
--- 463,469 ----
    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;
*************** cgraph_remove_node (struct cgraph_node *
*** 1412,1417 ****
--- 1413,1420 ----
    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);
  
*************** dump_cgraph_node (FILE *f, struct cgraph
*** 1853,1858 ****
--- 1856,1865 ----
  	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++;
*************** cgraph_clone_node (struct cgraph_node *n
*** 2081,2086 ****
--- 2088,2094 ----
    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: cgraph.h
===================================================================
*** cgraph.h	(revision 159059)
--- cgraph.h	(working copy)
*************** along with GCC; see the file COPYING3.  
*** 23,28 ****
--- 23,29 ----
  #define GCC_CGRAPH_H
  #include "tree.h"
  #include "basic-block.h"
+ #include "ipa-ref.h"
  
  enum availability
  {
*************** struct GTY((chain_next ("%h.next"), chai
*** 224,229 ****
--- 225,231 ----
       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;
*************** DEF_VEC_ALLOC_P(cgraph_edge_p,heap);
*** 427,433 ****
  /* The varpool data structure.
     Each static variable decl has assigned varpool_node.  */
  
! struct GTY((chain_next ("%h.next"))) varpool_node {
    tree decl;
    /* Pointer to the next function in varpool_nodes.  */
    struct varpool_node *next, *prev;
--- 429,435 ----
  /* The varpool data structure.
     Each static variable decl has assigned 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;
*************** struct GTY((chain_next ("%h.next"))) var
*** 436,441 ****
--- 438,444 ----
    /* 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;
  
*************** cgraph_can_remove_if_no_direct_calls_p (
*** 864,867 ****
--- 867,872 ----
  /* Constant pool accessor function.  */
  htab_t constant_pool_htab (void);
  
+ #include "ipa-ref-inline.h"
+ 
  #endif  /* GCC_CGRAPH_H  */
Index: ipa-ref.c
===================================================================
*** ipa-ref.c	(revision 159062)
--- ipa-ref.c	(working copy)
***************
*** 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: ipa-ref.h
===================================================================
*** ipa-ref.h	(revision 159062)
--- ipa-ref.h	(working copy)
***************
*** 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: lto-cgraph.c
===================================================================
*** lto-cgraph.c	(revision 159062)
--- lto-cgraph.c	(working copy)
*************** along with GCC; see the file COPYING3.  
*** 46,52 ****
  #include "lto-streamer.h"
  #include "gcov-io.h"
  
! static void output_varpool (varpool_node_set);
  
  /* Cgraph streaming is organized as set of record whose type
     is indicated by a tag.  */
--- 46,52 ----
  #include "lto-streamer.h"
  #include "gcov-io.h"
  
! 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.  */
*************** lto_output_edge (struct lto_simple_outpu
*** 286,291 ****
--- 286,315 ----
    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
*************** lto_output_node (struct lto_simple_outpu
*** 460,468 ****
  
  static void
  lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node *node,
! 		         varpool_node_set set)
  {
!   bool boundary_p = !varpool_node_in_set_p (node, set) && node->analyzed;
    struct bitpack_d *bp;
    struct varpool_node *alias;
    int count = 0;
--- 484,492 ----
  
  static void
  lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node *node,
! 		         cgraph_node_set set, varpool_node_set vset)
  {
!   bool boundary_p = !varpool_node_in_set_p (node, vset) && node->analyzed;
    struct bitpack_d *bp;
    struct varpool_node *alias;
    int count = 0;
*************** lto_output_varpool_node (struct lto_simp
*** 472,480 ****
    bp_pack_value (bp, node->externally_visible, 1);
    bp_pack_value (bp, node->force_output, 1);
    bp_pack_value (bp, node->finalized, 1);
    gcc_assert (node->finalized || !node->analyzed);
    gcc_assert (node->needed);
-   gcc_assert (!node->alias);
    /* Constant pool initializers can be de-unified into individual ltrans units.
       FIXME: Alternatively at -Os we may want to avoid generating for them the local
       labels and share them across LTRANS partitions.  */
--- 496,505 ----
    bp_pack_value (bp, node->externally_visible, 1);
    bp_pack_value (bp, node->force_output, 1);
    bp_pack_value (bp, node->finalized, 1);
+   bp_pack_value (bp, node->alias, 1);
+   gcc_assert (!node->alias || !node->extra_name);
    gcc_assert (node->finalized || !node->analyzed);
    gcc_assert (node->needed);
    /* Constant pool initializers can be de-unified into individual ltrans units.
       FIXME: Alternatively at -Os we may want to avoid generating for them the local
       labels and share them across LTRANS partitions.  */
*************** lto_output_varpool_node (struct lto_simp
*** 485,493 ****
      }
    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, boundary_p, 1);  /* in_other_partition.  */
      }
    /* Also emit any extra name aliases.  */
--- 510,518 ----
      }
    else
      {
!       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.  */
*************** lto_output_varpool_node (struct lto_simp
*** 505,510 ****
--- 530,563 ----
      }
  }
  
+ /* 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
*************** add_node_to (lto_cgraph_encoder_t encode
*** 533,538 ****
--- 586,610 ----
    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.  */
  
*************** output_outgoing_cgraph_edges (struct cgr
*** 554,559 ****
--- 626,686 ----
  
  /* 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)
  {
*************** output_cgraph (cgraph_node_set set, varp
*** 567,573 ****
    lto_cgraph_encoder_t encoder;
    lto_varpool_encoder_t varpool_encoder;
    struct cgraph_asm_node *can;
-   struct varpool_node *vnode;
  
    ob = lto_create_simple_output_block (LTO_section_cgraph);
  
--- 694,699 ----
*************** output_cgraph (cgraph_node_set set, varp
*** 590,595 ****
--- 716,722 ----
      {
        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))
      {
*************** output_cgraph (cgraph_node_set set, varp
*** 597,608 ****
        gcc_assert (!vnode->alias);
        lto_varpool_encoder_encode (varpool_encoder, vnode);
        lto_set_varpool_encoder_encode_initializer (varpool_encoder, vnode);
      }
-   /* FIXME: We do not track references, so for now we need to include all possibly
-      used variables in the encoder set.  */
-   for (vnode = varpool_nodes; vnode; vnode = vnode->next)
-     if (vnode->needed)
-       lto_varpool_encoder_encode (varpool_encoder, vnode);
    /* Pickle in also the initializer of all referenced readonly variables
       to help folding.  Constant pool variables are not shared, so we must
       pickle those too.  */
--- 724,731 ----
        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);
      }
    /* Pickle in also the initializer of all referenced readonly variables
       to help folding.  Constant pool variables are not shared, so we must
       pickle those too.  */
*************** output_cgraph (cgraph_node_set set, varp
*** 616,621 ****
--- 739,745 ----
  	      ||  TREE_READONLY (vnode->decl)))
  	{
  	  lto_set_varpool_encoder_encode_initializer (varpool_encoder, vnode);
+ 	  add_references (encoder, varpool_encoder, &vnode->ref_list);
  	}
      }
  
*************** output_cgraph (cgraph_node_set set, varp
*** 671,677 ****
    lto_output_uleb128_stream (ob->main_stream, 0);
  
    lto_destroy_simple_output_block (ob);
!   output_varpool (vset);
  }
  
  /* Overwrite the information in NODE based on FILE_DATA, TAG, FLAGS,
--- 795,802 ----
    lto_output_uleb128_stream (ob->main_stream, 0);
  
    lto_destroy_simple_output_block (ob);
!   output_varpool (set, vset);
!   output_refs (set, vset, encoder, varpool_encoder);
  }
  
  /* Overwrite the information in NODE based on FILE_DATA, TAG, FLAGS,
*************** input_overwrite_node (struct lto_file_de
*** 726,732 ****
  /* Output the part of the cgraph in SET.  */
  
  static void
! output_varpool (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;
--- 851,857 ----
  /* Output the part of the cgraph in SET.  */
  
  static void
! 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;
*************** output_varpool (varpool_node_set vset)
*** 740,746 ****
    for (i = 0; i < len; i++)
      {
        lto_output_varpool_node (ob, lto_varpool_encoder_deref (varpool_encoder, i),
! 			       vset);
      }
  
    lto_destroy_simple_output_block (ob);
--- 865,871 ----
    for (i = 0; i < len; i++)
      {
        lto_output_varpool_node (ob, lto_varpool_encoder_deref (varpool_encoder, i),
! 			       set, vset);
      }
  
    lto_destroy_simple_output_block (ob);
*************** input_varpool_node (struct lto_file_decl
*** 867,872 ****
--- 992,998 ----
    node->externally_visible = bp_unpack_value (bp, 1);
    node->force_output = bp_unpack_value (bp, 1);
    node->finalized = bp_unpack_value (bp, 1);
+   node->alias = bp_unpack_value (bp, 1);
    node->analyzed = node->finalized; 
    node->used_from_other_partition = bp_unpack_value (bp, 1);
    node->in_other_partition = bp_unpack_value (bp, 1);
*************** input_varpool_node (struct lto_file_decl
*** 887,892 ****
--- 1013,1045 ----
    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
*************** input_varpool_1 (struct lto_file_decl_da
*** 1034,1039 ****
--- 1187,1230 ----
    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;
  
*************** input_cgraph (void)
*** 1098,1103 ****
--- 1289,1299 ----
        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: ipa-ref-inline.h
===================================================================
*** ipa-ref-inline.h	(revision 159062)
--- ipa-ref-inline.h	(working copy)
***************
*** 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: lto-section-in.c
===================================================================
*** lto-section-in.c	(revision 159059)
--- lto-section-in.c	(working copy)
*************** const char *lto_section_name[LTO_N_SECTI
*** 53,58 ****
--- 53,59 ----
    "static_initializer",
    "cgraph",
    "varpool",
+   "refs",
    "jump_funcs"
    "ipa_pure_const",
    "ipa_reference",
Index: lto/lto.c
===================================================================
*** lto/lto.c	(revision 159062)
--- lto/lto.c	(working copy)
*************** lto_promote_cross_file_statics (void)
*** 718,753 ****
    struct varpool_node *vnode;
    unsigned i, n_sets;
    cgraph_node_set set;
    cgraph_node_set_iterator csi;
  
    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);
  
        /* 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;
  	  struct cgraph_edge *e;
  	  if (node->local.externally_visible)
  	    continue;
  	  for (e = node->callers; e && !globalize; e = e->next_caller)
  	    {
  	      struct cgraph_node *caller = e->caller;
--- 718,747 ----
    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);
  
    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->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;
*************** lto_promote_cross_file_statics (void)
*** 758,763 ****
--- 752,758 ----
  	    }
  	  if (globalize)
  	     {
+ 		gcc_assert (flag_wpa);
  		TREE_PUBLIC (node->decl) = 1;
  		DECL_VISIBILITY (node->decl) = VISIBILITY_HIDDEN;
  		if (node->same_body)
*************** lto_promote_cross_file_statics (void)
*** 772,777 ****
--- 767,787 ----
  		  }
  	     }
  	}
+       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;
+ 	    }
+ 	}
  
      }
  }
Index: Makefile.in
===================================================================
*** Makefile.in	(revision 159059)
--- Makefile.in	(working copy)
*************** CFGLOOP_H = cfgloop.h $(BASIC_BLOCK_H) $
*** 904,910 ****
  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
  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)
--- 904,910 ----
  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 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)
*************** OBJS-archive = \
*** 1425,1430 ****
--- 1425,1431 ----
  	ipa-prop.o \
  	ipa-pure-const.o \
  	ipa-reference.o \
+ 	ipa-ref.o \
  	ipa-struct-reorg.o \
  	ipa-type-escape.o \
  	ipa-utils.o \
*************** ipa-prop.o : ipa-prop.c $(CONFIG_H) $(SY
*** 2902,2907 ****
--- 2903,2911 ----
     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) \
*************** GTFILES = $(CPP_ID_DATA_H) $(srcdir)/inp
*** 3584,3590 ****
    $(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)/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 \
--- 3588,3594 ----
    $(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)/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: varpool.c
===================================================================
*** varpool.c	(revision 159059)
--- varpool.c	(working copy)
*************** varpool_node (tree decl)
*** 141,146 ****
--- 141,147 ----
    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;
*************** varpool_remove_node (struct varpool_node
*** 193,198 ****
--- 194,201 ----
        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);
*************** dump_varpool_node (FILE *f, struct varpo
*** 228,233 ****
--- 231,240 ----
    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.  */
*************** varpool_extra_name_alias (tree alias, tr
*** 633,638 ****
--- 640,646 ----
    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;
Index: lto-streamer.c
===================================================================
*** lto-streamer.c	(revision 159059)
--- lto-streamer.c	(working copy)
*************** lto_get_section_name (int section_type, 
*** 163,168 ****
--- 163,171 ----
      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: lto-streamer.h
===================================================================
*** lto-streamer.h	(revision 159062)
--- lto-streamer.h	(working copy)
*************** enum lto_section_type
*** 257,262 ****
--- 257,263 ----
    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,
*************** bool lto_varpool_encoder_encode_initiali
*** 855,860 ****
--- 856,864 ----
  					       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 Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]