diff mbox

IPA REF: refactoring

Message ID 53A84416.6030505@suse.cz
State New
Headers show

Commit Message

Martin Liška June 23, 2014, 3:13 p.m. UTC
Hello,
    this patch changes IPA REF API to c++ style. Changes were suggested and consulted with Honza.

Patch has been pre approved, will be committed if no comments.
Bootstrapped on x86_64-pc-linux-gnu, no regressions.

Thanks,
Martin

ChangeLog:
2014-06-22  Martin Liska  <mliska@suse.cz>

     * Makefile.in: Removed header file (ipa-ref-inline.h).
     * cgraph.c (cgraph_turn_edge_to_speculative): New IPA REF function
     called.
     (cgraph_speculative_call_info): Likewise.
     (cgraph_for_node_thunks_and_aliases): Likewise.
     (cgraph_for_node_and_aliases): Likewise.
     (verify_cgraph_node): Likewise.
     * cgraph.h: Batch of IPA REF functions become member functions of
     symtab_node: add_reference, maybe_add_reference, clone_references,
     clone_referring, clone_reference, find_reference,
     remove_stmt_references, remove_all_references,
     remove_all_referring, dump_references, dump_referring,
     has_alias_p, iterate_reference, iterate_referring.
     * cgraphbuild.c (record_reference): New IPA REF function used.
     (record_type_list): Likewise.
     (record_eh_tables): Likewise.
     (mark_address): Likewise.
     (mark_load): Likewise.
     (mark_store): Likewise.
     (pass_build_cgraph_edges): Likewise.
     (rebuild_cgraph_edge): Likewise.
     (cgraph_rebuild_references): Likewise.
     (pass_remove_cgraph_callee_edges): Likewise.
     * cgraphclones.c (cgraph_clone_node): Likewise.
     (cgraph_create_virtual_clone): Likewise.
     (cgraph_materialize_clone): Likewise.
     (cgraph_materialize_all_clones): Likewise.
     * cgraphunit.c (cgraph_reset_node): Likewise.
     (cgraph_reset_node): Likewise.
     (analyze_function): Likewise.
     (assemble_thunks_and_aliases): Likewise.
     (expand_function): Likewise.
     * ipa-comdats.c (propagate_comdat_group): Likewise.
     (enqueue_references): Likewise.
     * ipa-cp.c (ipcp_discover_new_direct_edges): Likewise.
     (create_specialized_node): Likewise.
     * ipa-devirt.c (referenced_from_vtable_p): Likewise.
     * ipa-inline-transform.c (can_remove_node_now_p_1): Likewise.
     * ipa-inline.c (reset_edge_caches): Likewise.
     (update_caller_keys): Likewise.
     (execute): Likewise.
     * ipa-prop.c (remove_described_reference): Likewise.
     (propagate_controlled_uses): Likewise.
     (ipa_edge_duplication_hook): Likewise.
     (ipa_modify_call_arguments): Likewise.
     * ipa-pure-const.c (propagate_pure_const): Likewise.
     * ipa-ref-inline.h: Header file removed, functions moved
     to symtab_node class.
     * ipa-ref.c (remove_reference): New class member function.
     (cannot_lead_to_return): New class member function.
     (referring_ref_list): Likewise.
     (referred_ref_list): Likewise.
     Rest of functions moved to symtab_node class.
     * ipa-ref.h: New member functions remove_reference,
     cannot_lead_to_return, referring_ref_list, referred_ref_list added
     to ipa_ref class.
     ipa_ref_list class has new member functions: first_reference,
     first_referring, clear, nreferences.
     * ipa-reference.c (analyze_function): New IPA REF function used.
     (write_node_summary_p): Likewise.
     (ipa_reference_write_optimization_summary): Likewise.
     * ipa-split.c (split_function): Likewise.
     * ipa-utils.c (ipa_reverse_postorder): Likewise.
     * ipa-visibility.c (cgraph_non_local_node_p_1): Likewise.
     (function_and_variable_visibility): Likewise.
     * ipa.c (has_addr_references_p): Likewise.
     (process_references): Argument type changed.
     (symtab_remove_unreachable_nodes): New IPA REF function used.
     (process_references): Likewise.
     (set_writeonly_bit): Likewise.
     * lto-cgraph.c: Implementation of new symtab_node member functions
     that uses new IPA REF functions.
     * lto-streamer-in.c (fixup_call_stmt_edges_1): New IPA REF function used.
     * lto-streamer-out.c (output_symbol_p): Likewise.
     * lto-streamer.h (referenced_from_this_partition_p): Argument type
     changed.
     * lto/lto-partition.c (add_references_to_partition): New IPA REF function
     used.
     (add_symbol_to_partition_1): Likewise.
     (lto_balanced_map): Likewise.
     * lto/lto-symtab.c (lto_cgraph_replace_node): Likewise.
     * symtab.c: Implementation of new IPA REF API.
     * trans-mem.c (ipa_tm_create_version_alias): New IPA REF function used.
     (ipa_tm_create_version): Likewise.
     (ipa_tm_execute): Likewise.
     * tree-emutls.c (gen_emutls_addr): Likewise.
     * tree-inline.c (copy_bb): Likewise.
     (delete_unreachable_blocks_update_callgraph): Likewise.
     * varpool.c (varpool_remove_unreferenced_decls): Likewise.
     (varpool_for_node_and_aliases): Likewise.

Comments

Jan Hubicka June 24, 2014, 6:21 p.m. UTC | #1
> Hello,
>    this patch changes IPA REF API to c++ style. Changes were suggested and consulted with Honza.
> 
> Patch has been pre approved, will be committed if no comments.
> Bootstrapped on x86_64-pc-linux-gnu, no regressions.
> 
> Thanks,
> Martin
> 
> ChangeLog:
> 2014-06-22  Martin Liska  <mliska@suse.cz>
> 
>     * Makefile.in: Removed header file (ipa-ref-inline.h).
>     * cgraph.c (cgraph_turn_edge_to_speculative): New IPA REF function
>     called.
>     (cgraph_speculative_call_info): Likewise.
>     (cgraph_for_node_thunks_and_aliases): Likewise.
>     (cgraph_for_node_and_aliases): Likewise.
>     (verify_cgraph_node): Likewise.
>     * cgraph.h: Batch of IPA REF functions become member functions of
>     symtab_node: add_reference, maybe_add_reference, clone_references,
>     clone_referring, clone_reference, find_reference,
>     remove_stmt_references, remove_all_references,
>     remove_all_referring, dump_references, dump_referring,
>     has_alias_p, iterate_reference, iterate_referring.
>     * cgraphbuild.c (record_reference): New IPA REF function used.
>     (record_type_list): Likewise.
>     (record_eh_tables): Likewise.
>     (mark_address): Likewise.
>     (mark_load): Likewise.
>     (mark_store): Likewise.
>     (pass_build_cgraph_edges): Likewise.
>     (rebuild_cgraph_edge): Likewise.
>     (cgraph_rebuild_references): Likewise.
>     (pass_remove_cgraph_callee_edges): Likewise.
>     * cgraphclones.c (cgraph_clone_node): Likewise.
>     (cgraph_create_virtual_clone): Likewise.
>     (cgraph_materialize_clone): Likewise.
>     (cgraph_materialize_all_clones): Likewise.
>     * cgraphunit.c (cgraph_reset_node): Likewise.
>     (cgraph_reset_node): Likewise.
>     (analyze_function): Likewise.
>     (assemble_thunks_and_aliases): Likewise.
>     (expand_function): Likewise.
>     * ipa-comdats.c (propagate_comdat_group): Likewise.
>     (enqueue_references): Likewise.
>     * ipa-cp.c (ipcp_discover_new_direct_edges): Likewise.
>     (create_specialized_node): Likewise.
>     * ipa-devirt.c (referenced_from_vtable_p): Likewise.
>     * ipa-inline-transform.c (can_remove_node_now_p_1): Likewise.
>     * ipa-inline.c (reset_edge_caches): Likewise.
>     (update_caller_keys): Likewise.
>     (execute): Likewise.
>     * ipa-prop.c (remove_described_reference): Likewise.
>     (propagate_controlled_uses): Likewise.
>     (ipa_edge_duplication_hook): Likewise.
>     (ipa_modify_call_arguments): Likewise.
>     * ipa-pure-const.c (propagate_pure_const): Likewise.
>     * ipa-ref-inline.h: Header file removed, functions moved
>     to symtab_node class.
>     * ipa-ref.c (remove_reference): New class member function.
>     (cannot_lead_to_return): New class member function.
>     (referring_ref_list): Likewise.
>     (referred_ref_list): Likewise.
>     Rest of functions moved to symtab_node class.
>     * ipa-ref.h: New member functions remove_reference,
>     cannot_lead_to_return, referring_ref_list, referred_ref_list added
>     to ipa_ref class.
>     ipa_ref_list class has new member functions: first_reference,
>     first_referring, clear, nreferences.
>     * ipa-reference.c (analyze_function): New IPA REF function used.
>     (write_node_summary_p): Likewise.
>     (ipa_reference_write_optimization_summary): Likewise.
>     * ipa-split.c (split_function): Likewise.
>     * ipa-utils.c (ipa_reverse_postorder): Likewise.
>     * ipa-visibility.c (cgraph_non_local_node_p_1): Likewise.
>     (function_and_variable_visibility): Likewise.
>     * ipa.c (has_addr_references_p): Likewise.
>     (process_references): Argument type changed.
>     (symtab_remove_unreachable_nodes): New IPA REF function used.
>     (process_references): Likewise.
>     (set_writeonly_bit): Likewise.
>     * lto-cgraph.c: Implementation of new symtab_node member functions
>     that uses new IPA REF functions.
>     * lto-streamer-in.c (fixup_call_stmt_edges_1): New IPA REF function used.
>     * lto-streamer-out.c (output_symbol_p): Likewise.
>     * lto-streamer.h (referenced_from_this_partition_p): Argument type
>     changed.
>     * lto/lto-partition.c (add_references_to_partition): New IPA REF function
>     used.
>     (add_symbol_to_partition_1): Likewise.
>     (lto_balanced_map): Likewise.
>     * lto/lto-symtab.c (lto_cgraph_replace_node): Likewise.
>     * symtab.c: Implementation of new IPA REF API.
>     * trans-mem.c (ipa_tm_create_version_alias): New IPA REF function used.
>     (ipa_tm_create_version): Likewise.
>     (ipa_tm_execute): Likewise.
>     * tree-emutls.c (gen_emutls_addr): Likewise.
>     * tree-inline.c (copy_bb): Likewise.
>     (delete_unreachable_blocks_update_callgraph): Likewise.
>     * varpool.c (varpool_remove_unreferenced_decls): Likewise.
>     (varpool_for_node_and_aliases): Likewise.

Patch is OK. Thanks a lot for working on it.
Note that I added the single_use pass that walks refs, so you need to update it too
before commiting.
Martin Liška June 25, 2014, 4:57 p.m. UTC | #2
On 06/24/2014 08:21 PM, Jan Hubicka wrote:
>> Hello,
>>     this patch changes IPA REF API to c++ style. Changes were suggested and consulted with Honza.
>>
>> Patch has been pre approved, will be committed if no comments.
>> Bootstrapped on x86_64-pc-linux-gnu, no regressions.
>>
>> Thanks,
>> Martin
>>
>> ChangeLog:
>> 2014-06-22  Martin Liska  <mliska@suse.cz>
>>
>>      * Makefile.in: Removed header file (ipa-ref-inline.h).
>>      * cgraph.c (cgraph_turn_edge_to_speculative): New IPA REF function
>>      called.
>>      (cgraph_speculative_call_info): Likewise.
>>      (cgraph_for_node_thunks_and_aliases): Likewise.
>>      (cgraph_for_node_and_aliases): Likewise.
>>      (verify_cgraph_node): Likewise.
>>      * cgraph.h: Batch of IPA REF functions become member functions of
>>      symtab_node: add_reference, maybe_add_reference, clone_references,
>>      clone_referring, clone_reference, find_reference,
>>      remove_stmt_references, remove_all_references,
>>      remove_all_referring, dump_references, dump_referring,
>>      has_alias_p, iterate_reference, iterate_referring.
>>      * cgraphbuild.c (record_reference): New IPA REF function used.
>>      (record_type_list): Likewise.
>>      (record_eh_tables): Likewise.
>>      (mark_address): Likewise.
>>      (mark_load): Likewise.
>>      (mark_store): Likewise.
>>      (pass_build_cgraph_edges): Likewise.
>>      (rebuild_cgraph_edge): Likewise.
>>      (cgraph_rebuild_references): Likewise.
>>      (pass_remove_cgraph_callee_edges): Likewise.
>>      * cgraphclones.c (cgraph_clone_node): Likewise.
>>      (cgraph_create_virtual_clone): Likewise.
>>      (cgraph_materialize_clone): Likewise.
>>      (cgraph_materialize_all_clones): Likewise.
>>      * cgraphunit.c (cgraph_reset_node): Likewise.
>>      (cgraph_reset_node): Likewise.
>>      (analyze_function): Likewise.
>>      (assemble_thunks_and_aliases): Likewise.
>>      (expand_function): Likewise.
>>      * ipa-comdats.c (propagate_comdat_group): Likewise.
>>      (enqueue_references): Likewise.
>>      * ipa-cp.c (ipcp_discover_new_direct_edges): Likewise.
>>      (create_specialized_node): Likewise.
>>      * ipa-devirt.c (referenced_from_vtable_p): Likewise.
>>      * ipa-inline-transform.c (can_remove_node_now_p_1): Likewise.
>>      * ipa-inline.c (reset_edge_caches): Likewise.
>>      (update_caller_keys): Likewise.
>>      (execute): Likewise.
>>      * ipa-prop.c (remove_described_reference): Likewise.
>>      (propagate_controlled_uses): Likewise.
>>      (ipa_edge_duplication_hook): Likewise.
>>      (ipa_modify_call_arguments): Likewise.
>>      * ipa-pure-const.c (propagate_pure_const): Likewise.
>>      * ipa-ref-inline.h: Header file removed, functions moved
>>      to symtab_node class.
>>      * ipa-ref.c (remove_reference): New class member function.
>>      (cannot_lead_to_return): New class member function.
>>      (referring_ref_list): Likewise.
>>      (referred_ref_list): Likewise.
>>      Rest of functions moved to symtab_node class.
>>      * ipa-ref.h: New member functions remove_reference,
>>      cannot_lead_to_return, referring_ref_list, referred_ref_list added
>>      to ipa_ref class.
>>      ipa_ref_list class has new member functions: first_reference,
>>      first_referring, clear, nreferences.
>>      * ipa-reference.c (analyze_function): New IPA REF function used.
>>      (write_node_summary_p): Likewise.
>>      (ipa_reference_write_optimization_summary): Likewise.
>>      * ipa-split.c (split_function): Likewise.
>>      * ipa-utils.c (ipa_reverse_postorder): Likewise.
>>      * ipa-visibility.c (cgraph_non_local_node_p_1): Likewise.
>>      (function_and_variable_visibility): Likewise.
>>      * ipa.c (has_addr_references_p): Likewise.
>>      (process_references): Argument type changed.
>>      (symtab_remove_unreachable_nodes): New IPA REF function used.
>>      (process_references): Likewise.
>>      (set_writeonly_bit): Likewise.
>>      * lto-cgraph.c: Implementation of new symtab_node member functions
>>      that uses new IPA REF functions.
>>      * lto-streamer-in.c (fixup_call_stmt_edges_1): New IPA REF function used.
>>      * lto-streamer-out.c (output_symbol_p): Likewise.
>>      * lto-streamer.h (referenced_from_this_partition_p): Argument type
>>      changed.
>>      * lto/lto-partition.c (add_references_to_partition): New IPA REF function
>>      used.
>>      (add_symbol_to_partition_1): Likewise.
>>      (lto_balanced_map): Likewise.
>>      * lto/lto-symtab.c (lto_cgraph_replace_node): Likewise.
>>      * symtab.c: Implementation of new IPA REF API.
>>      * trans-mem.c (ipa_tm_create_version_alias): New IPA REF function used.
>>      (ipa_tm_create_version): Likewise.
>>      (ipa_tm_execute): Likewise.
>>      * tree-emutls.c (gen_emutls_addr): Likewise.
>>      * tree-inline.c (copy_bb): Likewise.
>>      (delete_unreachable_blocks_update_callgraph): Likewise.
>>      * varpool.c (varpool_remove_unreferenced_decls): Likewise.
>>      (varpool_for_node_and_aliases): Likewise.
> Patch is OK. Thanks a lot for working on it.
> Note that I added the single_use pass that walks refs, so you need to update it too
> before commiting.
Thank you for your notice, patch has been just commited.

Martin
diff mbox

Patch

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 5587b75..c950273 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -905,7 +905,7 @@  CFGLOOP_H = cfgloop.h $(BASIC_BLOCK_H) double-int.h \
 IPA_UTILS_H = ipa-utils.h $(TREE_H) $(CGRAPH_H)
 IPA_REFERENCE_H = ipa-reference.h $(BITMAP_H) $(TREE_H)
 CGRAPH_H = cgraph.h $(VEC_H) $(TREE_H) $(BASIC_BLOCK_H) $(FUNCTION_H) \
-	cif-code.def ipa-ref.h ipa-ref-inline.h $(LINKER_PLUGIN_API_H) is-a.h
+	cif-code.def ipa-ref.h $(LINKER_PLUGIN_API_H) is-a.h
 DF_H = df.h $(BITMAP_H) $(REGSET_H) sbitmap.h $(BASIC_BLOCK_H) \
 	alloc-pool.h $(TIMEVAR_H)
 RESOURCE_H = resource.h hard-reg-set.h $(DF_H)
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index afd41b7..7360f77 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -1101,7 +1101,7 @@  cgraph_turn_edge_to_speculative (struct cgraph_edge *e,
 				 int direct_frequency)
 {
   struct cgraph_node *n = e->caller;
-  struct ipa_ref *ref;
+  struct ipa_ref *ref = NULL;
   struct cgraph_edge *e2;
 
   if (dump_file)
@@ -1123,8 +1123,7 @@  cgraph_turn_edge_to_speculative (struct cgraph_edge *e,
   e->count -= e2->count;
   e->frequency -= e2->frequency;
   cgraph_call_edge_duplication_hooks (e, e2);
-  ref = ipa_record_reference (n, n2,
-			      IPA_REF_ADDR, e->call_stmt);
+  ref = n->add_reference (n2, IPA_REF_ADDR, e->call_stmt);
   ref->lto_stmt_uid = e->lto_stmt_uid;
   ref->speculative = e->speculative;
   cgraph_mark_address_taken_node (n2);
@@ -1177,8 +1176,7 @@  cgraph_speculative_call_info (struct cgraph_edge *e,
   indirect = e2;
 
   reference = NULL;
-  for (i = 0; ipa_ref_list_reference_iterate (&e->caller->ref_list,
-					      i, ref); i++)
+  for (i = 0; e->caller->iterate_reference (i, ref); i++)
     if (ref->speculative
 	&& ((ref->stmt && ref->stmt == e->call_stmt)
 	    || (!ref->stmt && ref->lto_stmt_uid == e->lto_stmt_uid)))
@@ -1257,7 +1255,7 @@  cgraph_resolve_speculation (struct cgraph_edge *edge, tree callee_decl)
     edge->frequency = CGRAPH_FREQ_MAX;
   edge->speculative = false;
   e2->speculative = false;
-  ipa_remove_reference (ref);
+  ref->remove_reference ();
   if (e2->indirect_unknown_callee || e2->inline_failed)
     cgraph_remove_edge (e2);
   else
@@ -2197,7 +2195,7 @@  cgraph_for_node_thunks_and_aliases (struct cgraph_node *node,
 {
   struct cgraph_edge *e;
   int i;
-  struct ipa_ref *ref;
+  struct ipa_ref *ref = NULL;
 
   if (callback (node, data))
     return true;
@@ -2208,10 +2206,10 @@  cgraph_for_node_thunks_and_aliases (struct cgraph_node *node,
       if (cgraph_for_node_thunks_and_aliases (e->caller, callback, data,
 					      include_overwritable))
 	return true;
-  for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list, i, ref); i++)
+  for (i = 0; node->iterate_referring (i, ref); i++)
     if (ref->use == IPA_REF_ALIAS)
       {
-	struct cgraph_node *alias = ipa_ref_referring_node (ref);
+	struct cgraph_node *alias = dyn_cast <cgraph_node *> (ref->referring);
 	if (include_overwritable
 	    || cgraph_function_body_availability (alias) > AVAIL_OVERWRITABLE)
 	  if (cgraph_for_node_thunks_and_aliases (alias, callback, data,
@@ -2232,14 +2230,14 @@  cgraph_for_node_and_aliases (struct cgraph_node *node,
 			     bool include_overwritable)
 {
   int i;
-  struct ipa_ref *ref;
+  struct ipa_ref *ref = NULL;
 
   if (callback (node, data))
     return true;
-  for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list, i, ref); i++)
+  for (i = 0; node->iterate_referring (i, ref); i++)
     if (ref->use == IPA_REF_ALIAS)
       {
-	struct cgraph_node *alias = ipa_ref_referring_node (ref);
+	struct cgraph_node *alias = dyn_cast <cgraph_node *> (ref->referring);
 	if (include_overwritable
 	    || cgraph_function_body_availability (alias) > AVAIL_OVERWRITABLE)
           if (cgraph_for_node_and_aliases (alias, callback, data,
@@ -2843,15 +2841,14 @@  verify_cgraph_node (struct cgraph_node *node)
     {
       bool ref_found = false;
       int i;
-      struct ipa_ref *ref;
+      struct ipa_ref *ref = NULL;
 
       if (node->callees)
 	{
 	  error ("Alias has call edges");
           error_found = true;
 	}
-      for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list,
-						  i, ref); i++)
+      for (i = 0; node->iterate_reference (i, ref); i++)
 	if (ref->use != IPA_REF_ALIAS)
 	  {
 	    error ("Alias has non-alias reference");
@@ -2897,7 +2894,7 @@  verify_cgraph_node (struct cgraph_node *node)
 	{
 	  pointer_set_t *stmts = pointer_set_create ();
 	  int i;
-	  struct ipa_ref *ref;
+	  struct ipa_ref *ref = NULL;
 
 	  /* Reach the trees by walking over the CFG, and note the
 	     enclosing basic-blocks in the call edges.  */
@@ -2955,8 +2952,7 @@  verify_cgraph_node (struct cgraph_node *node)
 		}
 	      }
 	    for (i = 0;
-		 ipa_ref_list_reference_iterate (&node->ref_list, i, ref);
-		 i++)
+		 node->iterate_reference (i, ref); i++)
 	      if (ref->stmt && !pointer_set_contains (stmts, ref->stmt))
 		{
 		  error ("reference to dead statement");
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 2fad193..3131cc2 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -189,6 +189,71 @@  public:
       return x_section->name;
     }
 
+  /* Return ipa reference from this symtab_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 *add_reference (symtab_node *referred_node,
+				enum ipa_ref_use use_type);
+
+  /* Return ipa reference from this symtab_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 *add_reference (symtab_node *referred_node,
+				 enum ipa_ref_use use_type, gimple stmt);
+
+  /* If VAL is a reference to a function or a variable, add a reference from
+     this symtab_node to the corresponding symbol table node.  USE_TYPE specify
+     type of the use and STMT the statement (if it exists).  Return the new
+     reference or NULL if none was created.  */
+  struct ipa_ref *maybe_add_reference (tree val, enum ipa_ref_use use_type,
+				       gimple stmt);
+
+  /* Clone all references from symtab NODE to this symtab_node.  */
+  void clone_references (symtab_node *node);
+
+  /* Remove all stmt references in non-speculative references.
+     Those are not maintained during inlining & clonning.
+     The exception are speculative references that are updated along
+     with callgraph edges associated with them.  */
+  void clone_referring (symtab_node *node);
+
+  /* Clone reference REF to this symtab_node and set its stmt to STMT.  */
+  struct ipa_ref *clone_reference (struct ipa_ref *ref, gimple stmt);
+
+  /* Find the structure describing a reference to REFERRED_NODE
+     and associated with statement STMT.  */
+  struct ipa_ref *find_reference (symtab_node *, gimple, unsigned int);
+
+  /* Remove all references that are associated with statement STMT.  */
+  void remove_stmt_references (gimple stmt);
+
+  /* Remove all stmt references in non-speculative references.
+     Those are not maintained during inlining & clonning.
+     The exception are speculative references that are updated along
+     with callgraph edges associated with them.  */
+  void clear_stmts_in_references (void);
+
+  /* Remove all references in ref list.  */
+  void remove_all_references (void);
+
+  /* Remove all referring items in ref list.  */
+  void remove_all_referring (void);
+
+  /* Dump references in ref list to FILE.  */
+  void dump_references (FILE *file);
+
+  /* Dump referring in list to FILE.  */
+  void dump_referring (FILE *);
+
+  /* Return true if list contains an alias.  */
+  bool has_aliases_p (void);
+
+  /* Iterates I-th reference in the list, REF is also set.  */
+  struct ipa_ref *iterate_reference (unsigned i, struct ipa_ref *&ref);
+
+  /* Iterates I-th referring item in the list, REF is also set.  */
+  struct ipa_ref *iterate_referring (unsigned i, struct ipa_ref *&ref);
+
   /* Vectors of referring and referenced entities.  */
   struct ipa_ref_list ref_list;
 
@@ -1531,16 +1596,13 @@  varpool_all_refs_explicit_p (varpool_node *vnode)
 /* Constant pool accessor function.  */
 htab_t constant_pool_htab (void);
 
-/* FIXME: inappropriate dependency of cgraph on IPA.  */
-#include "ipa-ref-inline.h"
-
 /* Return node that alias N is aliasing.  */
 
 static inline symtab_node *
 symtab_alias_target (symtab_node *n)
 {
-  struct ipa_ref *ref;
-  ipa_ref_list_reference_iterate (&n->ref_list, 0, ref);
+  struct ipa_ref *ref = NULL;
+  n->iterate_reference (0, ref);
   gcc_checking_assert (ref->use == IPA_REF_ALIAS);
   return ref->referred;
 }
diff --git a/gcc/cgraphbuild.c b/gcc/cgraphbuild.c
index 6bdc8ca..bfc4495 100644
--- a/gcc/cgraphbuild.c
+++ b/gcc/cgraphbuild.c
@@ -82,17 +82,13 @@  record_reference (tree *tp, int *walk_subtrees, void *data)
 	  struct cgraph_node *node = cgraph_get_create_node (decl);
 	  if (!ctx->only_vars)
 	    cgraph_mark_address_taken_node (node);
-	  ipa_record_reference (ctx->varpool_node,
-				node,
-			        IPA_REF_ADDR, NULL);
+	  ctx->varpool_node->add_reference (node, IPA_REF_ADDR);
 	}
 
       if (TREE_CODE (decl) == VAR_DECL)
 	{
 	  varpool_node *vnode = varpool_node_for_decl (decl);
-	  ipa_record_reference (ctx->varpool_node,
-				vnode,
-				IPA_REF_ADDR, NULL);
+	  ctx->varpool_node->add_reference (vnode, IPA_REF_ADDR);
 	}
       *walk_subtrees = 0;
       break;
@@ -129,9 +125,7 @@  record_type_list (struct cgraph_node *node, tree list)
 	  if (TREE_CODE (type) == VAR_DECL)
 	    {
 	      varpool_node *vnode = varpool_node_for_decl (type);
-	      ipa_record_reference (node,
-				    vnode,
-				    IPA_REF_ADDR, NULL);
+	      node->add_reference (vnode, IPA_REF_ADDR);
 	    }
 	}
     }
@@ -150,7 +144,7 @@  record_eh_tables (struct cgraph_node *node, struct function *fun)
       tree per_decl = DECL_FUNCTION_PERSONALITY (node->decl);
       struct cgraph_node *per_node = cgraph_get_create_node (per_decl);
 
-      ipa_record_reference (node, per_node, IPA_REF_ADDR, NULL);
+      node->add_reference (per_node, IPA_REF_ADDR);
       cgraph_mark_address_taken_node (per_node);
     }
 
@@ -231,18 +225,14 @@  mark_address (gimple stmt, tree addr, tree, void *data)
     {
       struct cgraph_node *node = cgraph_get_create_node (addr);
       cgraph_mark_address_taken_node (node);
-      ipa_record_reference ((symtab_node *)data,
-			    node,
-			    IPA_REF_ADDR, stmt);
+      ((symtab_node *)data)->add_reference (node, IPA_REF_ADDR, stmt);
     }
   else if (addr && TREE_CODE (addr) == VAR_DECL
 	   && (TREE_STATIC (addr) || DECL_EXTERNAL (addr)))
     {
       varpool_node *vnode = varpool_node_for_decl (addr);
 
-      ipa_record_reference ((symtab_node *)data,
-			    vnode,
-			    IPA_REF_ADDR, stmt);
+      ((symtab_node *)data)->add_reference (vnode, IPA_REF_ADDR, stmt);
     }
 
   return false;
@@ -260,18 +250,14 @@  mark_load (gimple stmt, tree t, tree, void *data)
 	 directly manipulated in the code.  Pretend that it's an address.  */
       struct cgraph_node *node = cgraph_get_create_node (t);
       cgraph_mark_address_taken_node (node);
-      ipa_record_reference ((symtab_node *)data,
-			    node,
-			    IPA_REF_ADDR, stmt);
+      ((symtab_node *)data)->add_reference (node, IPA_REF_ADDR, stmt);
     }
   else if (t && TREE_CODE (t) == VAR_DECL
 	   && (TREE_STATIC (t) || DECL_EXTERNAL (t)))
     {
       varpool_node *vnode = varpool_node_for_decl (t);
 
-      ipa_record_reference ((symtab_node *)data,
-			    vnode,
-			    IPA_REF_LOAD, stmt);
+      ((symtab_node *)data)->add_reference (vnode, IPA_REF_LOAD, stmt);
     }
   return false;
 }
@@ -287,9 +273,7 @@  mark_store (gimple stmt, tree t, tree, void *data)
     {
       varpool_node *vnode = varpool_node_for_decl (t);
 
-      ipa_record_reference ((symtab_node *)data,
-			    vnode,
-			    IPA_REF_STORE, stmt);
+      ((symtab_node *)data)->add_reference (vnode, IPA_REF_STORE, stmt);
      }
   return false;
 }
@@ -375,22 +359,19 @@  pass_build_cgraph_edges::execute (function *fun)
 	      && gimple_omp_parallel_child_fn (stmt))
 	    {
 	      tree fn = gimple_omp_parallel_child_fn (stmt);
-	      ipa_record_reference (node,
-				    cgraph_get_create_node (fn),
-				    IPA_REF_ADDR, stmt);
+	      node->add_reference (cgraph_get_create_node (fn),
+				      IPA_REF_ADDR, stmt);
 	    }
 	  if (gimple_code (stmt) == GIMPLE_OMP_TASK)
 	    {
 	      tree fn = gimple_omp_task_child_fn (stmt);
 	      if (fn)
-		ipa_record_reference (node,
-				      cgraph_get_create_node (fn),
-				      IPA_REF_ADDR, stmt);
+		node->add_reference (cgraph_get_create_node (fn),
+					IPA_REF_ADDR, stmt);
 	      fn = gimple_omp_task_copy_fn (stmt);
 	      if (fn)
-		ipa_record_reference (node,
-				      cgraph_get_create_node (fn),
-				      IPA_REF_ADDR, stmt);
+		node->add_reference (cgraph_get_create_node (fn),
+					IPA_REF_ADDR, stmt);
 	    }
 	}
       for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
@@ -446,7 +427,7 @@  rebuild_cgraph_edges (void)
   gimple_stmt_iterator gsi;
 
   cgraph_node_remove_callees (node);
-  ipa_remove_all_references (&node->ref_list);
+  node->remove_all_references ();
 
   node->count = ENTRY_BLOCK_PTR_FOR_FN (cfun)->count;
 
@@ -492,13 +473,13 @@  cgraph_rebuild_references (void)
   basic_block bb;
   struct cgraph_node *node = cgraph_get_node (current_function_decl);
   gimple_stmt_iterator gsi;
-  struct ipa_ref *ref;
+  struct ipa_ref *ref = NULL;
   int i;
 
   /* Keep speculative references for further cgraph edge expansion.  */
-  for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list, i, ref);)
+  for (i = 0; node->iterate_reference (i, ref);)
     if (!ref->speculative)
-      ipa_remove_reference (ref);
+      ref->remove_reference ();
     else
       i++;
 
@@ -588,7 +569,7 @@  pass_remove_cgraph_callee_edges::execute (function *)
 {
   struct cgraph_node *node = cgraph_get_node (current_function_decl);
   cgraph_node_remove_callees (node);
-  ipa_remove_all_references (&node->ref_list);
+  node->remove_all_references ();
   return 0;
 }
 
diff --git a/gcc/cgraphclones.c b/gcc/cgraphclones.c
index 6f83d74..d57cd9f 100644
--- a/gcc/cgraphclones.c
+++ b/gcc/cgraphclones.c
@@ -459,7 +459,7 @@  cgraph_clone_node (struct cgraph_node *n, tree decl, 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, update_original);
-  ipa_clone_references (new_node, &n->ref_list);
+  new_node->clone_references (n);
 
   new_node->next_sibling_clone = n->clones;
   if (n->clones)
@@ -568,8 +568,7 @@  cgraph_create_virtual_clone (struct cgraph_node *old_node,
       || in_lto_p)
     new_node->unique_name = true;
   FOR_EACH_VEC_SAFE_ELT (tree_map, i, map)
-    ipa_maybe_record_reference (new_node, map->new_tree,
-				IPA_REF_ADDR, NULL);
+    new_node->maybe_add_reference (map->new_tree, IPA_REF_ADDR, NULL);
   if (!args_to_skip)
     new_node->clone.combined_args_to_skip = old_node->clone.combined_args_to_skip;
   else if (old_node->clone.combined_args_to_skip)
@@ -1035,7 +1034,7 @@  cgraph_materialize_clone (struct cgraph_node *node)
     {
       cgraph_release_function_body (node->clone_of);
       cgraph_node_remove_callees (node->clone_of);
-      ipa_remove_all_references (&node->clone_of->ref_list);
+      node->clone_of->remove_all_references ();
     }
   node->clone_of = NULL;
   bitmap_obstack_release (NULL);
@@ -1120,10 +1119,10 @@  cgraph_materialize_all_clones (void)
     if (!node->analyzed && node->callees)
       {
         cgraph_node_remove_callees (node);
-	ipa_remove_all_references (&node->ref_list);
+	node->remove_all_references ();
       }
     else
-      ipa_clear_stmts_in_references (node);
+      node->clear_stmts_in_references ();
   if (cgraph_dump_file)
     fprintf (cgraph_dump_file, "Materialization Call site updates done.\n");
 #ifdef ENABLE_CHECKING
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 1b7ab33..76b2fda1 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -393,7 +393,7 @@  cgraph_reset_node (struct cgraph_node *node)
   node->cpp_implicit_alias = false;
 
   cgraph_node_remove_callees (node);
-  ipa_remove_all_references (&node->ref_list);
+  node->remove_all_references ();
 }
 
 /* Return true when there are references to NODE.  */
@@ -401,10 +401,10 @@  cgraph_reset_node (struct cgraph_node *node)
 static bool
 referred_to_p (symtab_node *node)
 {
-  struct ipa_ref *ref;
+  struct ipa_ref *ref = NULL;
 
   /* See if there are any references at all.  */
-  if (ipa_ref_list_referring_iterate (&node->ref_list, 0, ref))
+  if (node->iterate_referring (0, ref))
     return true;
   /* For functions check also calls.  */
   cgraph_node *cn = dyn_cast <cgraph_node *> (node);
@@ -1069,7 +1069,7 @@  analyze_functions (void)
 		   next = next->same_comdat_group)
 		enqueue_node (next);
 	    }
-	  for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list, i, ref); i++)
+	  for (i = 0; node->iterate_reference (i, ref); i++)
 	    if (ref->referred->definition)
 	      enqueue_node (ref->referred);
           cgraph_process_new_functions ();
@@ -1712,7 +1712,7 @@  assemble_thunks_and_aliases (struct cgraph_node *node)
 {
   struct cgraph_edge *e;
   int i;
-  struct ipa_ref *ref;
+  struct ipa_ref *ref = NULL;
 
   for (e = node->callers; e;)
     if (e->caller->thunk.thunk_p)
@@ -1725,11 +1725,10 @@  assemble_thunks_and_aliases (struct cgraph_node *node)
       }
     else
       e = e->next_caller;
-  for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list,
-					     i, ref); i++)
+  for (i = 0; node->iterate_referring (i, ref); i++)
     if (ref->use == IPA_REF_ALIAS)
       {
-	struct cgraph_node *alias = ipa_ref_referring_node (ref);
+	struct cgraph_node *alias = dyn_cast <cgraph_node *> (ref->referring);
         bool saved_written = TREE_ASM_WRITTEN (node->decl);
 
 	/* Force assemble_alias to really output the alias this time instead
@@ -1852,7 +1851,7 @@  expand_function (struct cgraph_node *node)
   /* Eliminate all call edges.  This is important so the GIMPLE_CALL no longer
      points to the dead function body.  */
   cgraph_node_remove_callees (node);
-  ipa_remove_all_references (&node->ref_list);
+  node->remove_all_references ();
 }
 
 /* Node comparer that is responsible for the order that corresponds
diff --git a/gcc/ipa-comdats.c b/gcc/ipa-comdats.c
index 6926900..274332c 100644
--- a/gcc/ipa-comdats.c
+++ b/gcc/ipa-comdats.c
@@ -72,7 +72,7 @@  propagate_comdat_group (struct symtab_node *symbol,
   /* Walk all references to SYMBOL, recursively dive into aliases.  */
 
   for (i = 0;
-       ipa_ref_list_referring_iterate (&symbol->ref_list, i, ref)
+       symbol->iterate_referring (i, ref)
        && newgroup != error_mark_node; i++)
     {
       struct symtab_node *symbol2 = ref->referring;
@@ -161,9 +161,9 @@  enqueue_references (symtab_node **first,
 		    symtab_node *symbol)
 {
   int i;
-  struct ipa_ref *ref;
+  struct ipa_ref *ref = NULL;
 
-  for (i = 0; ipa_ref_list_reference_iterate (&symbol->ref_list, i, ref); i++)
+  for (i = 0; symbol->iterate_reference (i, ref); i++)
     {
       symtab_node *node = symtab_alias_ultimate_target (ref->referred, NULL);
       if (!node->aux && node->definition)
diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c
index 33ff9b6..04e88b5 100644
--- a/gcc/ipa-cp.c
+++ b/gcc/ipa-cp.c
@@ -2387,14 +2387,12 @@  ipcp_discover_new_direct_edges (struct cgraph_node *node,
 		    fprintf (dump_file, "     controlled uses count of param "
 			     "%i bumped down to %i\n", param_index, c);
 		  if (c == 0
-		      && (to_del = ipa_find_reference (node,
-						       cs->callee,
-						       NULL, 0)))
+		      && (to_del = node->find_reference (cs->callee, NULL, 0)))
 		    {
 		      if (dump_file && (dump_flags & TDF_DETAILS))
 			fprintf (dump_file, "       and even removing its "
 				 "cloning-created reference\n");
-		      ipa_remove_reference (to_del);
+		      to_del->remove_reference ();
 		    }
 		}
 	    }
@@ -2803,8 +2801,7 @@  create_specialized_node (struct cgraph_node *node,
 					  args_to_skip, "constprop");
   ipa_set_node_agg_value_chain (new_node, aggvals);
   for (av = aggvals; av; av = av->next)
-    ipa_maybe_record_reference (new_node, av->value,
-				IPA_REF_ADDR, NULL);
+    new_node->maybe_add_reference (av->value, IPA_REF_ADDR, NULL);
 
   if (dump_file && (dump_flags & TDF_DETAILS))
     {
diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c
index a90d1dc..4f731a2 100644
--- a/gcc/ipa-devirt.c
+++ b/gcc/ipa-devirt.c
@@ -685,8 +685,7 @@  referenced_from_vtable_p (struct cgraph_node *node)
   if (cgraph_state <= CGRAPH_STATE_CONSTRUCTION)
     return true;
 
-  for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list,
-					      i, ref); i++)
+  for (i = 0; node->iterate_referring (i, ref); i++)
 	
     if ((ref->use == IPA_REF_ALIAS
 	 && referenced_from_vtable_p (cgraph (ref->referring)))
diff --git a/gcc/ipa-inline-transform.c b/gcc/ipa-inline-transform.c
index 4cfd87b..03442fc 100644
--- a/gcc/ipa-inline-transform.c
+++ b/gcc/ipa-inline-transform.c
@@ -86,7 +86,7 @@  can_remove_node_now_p_1 (struct cgraph_node *node)
      can remove its offline copy, but we would need to keep unanalyzed node in
      the callgraph so references can point to it.  */
   return (!node->address_taken
-	  && !ipa_ref_has_aliases_p (&node->ref_list)
+	  && !node->has_aliases_p ()
 	  && !node->used_as_abstract_origin
 	  && cgraph_can_remove_if_no_direct_calls_p (node)
 	  /* Inlining might enable more devirtualizing, so we want to remove
@@ -451,7 +451,7 @@  inline_transform (struct cgraph_node *node)
       next = e->next_callee;
       cgraph_redirect_edge_call_stmt_to_callee (e);
     }
-  ipa_remove_all_references (&node->ref_list);
+  node->remove_all_references ();
 
   timevar_push (TV_INTEGRATION);
   if (node->callees && optimize)
diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c
index 82bbd7f..81030f3 100644
--- a/gcc/ipa-inline.c
+++ b/gcc/ipa-inline.c
@@ -1120,7 +1120,7 @@  reset_edge_caches (struct cgraph_node *node)
   struct cgraph_edge *e = node->callees;
   struct cgraph_node *where = node;
   int i;
-  struct ipa_ref *ref;
+  struct ipa_ref *ref = NULL;
 
   if (where->global.inlined_to)
     where = where->global.inlined_to;
@@ -1131,10 +1131,9 @@  reset_edge_caches (struct cgraph_node *node)
   for (edge = where->callers; edge; edge = edge->next_caller)
     if (edge->inline_failed)
       reset_edge_growth_cache (edge);
-  for (i = 0; ipa_ref_list_referring_iterate (&where->ref_list,
-					      i, ref); i++)
+  for (i = 0; where->iterate_referring (i, ref); i++)
     if (ref->use == IPA_REF_ALIAS)
-      reset_edge_caches (ipa_ref_referring_node (ref));
+      reset_edge_caches (dyn_cast <cgraph_node *> (ref->referring));
 
   if (!e)
     return;
@@ -1174,7 +1173,7 @@  update_caller_keys (fibheap_t heap, struct cgraph_node *node,
 {
   struct cgraph_edge *edge;
   int i;
-  struct ipa_ref *ref;
+  struct ipa_ref *ref = NULL;
 
   if ((!node->alias && !inline_summary (node)->inlinable)
       || node->global.inlined_to)
@@ -1182,11 +1181,10 @@  update_caller_keys (fibheap_t heap, struct cgraph_node *node,
   if (!bitmap_set_bit (updated_nodes, node->uid))
     return;
 
-  for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list,
-					      i, ref); i++)
+  for (i = 0; node->iterate_referring (i, ref); i++)
     if (ref->use == IPA_REF_ALIAS)
       {
-	struct cgraph_node *alias = ipa_ref_referring_node (ref);
+	struct cgraph_node *alias = dyn_cast <cgraph_node *> (ref->referring);
         update_caller_keys (heap, alias, updated_nodes, check_inlinablity_for);
       }
 
@@ -2430,7 +2428,7 @@  pass_early_inline::execute (function *fun)
 #ifdef ENABLE_CHECKING
   verify_cgraph_node (node);
 #endif
-  ipa_remove_all_references (&node->ref_list);
+  node->remove_all_references ();
 
   /* Even when not optimizing or not inlining inline always-inline
      functions.  */
diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
index d9dca52..5f5bf89 100644
--- a/gcc/ipa-prop.c
+++ b/gcc/ipa-prop.c
@@ -2806,12 +2806,12 @@  remove_described_reference (symtab_node *symbol, struct ipa_cst_ref_desc *rdesc)
   origin = rdesc->cs;
   if (!origin)
     return false;
-  to_del = ipa_find_reference (origin->caller, symbol,
-			       origin->call_stmt, origin->lto_stmt_uid);
+  to_del = origin->caller->find_reference (symbol, origin->call_stmt,
+					   origin->lto_stmt_uid);
   if (!to_del)
     return false;
 
-  ipa_remove_reference (to_del);
+  to_del->remove_reference ();
   if (dump_file)
     fprintf (dump_file, "ipa-prop: Removed a reference from %s/%i to %s.\n",
 	     xstrdup (origin->caller->name ()),
@@ -3209,8 +3209,7 @@  propagate_controlled_uses (struct cgraph_edge *cs)
 	      if (t && TREE_CODE (t) == ADDR_EXPR
 		  && TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL
 		  && (n = cgraph_get_node (TREE_OPERAND (t, 0)))
-		  && (ref = ipa_find_reference (new_root,
-						n, NULL, 0)))
+		  && (ref = new_root->find_reference (n, NULL, 0)))
 		{
 		  if (dump_file)
 		    fprintf (dump_file, "ipa-prop: Removing cloning-created "
@@ -3218,7 +3217,7 @@  propagate_controlled_uses (struct cgraph_edge *cs)
 			     xstrdup (new_root->name ()),
 			     new_root->order,
 			     xstrdup (n->name ()), n->order);
-		  ipa_remove_reference (ref);
+		  ref->remove_reference ();
 		}
 	    }
 	}
@@ -3249,8 +3248,7 @@  propagate_controlled_uses (struct cgraph_edge *cs)
 			 && IPA_NODE_REF (clone)->ipcp_orig_node)
 		    {
 		      struct ipa_ref *ref;
-		      ref = ipa_find_reference (clone,
-						n, NULL, 0);
+		      ref = clone->find_reference (n, NULL, 0);
 		      if (ref)
 			{
 			  if (dump_file)
@@ -3261,7 +3259,7 @@  propagate_controlled_uses (struct cgraph_edge *cs)
 				     clone->order,
 				     xstrdup (n->name ()),
 				     n->order);
-			  ipa_remove_reference (ref);
+			  ref->remove_reference ();
 			}
 		      clone = clone->callers->caller;
 		    }
@@ -3455,10 +3453,10 @@  ipa_edge_duplication_hook (struct cgraph_edge *src, struct cgraph_edge *dst,
 	      struct ipa_ref *ref;
 	      symtab_node *n = cgraph_node_for_jfunc (src_jf);
 	      gcc_checking_assert (n);
-	      ref = ipa_find_reference (src->caller, n,
-					src->call_stmt, src->lto_stmt_uid);
+	      ref = src->caller->find_reference (n, src->call_stmt,
+						 src->lto_stmt_uid);
 	      gcc_checking_assert (ref);
-	      ipa_clone_ref (ref, dst->caller, ref->stmt);
+	      dst->caller->clone_reference (ref, ref->stmt);
 
 	      gcc_checking_assert (ipa_refdesc_pool);
 	      struct ipa_cst_ref_desc *dst_rdesc
@@ -3899,7 +3897,7 @@  ipa_modify_call_arguments (struct cgraph_edge *cs, gimple stmt,
   len = adjustments.length ();
   vargs.create (len);
   callee_decl = !cs ? gimple_call_fndecl (stmt) : cs->callee->decl;
-  ipa_remove_stmt_references (current_node, stmt);
+  current_node->remove_stmt_references (stmt);
 
   gsi = gsi_for_stmt (stmt);
   prev_gsi = gsi;
diff --git a/gcc/ipa-pure-const.c b/gcc/ipa-pure-const.c
index b9a3d3e..a074a11 100644
--- a/gcc/ipa-pure-const.c
+++ b/gcc/ipa-pure-const.c
@@ -1138,7 +1138,7 @@  propagate_pure_const (void)
 	  struct cgraph_edge *e;
 	  struct cgraph_edge *ie;
 	  int i;
-	  struct ipa_ref *ref;
+	  struct ipa_ref *ref = NULL;
 
 	  funct_state w_l = get_function_state (w);
 	  if (dump_file && (dump_flags & TDF_DETAILS))
@@ -1263,7 +1263,7 @@  propagate_pure_const (void)
 	    break;
 
 	  /* And finally all loads and stores.  */
-	  for (i = 0; ipa_ref_list_reference_iterate (&w->ref_list, i, ref); i++)
+	  for (i = 0; w->iterate_reference (i, ref); i++)
 	    {
 	      enum pure_const_state_e ref_state = IPA_CONST;
 	      bool ref_looping = false;
@@ -1271,14 +1271,14 @@  propagate_pure_const (void)
 		{
 		case IPA_REF_LOAD:
 		  /* readonly reads are safe.  */
-		  if (TREE_READONLY (ipa_ref_varpool_node (ref)->decl))
+		  if (TREE_READONLY (ref->referred->decl))
 		    break;
 		  if (dump_file && (dump_flags & TDF_DETAILS))
 		    fprintf (dump_file, "    nonreadonly global var read\n");
 		  ref_state = IPA_PURE;
 		  break;
 		case IPA_REF_STORE:
-		  if (ipa_ref_cannot_lead_to_return (ref))
+		  if (ref->cannot_lead_to_return ())
 		    break;
 		  ref_state = IPA_NEITHER;
 		  if (dump_file && (dump_flags & TDF_DETAILS))
diff --git a/gcc/ipa-ref-inline.h b/gcc/ipa-ref-inline.h
deleted file mode 100644
index e12fce6..0000000
--- a/gcc/ipa-ref-inline.h
+++ /dev/null
@@ -1,108 +0,0 @@ 
-/* IPA reference lists.
-   Copyright (C) 2010-2014 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 referring.  */
-static inline struct cgraph_node *
-ipa_ref_node (struct ipa_ref *ref)
-{
-  return cgraph (ref->referred);
-}
-
-/* Return varpool node REF is referring.  */
-
-static inline varpool_node *
-ipa_ref_varpool_node (struct ipa_ref *ref)
-{
-  return varpool (ref->referred);
-}
-
-/* Return cgraph node REF is in.  */
-
-static inline struct cgraph_node *
-ipa_ref_referring_node (struct ipa_ref *ref)
-{
-  return cgraph (ref->referring);
-}
-
-/* Return varpool node REF is in.  */
-
-static inline varpool_node *
-ipa_ref_referring_varpool_node (struct ipa_ref *ref)
-{
-  return varpool (ref->referring);
-}
-
-/* Return reference list REF is in.  */
-
-static inline struct ipa_ref_list *
-ipa_ref_referring_ref_list (struct ipa_ref *ref)
-{
-  return &ref->referring->ref_list;
-}
-
-/* Return reference list REF is in.  */
-
-static inline struct ipa_ref_list *
-ipa_ref_referred_ref_list (struct ipa_ref *ref)
-{
-  return &ref->referred->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_safe_length (list->references))
-    return NULL;
-  return &(*list->references)[0];
-}
-
-/* Return first referring ref in LIST or NULL if empty.  */
-
-static inline struct ipa_ref *
-ipa_ref_list_first_referring (struct ipa_ref_list *list)
-{
-  if (!list->referring.length ())
-    return NULL;
-  return list->referring[0];
-}
-
-/* Clear reference list.  */
-
-static inline void
-ipa_empty_ref_list (struct ipa_ref_list *list)
-{
-  list->referring.create (0);
-  list->references = NULL;
-}
-
-/* Clear reference list.  */
-
-static inline unsigned int
-ipa_ref_list_nreferences (struct ipa_ref_list *list)
-{
-  return vec_safe_length (list->references);
-}
-
-#define ipa_ref_list_reference_iterate(L,I,P) \
-   vec_safe_iterate ((L)->references, (I), &(P))
-#define ipa_ref_list_referring_iterate(L,I,P) \
-   (L)->referring.iterate ((I), &(P))
diff --git a/gcc/ipa-ref.c b/gcc/ipa-ref.c
index df84c9c..1be173a 100644
--- a/gcc/ipa-ref.c
+++ b/gcc/ipa-ref.c
@@ -27,294 +27,60 @@  along with GCC; see the file COPYING3.  If not see
 #include "cgraph.h"
 #include "ipa-utils.h"
 
-static const char *ipa_ref_use_name[] = {"read","write","addr","alias"};
-
-/* 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 (symtab_node *referring_node,
-		      symtab_node *referred_node,
-		      enum ipa_ref_use use_type, gimple stmt)
-{
-  struct ipa_ref *ref, *ref2;
-  struct ipa_ref_list *list, *list2;
-  ipa_ref_t *old_references;
-
-  gcc_checking_assert (!stmt || is_a <cgraph_node *> (referring_node));
-  gcc_checking_assert (use_type != IPA_REF_ALIAS || !stmt);
-
-  list = &referring_node->ref_list;
-  old_references = vec_safe_address (list->references);
-  vec_safe_grow (list->references, vec_safe_length (list->references) + 1);
-  ref = &list->references->last ();
-
-  list2 = &referred_node->ref_list;
-  list2->referring.safe_push (ref);
-  ref->referred_index = list2->referring.length () - 1;
-  ref->referring = referring_node;
-  ref->referred = referred_node;
-  ref->stmt = stmt;
-  ref->lto_stmt_uid = 0;
-  ref->use = use_type;
-  ref->speculative = 0;
-
-  /* If vector was moved in memory, update pointers.  */
-  if (old_references != list->references->address ())
-    {
-      int i;
-      for (i = 0; ipa_ref_list_reference_iterate (list, i, ref2); i++)
-	ipa_ref_referred_ref_list (ref2)->referring[ref2->referred_index] = ref2;
-    }
-  return ref;
-}
-
-/* If VAL is a reference to a function or a variable, add a reference from
-   REFERRING_NODE to the corresponding symbol table node.  USE_TYPE specify
-   type of the use and STMT the statement (if it exists).  Return the new
-   reference or NULL if none was created.  */
-
-struct ipa_ref *
-ipa_maybe_record_reference (symtab_node *referring_node, tree val,
-			    enum ipa_ref_use use_type, gimple stmt)
-{
-  STRIP_NOPS (val);
-  if (TREE_CODE (val) != ADDR_EXPR)
-    return NULL;
-  val = get_base_var (val);
-  if (val && (TREE_CODE (val) == FUNCTION_DECL
-	       || TREE_CODE (val) == VAR_DECL))
-    {
-      symtab_node *referred = symtab_get_node (val);
-      gcc_checking_assert (referred);
-      return ipa_record_reference (referring_node, referred,
-				   use_type, stmt);
-    }
-  return NULL;
-}
-
-/* Remove reference REF.  */
+/* Remove reference.  */
 
 void
-ipa_remove_reference (struct ipa_ref *ref)
+ipa_ref::remove_reference ()
 {
-  struct ipa_ref_list *list = ipa_ref_referred_ref_list (ref);
-  struct ipa_ref_list *list2 = ipa_ref_referring_ref_list (ref);
+  struct ipa_ref_list *list = referred_ref_list ();
+  struct ipa_ref_list *list2 = referring_ref_list ();
   vec<ipa_ref_t, va_gc> *old_references = list2->references;
   struct ipa_ref *last;
 
-  gcc_assert (list->referring[ref->referred_index] == ref);
+  gcc_assert (list->referring[referred_index] == this);
   last = list->referring.last ();
-  if (ref != last)
+  if (this != last)
     {
-      list->referring[ref->referred_index] = list->referring.last ();
-      list->referring[ref->referred_index]->referred_index 
-	  = ref->referred_index;
+      list->referring[referred_index] = list->referring.last ();
+      list->referring[referred_index]->referred_index
+	  = referred_index;
     }
   list->referring.pop ();
 
   last = &list2->references->last ();
+
+  struct ipa_ref *ref = this;
+
   if (ref != last)
     {
       *ref = *last;
-      ipa_ref_referred_ref_list (ref)->referring[ref->referred_index] = ref;
+      referred_ref_list ()->referring[referred_index] = ref;
     }
   list2->references->pop ();
   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_safe_length (list->references))
-    ipa_remove_reference (&list->references->last ());
-  vec_free (list->references);
-}
-
-/* Remove all references in ref list LIST.  */
-
-void
-ipa_remove_all_referring (struct ipa_ref_list *list)
-{
-  while (list->referring.length ())
-    ipa_remove_reference (list->referring.last ());
-  list->referring.release ();
-}
-
-/* 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++)
-    {
-      fprintf (file, "%s/%i (%s)",
-               ref->referred->asm_name (),
-               ref->referred->order,
-	       ipa_ref_use_name [ref->use]);
-      if (ref->speculative)
-	fprintf (file, " (speculative)");
-    }
-  fprintf (file, "\n");
-}
-
-/* Dump referring in LIST to FILE.  */
-
-void
-ipa_dump_referring (FILE * file, struct ipa_ref_list *list)
-{
-  struct ipa_ref *ref;
-  int i;
-  for (i = 0; ipa_ref_list_referring_iterate (list, i, ref); i++)
-    {
-      fprintf (file, "%s/%i (%s)",
-               ref->referring->asm_name (),
-               ref->referring->order,
-	       ipa_ref_use_name [ref->use]);
-      if (ref->speculative)
-	fprintf (file, " (speculative)");
-    }
-  fprintf (file, "\n");
-}
-
-/* Clone reference REF to DEST_NODE and set its stmt to STMT.  */
-
-struct ipa_ref *
-ipa_clone_ref (struct ipa_ref *ref,
-	       symtab_node *dest_node,
-	       gimple stmt)
-{
-  bool speculative = ref->speculative;
-  unsigned int stmt_uid = ref->lto_stmt_uid;
-  struct ipa_ref *ref2;
-
-  ref2 = ipa_record_reference (dest_node,
-			       ref->referred,
-			       ref->use, stmt);
-  ref2->speculative = speculative;
-  ref2->lto_stmt_uid = stmt_uid;
-  return ref2;
-}
-
-/* Clone all references from SRC to DEST_NODE or DEST_VARPOOL_NODE.  */
+/* Return true when execution of reference can lead to return from
+   function.  */
 
-void
-ipa_clone_references (symtab_node *dest_node,
-		      struct ipa_ref_list *src)
-{
-  struct ipa_ref *ref, *ref2;
-  int i;
-  for (i = 0; ipa_ref_list_reference_iterate (src, i, ref); i++)
-    {
-      bool speculative = ref->speculative;
-      unsigned int stmt_uid = ref->lto_stmt_uid;
-
-      ref2 = ipa_record_reference (dest_node,
-				   ref->referred,
-				   ref->use, ref->stmt);
-      ref2->speculative = speculative;
-      ref2->lto_stmt_uid = stmt_uid;
-    }
-}
-
-/* Clone all referring from SRC to DEST_NODE or DEST_VARPOOL_NODE.  */
-
-void
-ipa_clone_referring (symtab_node *dest_node,
-		    struct ipa_ref_list *src)
-{
-  struct ipa_ref *ref, *ref2;
-  int i;
-  for (i = 0; ipa_ref_list_referring_iterate (src, i, ref); i++)
-    {
-      bool speculative = ref->speculative;
-      unsigned int stmt_uid = ref->lto_stmt_uid;
-
-      ref2 = ipa_record_reference (ref->referring,
-				   dest_node,
-				   ref->use, ref->stmt);
-      ref2->speculative = speculative;
-      ref2->lto_stmt_uid = stmt_uid;
-    }
-}
-
-/* Return true when execution of REF can lead to return from
-   function. */
 bool
-ipa_ref_cannot_lead_to_return (struct ipa_ref *ref)
+ipa_ref::cannot_lead_to_return ()
 {
-  return cgraph_node_cannot_return (ipa_ref_referring_node (ref));
-}
-
-/* Return true if list contains an alias.  */
-bool
-ipa_ref_has_aliases_p (struct ipa_ref_list *ref_list)
-{
-  struct ipa_ref *ref;
-  int i;
-
-  for (i = 0; ipa_ref_list_referring_iterate (ref_list, i, ref); i++)
-    if (ref->use == IPA_REF_ALIAS)
-      return true;
-  return false;
+  return cgraph_node_cannot_return (dyn_cast <cgraph_node *> (referring));
 }
 
-/* Find the structure describing a reference in REFERRING_NODE to REFERRED_NODE
-   and associated with statement STMT.  */
+/* Return reference list this reference is in.  */
 
-struct ipa_ref *
-ipa_find_reference (symtab_node *referring_node, symtab_node *referred_node,
-		    gimple stmt, unsigned int lto_stmt_uid)
+struct ipa_ref_list *
+ipa_ref::referring_ref_list (void)
 {
-  struct ipa_ref *r = NULL;
-  int i;
-
-  for (i = 0; ipa_ref_list_reference_iterate (&referring_node->ref_list, i, r); i++)
-    if (r->referred == referred_node
-	&& !r->speculative
-	&& ((stmt && r->stmt == stmt)
-	    || (lto_stmt_uid && r->lto_stmt_uid == lto_stmt_uid)
-	    || (!stmt && !lto_stmt_uid && !r->stmt && !r->lto_stmt_uid)))
-      return r;
-  return NULL;
+  return &referring->ref_list;
 }
 
-/* Remove all references from REFERRING_NODE that are associated with statement
-   STMT.  */
+/* Return reference list this reference is in.  */
 
-void
-ipa_remove_stmt_references (symtab_node *referring_node, gimple stmt)
+struct ipa_ref_list *
+ipa_ref::referred_ref_list (void)
 {
-  struct ipa_ref *r = NULL;
-  int i = 0;
-
-  while (ipa_ref_list_reference_iterate (&referring_node->ref_list, i, r))
-    if (r->stmt == stmt)
-      ipa_remove_reference (r);
-    else
-      i++;
-}
-
-/* Remove all stmt references in non-speculative references.
-   Those are not maintained during inlining & clonning. 
-   The exception are speculative references that are updated along
-   with callgraph edges associated with them.  */
-
-void
-ipa_clear_stmts_in_references (symtab_node *referring_node)
-{
-  struct ipa_ref *r = NULL;
-  int i;
-
-  for (i = 0; ipa_ref_list_reference_iterate (&referring_node->ref_list, i, r); i++)
-    if (!r->speculative)
-      {
-	r->stmt = NULL;
-	r->lto_stmt_uid = 0;
-      }
+  return &referred->ref_list;
 }
diff --git a/gcc/ipa-ref.h b/gcc/ipa-ref.h
index 4ce5f8d..d2de006 100644
--- a/gcc/ipa-ref.h
+++ b/gcc/ipa-ref.h
@@ -35,6 +35,20 @@  enum GTY(()) ipa_ref_use
 /* Record of reference in callgraph or varpool.  */
 struct GTY(()) ipa_ref
 {
+public:
+  /* Remove reference.  */
+  void remove_reference ();
+
+  /* Return true when execution of reference can lead to return from
+     function.  */
+  bool cannot_lead_to_return ();
+
+  /* Return reference list this reference is in.  */
+  struct ipa_ref_list * referring_ref_list (void);
+
+  /* Return reference list this reference is in.  */
+  struct ipa_ref_list * referred_ref_list (void);
+
   symtab_node *referring;
   symtab_node *referred;
   gimple stmt;
@@ -51,29 +65,39 @@  typedef struct ipa_ref *ipa_ref_ptr;
 /* List of references.  This is stored in both callgraph and varpool nodes.  */
 struct GTY(()) ipa_ref_list
 {
+public:
+  /* Return first reference in list or NULL if empty.  */
+  struct ipa_ref *first_reference (void)
+  {
+    if (!vec_safe_length (references))
+      return NULL;
+    return &(*references)[0];
+  }
+
+  /* Return first referring ref in list or NULL if empty.  */
+  struct ipa_ref *first_referring (void)
+  {
+    if (!referring.length ())
+      return NULL;
+    return referring[0];
+  }
+
+  /* Clear reference list.  */
+  void clear (void)
+  {
+    referring.create (0);
+    references = NULL;
+  }
+
+  /* Return number of references.  */
+  unsigned int nreferences (void)
+  {
+    return vec_safe_length (references);
+  }
+
   /* Store actual references in references vector.  */
   vec<ipa_ref_t, va_gc> *references;
   /* Referring 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>  GTY((skip)) referring;
 };
-
-struct ipa_ref * ipa_record_reference (symtab_node *,
-				       symtab_node *,
-				       enum ipa_ref_use, gimple);
-struct ipa_ref * ipa_maybe_record_reference (symtab_node *, tree,
-					     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_referring (struct ipa_ref_list *);
-void ipa_dump_references (FILE *, struct ipa_ref_list *);
-void ipa_dump_referring (FILE *, struct ipa_ref_list *);
-void ipa_clone_references (symtab_node *, struct ipa_ref_list *);
-void ipa_clone_referring (symtab_node *, struct ipa_ref_list *);
-struct ipa_ref * ipa_clone_ref (struct ipa_ref *, symtab_node *, gimple);
-bool ipa_ref_cannot_lead_to_return (struct ipa_ref *);
-bool ipa_ref_has_aliases_p (struct ipa_ref_list *);
-struct ipa_ref * ipa_find_reference (symtab_node *, symtab_node *, gimple, unsigned int);
-void ipa_remove_stmt_references (symtab_node *, gimple);
-void ipa_clear_stmts_in_references (symtab_node *);
diff --git a/gcc/ipa-reference.c b/gcc/ipa-reference.c
index e815454..064fde2 100644
--- a/gcc/ipa-reference.c
+++ b/gcc/ipa-reference.c
@@ -450,16 +450,16 @@  static void
 analyze_function (struct cgraph_node *fn)
 {
   ipa_reference_local_vars_info_t local;
-  struct ipa_ref *ref;
+  struct ipa_ref *ref = NULL;
   int i;
   tree var;
 
   local = init_function_info (fn);
-  for (i = 0; ipa_ref_list_reference_iterate (&fn->ref_list, i, ref); i++)
+  for (i = 0; fn->iterate_reference (i, ref); i++)
     {
       if (!is_a <varpool_node *> (ref->referred))
 	continue;
-      var = ipa_ref_varpool_node (ref)->decl;
+      var = ref->referred->decl;
       if (!is_proper_for_analysis (var))
 	continue;
       switch (ref->use)
@@ -468,7 +468,7 @@  analyze_function (struct cgraph_node *fn)
           bitmap_set_bit (local->statics_read, DECL_UID (var));
 	  break;
 	case IPA_REF_STORE:
-	  if (ipa_ref_cannot_lead_to_return (ref))
+	  if (ref->cannot_lead_to_return ())
 	    break;
           bitmap_set_bit (local->statics_written, DECL_UID (var));
 	  break;
@@ -882,7 +882,7 @@  write_node_summary_p (struct cgraph_node *node,
      In future we might also want to include summaries of functions references
      by initializers of constant variables references in current unit.  */
   if (!reachable_from_this_partition_p (node, encoder)
-      && !referenced_from_this_partition_p (&node->ref_list, encoder))
+      && !referenced_from_this_partition_p (node, encoder))
     return false;
 
   /* See if the info has non-empty intersections with vars we want to encode.  */
@@ -949,7 +949,7 @@  ipa_reference_write_optimization_summary (void)
       varpool_node *vnode = dyn_cast <varpool_node *> (snode);
       if (vnode
 	  && bitmap_bit_p (all_module_statics, DECL_UID (vnode->decl))
-	  && referenced_from_this_partition_p (&vnode->ref_list, encoder))
+	  && referenced_from_this_partition_p (vnode, encoder))
 	{
 	  tree decl = vnode->decl;
 	  bitmap_set_bit (ltrans_statics, DECL_UID (decl));
diff --git a/gcc/ipa-split.c b/gcc/ipa-split.c
index bfcd43e..3ca57b6 100644
--- a/gcc/ipa-split.c
+++ b/gcc/ipa-split.c
@@ -1251,7 +1251,7 @@  split_function (struct split_point *split_point)
      a warning for the non-inlinable part.  */
   DECL_NO_INLINE_WARNING_P (node->decl) = 1;
   cgraph_node_remove_callees (cur_node);
-  ipa_remove_all_references (&cur_node->ref_list);
+  cur_node->remove_all_references ();
   if (!split_part_return_p)
     TREE_THIS_VOLATILE (node->decl) = 1;
   if (dump_file)
diff --git a/gcc/ipa-utils.c b/gcc/ipa-utils.c
index 8e7c7cb..c191210 100644
--- a/gcc/ipa-utils.c
+++ b/gcc/ipa-utils.c
@@ -289,7 +289,7 @@  ipa_reverse_postorder (struct cgraph_node **order)
   int order_pos = 0;
   struct cgraph_edge *edge;
   int pass;
-  struct ipa_ref *ref;
+  struct ipa_ref *ref = NULL;
 
   struct postorder_stack *stack =
     XCNEWVEC (struct postorder_stack, cgraph_n_nodes);
@@ -332,13 +332,13 @@  ipa_reverse_postorder (struct cgraph_node **order)
 			    (cgraph_function_node (edge->callee, NULL)->decl))
 			node2 = NULL;
 		    }
-		  for (;ipa_ref_list_referring_iterate (&stack[stack_size].node->ref_list,
+		  for (; stack[stack_size].node->iterate_referring (
 						       stack[stack_size].ref,
 						       ref) && !node2;
 		       stack[stack_size].ref++)
 		    {
 		      if (ref->use == IPA_REF_ALIAS)
-			node2 = ipa_ref_referring_node (ref);
+			node2 = dyn_cast <cgraph_node *> (ref->referring);
 		    }
 		  if (!node2)
 		    break;
diff --git a/gcc/ipa-visibility.c b/gcc/ipa-visibility.c
index 9e4d8c3..a4848c2 100644
--- a/gcc/ipa-visibility.c
+++ b/gcc/ipa-visibility.c
@@ -91,7 +91,7 @@  cgraph_non_local_node_p_1 (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED
 {
    /* FIXME: Aliases can be local, but i386 gets thunks wrong then.  */
    return !(cgraph_only_called_directly_or_aliased_p (node)
-	    && !ipa_ref_has_aliases_p (&node->ref_list)
+	    && !node->has_aliases_p ()
 	    && node->definition
 	    && !DECL_EXTERNAL (node->decl)
 	    && !node->externally_visible
@@ -120,15 +120,15 @@  bool
 address_taken_from_non_vtable_p (symtab_node *node)
 {
   int i;
-  struct ipa_ref *ref;
-  for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list,
-					     i, ref); i++)
+  struct ipa_ref *ref = NULL;
+
+  for (i = 0; node->iterate_referring (i, ref); i++)
     if (ref->use == IPA_REF_ADDR)
       {
 	varpool_node *node;
 	if (is_a <cgraph_node *> (ref->referring))
 	  return true;
-	node = ipa_ref_referring_varpool_node (ref);
+	node = dyn_cast <varpool_node *> (ref->referring);
 	if (!DECL_VIRTUAL_P (node->decl))
 	  return true;
       }
@@ -682,8 +682,7 @@  function_and_variable_visibility (bool whole_program)
 	  bool found = false;
 
 	  /* See if there is something to update.  */
-	  for (i = 0; ipa_ref_list_referring_iterate (&vnode->ref_list,
-						      i, ref); i++)
+	  for (i = 0; vnode->iterate_referring (i, ref); i++)
 	    if (ref->use == IPA_REF_ADDR
 		&& can_replace_by_local_alias_in_vtable (ref->referred))
 	      {
@@ -696,7 +695,7 @@  function_and_variable_visibility (bool whole_program)
 	      walk_tree (&DECL_INITIAL (vnode->decl),
 			 update_vtable_references, NULL, visited_nodes);
 	      pointer_set_destroy (visited_nodes);
-	      ipa_remove_all_references (&vnode->ref_list);
+	      vnode->remove_all_references ();
 	      record_references_in_initializer (vnode->decl, false);
 	    }
 	}
diff --git a/gcc/ipa.c b/gcc/ipa.c
index 5128b4d..53033fc 100644
--- a/gcc/ipa.c
+++ b/gcc/ipa.c
@@ -50,10 +50,9 @@  has_addr_references_p (struct cgraph_node *node,
 		       void *data ATTRIBUTE_UNUSED)
 {
   int i;
-  struct ipa_ref *ref;
+  struct ipa_ref *ref = NULL;
 
-  for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list,
-					      i, ref); i++)
+  for (i = 0; node->iterate_referring (i, ref); i++)
     if (ref->use == IPA_REF_ADDR)
       return true;
   return false;
@@ -100,14 +99,14 @@  enqueue_node (symtab_node *node, symtab_node **first,
 /* Process references.  */
 
 static void
-process_references (struct ipa_ref_list *list,
+process_references (symtab_node *snode,
 		    symtab_node **first,
 		    bool before_inlining_p,
 		    struct pointer_set_t *reachable)
 {
   int i;
-  struct ipa_ref *ref;
-  for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++)
+  struct ipa_ref *ref = NULL;
+  for (i = 0; snode->iterate_reference (i, ref); i++)
     {
       symtab_node *node = ref->referred;
 
@@ -357,8 +356,7 @@  symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
 		  enqueue_node (next, &first, reachable);
 	    }
 	  /* Mark references as reachable.  */
-	  process_references (&node->ref_list, &first,
-			      before_inlining_p, reachable);
+	  process_references (node, &first, before_inlining_p, reachable);
 	}
 
       if (cgraph_node *cnode = dyn_cast <cgraph_node *> (node))
@@ -445,8 +443,8 @@  symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
 	  && !vnode->alias
 	  && in_boundary_p)
 	{
-	  struct ipa_ref *ref;
-	  for (int i = 0; ipa_ref_list_reference_iterate (&node->ref_list, i, ref); i++)
+	  struct ipa_ref *ref = NULL;
+	  for (int i = 0; node->iterate_reference (i, ref); i++)
 	    enqueue_node (ref->referred, &first, reachable);
 	}
     }
@@ -492,7 +490,7 @@  symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
 		node->local.local = false;
 	      cgraph_node_remove_callees (node);
 	      symtab_remove_from_same_comdat_group (node);
-	      ipa_remove_all_references (&node->ref_list);
+	      node->remove_all_references ();
 	      changed = true;
 	    }
 	}
@@ -554,7 +552,7 @@  symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
 	    varpool_remove_initializer (vnode);
 	  else
 	    DECL_INITIAL (vnode->decl) = init;
-	  ipa_remove_all_references (&vnode->ref_list);
+	  vnode->remove_all_references ();
 	}
       else
 	vnode->aux = NULL;
@@ -617,8 +615,7 @@  process_references (varpool_node *vnode,
       || TREE_THIS_VOLATILE (vnode->decl))
     *explicit_refs = false;
 
-  for (i = 0; ipa_ref_list_referring_iterate (&vnode->ref_list,
-					     i, ref)
+  for (i = 0; vnode->iterate_referring (i, ref)
 	      && *explicit_refs && (!*written || !*address_taken || !*read); i++)
     switch (ref->use)
       {
@@ -657,7 +654,7 @@  set_writeonly_bit (varpool_node *vnode, void *data ATTRIBUTE_UNUSED)
     {
       DECL_INITIAL (vnode->decl) = NULL;
       if (!vnode->alias)
-	ipa_remove_all_references (&vnode->ref_list);
+	vnode->remove_all_references ();
     }
   return false;
 }
diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c
index 1683704..e2c38a1 100644
--- a/gcc/lto-cgraph.c
+++ b/gcc/lto-cgraph.c
@@ -315,14 +315,15 @@  lto_output_edge (struct lto_simple_output_block *ob, struct cgraph_edge *edge,
     }
 }
 
-/* Return if LIST contain references from other partitions.  */
+/* Return if NODE contain references from other partitions.  */
 
 bool
-referenced_from_other_partition_p (struct ipa_ref_list *list, lto_symtab_encoder_t encoder)
+referenced_from_other_partition_p (symtab_node *node, lto_symtab_encoder_t encoder)
 {
   int i;
-  struct ipa_ref *ref;
-  for (i = 0; ipa_ref_list_referring_iterate (list, i, ref); i++)
+  struct ipa_ref *ref = NULL;
+
+  for (i = 0; node->iterate_referring (i, ref); i++)
     {
       if (ref->referring->in_other_partition
           || !lto_symtab_encoder_in_partition_p (encoder, ref->referring))
@@ -348,15 +349,16 @@  reachable_from_other_partition_p (struct cgraph_node *node, lto_symtab_encoder_t
   return false;
 }
 
-/* Return if LIST contain references from other partitions.  */
+/* Return if NODE contain references from other partitions.  */
 
 bool
-referenced_from_this_partition_p (struct ipa_ref_list *list,
+referenced_from_this_partition_p (symtab_node *node,
 				  lto_symtab_encoder_t encoder)
 {
   int i;
-  struct ipa_ref *ref;
-  for (i = 0; ipa_ref_list_referring_iterate (list, i, ref); i++)
+  struct ipa_ref *ref = NULL;
+
+  for (i = 0; node->iterate_referring (i, ref); i++)
     if (lto_symtab_encoder_in_partition_p (encoder, ref->referring))
       return true;
   return false;
@@ -523,8 +525,7 @@  lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
   bp_pack_value (&bp, tag == LTO_symtab_analyzed_node
 		 && symtab_get_symbol_partitioning_class (node) == SYMBOL_PARTITION
 		 && (reachable_from_other_partition_p (node, encoder)
-		     || referenced_from_other_partition_p (&node->ref_list,
-							   encoder)), 1);
+		     || referenced_from_other_partition_p (node, encoder)), 1);
   bp_pack_value (&bp, node->lowered, 1);
   bp_pack_value (&bp, in_other_partition, 1);
   /* Real aliases in a boundary become non-aliases. However we still stream
@@ -607,8 +608,7 @@  lto_output_varpool_node (struct lto_simple_output_block *ob, varpool_node *node,
   else
     {
       bp_pack_value (&bp, node->definition
-		     && referenced_from_other_partition_p (&node->ref_list,
-							   encoder), 1);
+		     && referenced_from_other_partition_p (node, encoder), 1);
       bp_pack_value (&bp, node->analyzed
 		     && boundary_p && !DECL_EXTERNAL (node->decl), 1);
 	  /* in_other_partition.  */
@@ -759,14 +759,13 @@  output_refs (lto_symtab_encoder_t encoder)
     {
       symtab_node *node = lsei_node (lsei);
 
-      count = ipa_ref_list_nreferences (&node->ref_list);
+      count = node->ref_list.nreferences ();
       if (count)
 	{
 	  streamer_write_gcov_count_stream (ob->main_stream, count);
 	  streamer_write_uhwi_stream (ob->main_stream,
 				     lto_symtab_encoder_lookup (encoder, node));
-	  for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list,
-						      i, ref); i++)
+	  for (i = 0; node->iterate_reference (i, ref); i++)
 	    lto_output_ref (ob, ref, encoder);
 	}
     }
@@ -790,17 +789,16 @@  add_node_to (lto_symtab_encoder_t encoder, struct cgraph_node *node,
   lto_symtab_encoder_encode (encoder, node);
 }
 
-/* Add all references in LIST to encoders.  */
+/* Add all references in NODE to encoders.  */
 
 static void
-add_references (lto_symtab_encoder_t encoder,
-		struct ipa_ref_list *list)
+add_references (lto_symtab_encoder_t encoder, symtab_node *node)
 {
   int i;
-  struct ipa_ref *ref;
-  for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++)
+  struct ipa_ref *ref = NULL;
+  for (i = 0; node->iterate_reference (i, ref); i++)
     if (is_a <cgraph_node *> (ref->referred))
-      add_node_to (encoder, ipa_ref_node (ref), false);
+      add_node_to (encoder, dyn_cast <cgraph_node *> (ref->referred), false);
     else
       lto_symtab_encoder_encode (encoder, ref->referred);
 }
@@ -833,7 +831,7 @@  compute_ltrans_boundary (lto_symtab_encoder_t in_encoder)
       struct cgraph_node *node = lsei_cgraph_node (lsei);
       add_node_to (encoder, node, true);
       lto_set_symtab_encoder_in_partition (encoder, node);
-      add_references (encoder, &node->ref_list);
+      add_references (encoder, node);
       /* For proper debug info, we need to ship the origins, too.  */
       if (DECL_ABSTRACT_ORIGIN (node->decl))
 	{
@@ -849,7 +847,7 @@  compute_ltrans_boundary (lto_symtab_encoder_t in_encoder)
 
       lto_set_symtab_encoder_in_partition (encoder, vnode);
       lto_set_symtab_encoder_encode_initializer (encoder, vnode);
-      add_references (encoder, &vnode->ref_list);
+      add_references (encoder, vnode);
       /* For proper debug info, we need to ship the origins, too.  */
       if (DECL_ABSTRACT_ORIGIN (vnode->decl))
 	{
@@ -871,7 +869,7 @@  compute_ltrans_boundary (lto_symtab_encoder_t in_encoder)
 	      && ctor_for_folding (vnode->decl) != error_mark_node)
 	    {
 	      lto_set_symtab_encoder_encode_initializer (encoder, vnode);
-	      add_references (encoder, &vnode->ref_list);
+	      add_references (encoder, vnode);
 	    }
        }
     }
@@ -1315,7 +1313,7 @@  input_ref (struct lto_input_block *ib,
   use = (enum ipa_ref_use) bp_unpack_value (&bp, 2);
   speculative = (enum ipa_ref_use) bp_unpack_value (&bp, 1);
   node = nodes[streamer_read_hwi (ib)];
-  ref = ipa_record_reference (referring_node, node, use, NULL);
+  ref = referring_node->add_reference (node, use);
   ref->speculative = speculative;
   if (is_a <cgraph_node *> (referring_node))
     ref->lto_stmt_uid = streamer_read_hwi (ib);
diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c
index a18c64e..6bafaa3 100644
--- a/gcc/lto-streamer-in.c
+++ b/gcc/lto-streamer-in.c
@@ -785,7 +785,7 @@  fixup_call_stmt_edges_1 (struct cgraph_node *node, gimple *stmts,
 			 struct function *fn)
 {
   struct cgraph_edge *cedge;
-  struct ipa_ref *ref;
+  struct ipa_ref *ref = NULL;
   unsigned int i;
 
   for (cedge = node->callees; cedge; cedge = cedge->next_callee)
@@ -804,9 +804,7 @@  fixup_call_stmt_edges_1 (struct cgraph_node *node, gimple *stmts,
       if (!cedge->call_stmt)
         fatal_error ("Cgraph edge statement index not found");
     }
-  for (i = 0;
-       ipa_ref_list_reference_iterate (&node->ref_list, i, ref);
-       i++)
+  for (i = 0; node->iterate_reference (i, ref); i++)
     if (ref->lto_stmt_uid)
       {
 	if (gimple_stmt_max_uid (fn) < ref->lto_stmt_uid)
diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c
index 05b2384..59207ee 100644
--- a/gcc/lto-streamer-out.c
+++ b/gcc/lto-streamer-out.c
@@ -2361,8 +2361,7 @@  output_symbol_p (symtab_node *node)
     {
       int i;
       struct ipa_ref *ref;
-      for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list,
-					          i, ref); i++)
+      for (i = 0; node->iterate_referring (i, ref); i++)
 	{
 	  if (ref->use == IPA_REF_ALIAS)
 	    continue;
diff --git a/gcc/lto-streamer.h b/gcc/lto-streamer.h
index 521d78d..dec9967 100644
--- a/gcc/lto-streamer.h
+++ b/gcc/lto-streamer.h
@@ -887,7 +887,7 @@  bool referenced_from_other_partition_p (struct ipa_ref_list *,
 				        lto_symtab_encoder_t);
 bool reachable_from_other_partition_p (struct cgraph_node *,
 				       lto_symtab_encoder_t);
-bool referenced_from_this_partition_p (struct ipa_ref_list *,
+bool referenced_from_this_partition_p (struct symtab_node *,
 					lto_symtab_encoder_t);
 bool reachable_from_this_partition_p (struct cgraph_node *,
 				      lto_symtab_encoder_t);
diff --git a/gcc/lto/lto-partition.c b/gcc/lto/lto-partition.c
index 5a8c843..4d19ef6 100644
--- a/gcc/lto/lto-partition.c
+++ b/gcc/lto/lto-partition.c
@@ -86,10 +86,10 @@  static void
 add_references_to_partition (ltrans_partition part, symtab_node *node)
 {
   int i;
-  struct ipa_ref *ref;
+  struct ipa_ref *ref = NULL;
 
   /* Add all duplicated references to the partition.  */
-  for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list, i, ref); i++)
+  for (i = 0; node->iterate_reference (i, ref); i++)
     if (symtab_get_symbol_partitioning_class (ref->referred) == SYMBOL_DUPLICATE)
       add_symbol_to_partition (part, ref->referred);
     /* References to a readonly variable may be constant foled into its value.
@@ -114,7 +114,7 @@  add_symbol_to_partition_1 (ltrans_partition part, symtab_node *node)
 {
   enum symbol_partitioning_class c = symtab_get_symbol_partitioning_class (node);
   int i;
-  struct ipa_ref *ref;
+  struct ipa_ref *ref = NULL;
   symtab_node *node1;
 
   /* If NODE is already there, we have nothing to do.  */
@@ -168,7 +168,7 @@  add_symbol_to_partition_1 (ltrans_partition part, symtab_node *node)
   add_references_to_partition (part, node);
 
   /* Add all aliases associated with the symbol.  */
-  for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list, i, ref); i++)
+  for (i = 0; node->iterate_referring (i, ref); i++)
     if (ref->use == IPA_REF_ALIAS && !node->weakref)
       add_symbol_to_partition_1 (part, ref->referring);
 
@@ -516,9 +516,9 @@  lto_balanced_map (int n_lto_partitions)
 	 it and thus we need to subtract it from COST.  */
       while (last_visited_node < lto_symtab_encoder_size (partition->encoder))
 	{
-	  struct ipa_ref_list *refs;
+	  symtab_node *refs_node;
 	  int j;
-	  struct ipa_ref *ref;
+	  struct ipa_ref *ref = NULL;
 	  symtab_node *snode = lto_symtab_encoder_deref (partition->encoder,
 							last_visited_node);
 
@@ -526,7 +526,7 @@  lto_balanced_map (int n_lto_partitions)
 	    {
 	      struct cgraph_edge *edge;
 
-	      refs = &node->ref_list;
+	      refs_node = node;
 
 	      last_visited_node++;
 
@@ -570,18 +570,18 @@  lto_balanced_map (int n_lto_partitions)
 	    }
 	  else
 	    {
-	      refs = &snode->ref_list;
+	      refs_node = snode;
 	      last_visited_node++;
 	    }
 
 	  /* Compute boundary cost of IPA REF edges and at the same time look into
 	     variables referenced from current partition and try to add them.  */
-	  for (j = 0; ipa_ref_list_reference_iterate (refs, j, ref); j++)
+	  for (j = 0; refs_node->iterate_reference (j, ref); j++)
 	    if (is_a <varpool_node *> (ref->referred))
 	      {
 		int index;
 
-		vnode = ipa_ref_varpool_node (ref);
+		vnode = dyn_cast <varpool_node *> (ref->referred);
 		if (!vnode->definition)
 		  continue;
 		if (!symbol_partitioned_p (vnode) && flag_toplevel_reorder
@@ -599,7 +599,7 @@  lto_balanced_map (int n_lto_partitions)
 	      {
 		int index;
 
-		node = ipa_ref_node (ref);
+		node = dyn_cast <cgraph_node *> (ref->referred);
 		if (!node->definition)
 		  continue;
 		index = lto_symtab_encoder_lookup (partition->encoder,
@@ -610,12 +610,12 @@  lto_balanced_map (int n_lto_partitions)
 		else
 		  cost++;
 	      }
-	  for (j = 0; ipa_ref_list_referring_iterate (refs, j, ref); j++)
+	  for (j = 0; refs_node->iterate_referring (j, ref); j++)
 	    if (is_a <varpool_node *> (ref->referring))
 	      {
 		int index;
 
-		vnode = ipa_ref_referring_varpool_node (ref);
+		vnode = dyn_cast <varpool_node *> (ref->referring);
 		gcc_assert (vnode->definition);
 		/* It is better to couple variables with their users, because it allows them
 		   to be removed.  Coupling with objects they refer to only helps to reduce
@@ -636,7 +636,7 @@  lto_balanced_map (int n_lto_partitions)
 	      {
 		int index;
 
-		node = ipa_ref_referring_node (ref);
+		node = dyn_cast <cgraph_node *> (ref->referring);
 		gcc_assert (node->definition);
 		index = lto_symtab_encoder_lookup (partition->encoder,
 						   node);
diff --git a/gcc/lto/lto-symtab.c b/gcc/lto/lto-symtab.c
index c02f987..82ee827 100644
--- a/gcc/lto/lto-symtab.c
+++ b/gcc/lto/lto-symtab.c
@@ -84,7 +84,7 @@  lto_cgraph_replace_node (struct cgraph_node *node,
 	e->call_stmt_cannot_inline_p = 1;
     }
   /* Redirect incomming references.  */
-  ipa_clone_referring (prevailing_node, &node->ref_list);
+  prevailing_node->clone_referring (node);
 
   ipa_merge_profiles (prevailing_node, node);
   lto_free_function_in_decl_state_for_node (node);
@@ -106,7 +106,7 @@  lto_varpool_replace_node (varpool_node *vnode,
   gcc_assert (!vnode->definition || prevailing_node->definition);
   gcc_assert (!vnode->analyzed || prevailing_node->analyzed);
 
-  ipa_clone_referring (prevailing_node, &vnode->ref_list);
+  prevailing_node->clone_referring (vnode);
   if (vnode->force_output)
     prevailing_node->force_output = true;
   if (vnode->forced_by_abi)
diff --git a/gcc/symtab.c b/gcc/symtab.c
index 1389565..aaa96ed 100644
--- a/gcc/symtab.c
+++ b/gcc/symtab.c
@@ -42,6 +42,9 @@  along with GCC; see the file COPYING3.  If not see
 #include "timevar.h"
 #include "lto-streamer.h"
 #include "output.h"
+#include "ipa-utils.h"
+
+static const char *ipa_ref_use_name[] = {"read","write","addr","alias"};
 
 const char * const ld_plugin_symbol_resolution_names[]=
 {
@@ -284,7 +287,7 @@  symtab_register_node (symtab_node *node)
   if (!node->decl->decl_with_vis.symtab_node)
     node->decl->decl_with_vis.symtab_node = node;
 
-  ipa_empty_ref_list (&node->ref_list);
+  node->ref_list.clear ();
 
   node->order = symtab_order++;
 
@@ -319,8 +322,8 @@  symtab_remove_from_same_comdat_group (symtab_node *node)
 void
 symtab_unregister_node (symtab_node *node)
 {
-  ipa_remove_all_references (&node->ref_list);
-  ipa_remove_all_referring (&node->ref_list);
+  node->remove_all_references ();
+  node->remove_all_referring ();
 
   /* Remove reference to section.  */
   node->set_section_for_node (NULL);
@@ -522,6 +525,277 @@  symtab_node::name () const
   return lang_hooks.decl_printable_name (decl, 2);
 }
 
+/* Return ipa reference from this symtab_node to
+   REFERED_NODE or REFERED_VARPOOL_NODE. USE_TYPE specify type
+   of the use.  */
+
+struct ipa_ref *
+symtab_node::add_reference (symtab_node *referred_node,
+			    enum ipa_ref_use use_type)
+{
+  return add_reference (referred_node, use_type, NULL);
+}
+
+
+/* Return ipa reference from this symtab_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 *
+symtab_node::add_reference (symtab_node *referred_node,
+			    enum ipa_ref_use use_type, gimple stmt)
+{
+  struct ipa_ref *ref = NULL, *ref2 = NULL;
+  struct ipa_ref_list *list, *list2;
+  ipa_ref_t *old_references;
+
+  gcc_checking_assert (!stmt || is_a <cgraph_node *> (this));
+  gcc_checking_assert (use_type != IPA_REF_ALIAS || !stmt);
+
+  list = &ref_list;
+  old_references = vec_safe_address (list->references);
+  vec_safe_grow (list->references, vec_safe_length (list->references) + 1);
+  ref = &list->references->last ();
+
+  list2 = &referred_node->ref_list;
+  list2->referring.safe_push (ref);
+  ref->referred_index = list2->referring.length () - 1;
+  ref->referring = this;
+  ref->referred = referred_node;
+  ref->stmt = stmt;
+  ref->lto_stmt_uid = 0;
+  ref->use = use_type;
+  ref->speculative = 0;
+
+  /* If vector was moved in memory, update pointers.  */
+  if (old_references != list->references->address ())
+    {
+      int i;
+      for (i = 0; iterate_reference(i, ref2); i++)
+	ref2->referred_ref_list ()->referring[ref2->referred_index] = ref2;
+    }
+  return ref;
+}
+
+/* If VAL is a reference to a function or a variable, add a reference from
+   this symtab_node to the corresponding symbol table node.  USE_TYPE specify
+   type of the use and STMT the statement (if it exists).  Return the new
+   reference or NULL if none was created.  */
+
+struct ipa_ref *
+symtab_node::maybe_add_reference (tree val, enum ipa_ref_use use_type,
+				  gimple stmt)
+{
+  STRIP_NOPS (val);
+  if (TREE_CODE (val) != ADDR_EXPR)
+    return NULL;
+  val = get_base_var (val);
+  if (val && (TREE_CODE (val) == FUNCTION_DECL
+	       || TREE_CODE (val) == VAR_DECL))
+    {
+      symtab_node *referred = symtab_get_node (val);
+      gcc_checking_assert (referred);
+      return add_reference (referred, use_type, stmt);
+    }
+  return NULL;
+}
+
+/* Clone all references from symtab NODE to this symtab_node.  */
+
+void
+symtab_node::clone_references (struct symtab_node *node)
+{
+  struct ipa_ref *ref = NULL, *ref2 = NULL;
+  int i;
+  for (i = 0; node->iterate_reference (i, ref); i++)
+    {
+      bool speculative = ref->speculative;
+      unsigned int stmt_uid = ref->lto_stmt_uid;
+
+      ref2 = add_reference (ref->referred, ref->use, ref->stmt);
+      ref2->speculative = speculative;
+      ref2->lto_stmt_uid = stmt_uid;
+    }
+}
+
+/* Clone all referring from symtab NODE to this symtab_node.  */
+
+void
+symtab_node::clone_referring (struct symtab_node *node)
+{
+  struct ipa_ref *ref = NULL, *ref2 = NULL;
+  int i;
+  for (i = 0; node->iterate_referring(i, ref); i++)
+    {
+      bool speculative = ref->speculative;
+      unsigned int stmt_uid = ref->lto_stmt_uid;
+
+      ref2 = ref->referring->add_reference (this, ref->use, ref->stmt);
+      ref2->speculative = speculative;
+      ref2->lto_stmt_uid = stmt_uid;
+    }
+}
+
+/* Clone reference REF to this symtab_node and set its stmt to STMT.  */
+
+struct ipa_ref *
+symtab_node::clone_reference (struct ipa_ref *ref, gimple stmt)
+{
+  bool speculative = ref->speculative;
+  unsigned int stmt_uid = ref->lto_stmt_uid;
+  struct ipa_ref *ref2;
+
+  ref2 = add_reference (ref->referred, ref->use, stmt);
+  ref2->speculative = speculative;
+  ref2->lto_stmt_uid = stmt_uid;
+  return ref2;
+}
+
+/* Find the structure describing a reference to REFERRED_NODE
+   and associated with statement STMT.  */
+
+struct ipa_ref *
+symtab_node::find_reference (symtab_node *referred_node,
+			     gimple stmt, unsigned int lto_stmt_uid)
+{
+  struct ipa_ref *r = NULL;
+  int i;
+
+  for (i = 0; iterate_reference (i, r); i++)
+    if (r->referred == referred_node
+	&& !r->speculative
+	&& ((stmt && r->stmt == stmt)
+	    || (lto_stmt_uid && r->lto_stmt_uid == lto_stmt_uid)
+	    || (!stmt && !lto_stmt_uid && !r->stmt && !r->lto_stmt_uid)))
+      return r;
+  return NULL;
+}
+
+/* Remove all references that are associated with statement STMT.  */
+
+void
+symtab_node::remove_stmt_references (gimple stmt)
+{
+  struct ipa_ref *r = NULL;
+  int i = 0;
+
+  while (iterate_reference (i, r))
+    if (r->stmt == stmt)
+      r->remove_reference ();
+    else
+      i++;
+}
+
+/* Remove all stmt references in non-speculative references.
+   Those are not maintained during inlining & clonning.
+   The exception are speculative references that are updated along
+   with callgraph edges associated with them.  */
+
+void
+symtab_node::clear_stmts_in_references (void)
+{
+  struct ipa_ref *r = NULL;
+  int i;
+
+  for (i = 0; iterate_reference (i, r); i++)
+    if (!r->speculative)
+      {
+	r->stmt = NULL;
+	r->lto_stmt_uid = 0;
+      }
+}
+
+/* Remove all references in ref list.  */
+
+void
+symtab_node::remove_all_references (void)
+{
+  while (vec_safe_length (ref_list.references))
+    ref_list.references->last ().remove_reference ();
+  vec_free (ref_list.references);
+}
+
+/* Remove all referring items in ref list.  */
+
+void
+symtab_node::remove_all_referring (void)
+{
+  while (ref_list.referring.length ())
+    ref_list.referring.last ()->remove_reference ();
+  ref_list.referring.release ();
+}
+
+/* Dump references in ref list to FILE.  */
+
+void
+symtab_node::dump_references (FILE *file)
+{
+  struct ipa_ref *ref = NULL;
+  int i;
+  for (i = 0; iterate_reference (i, ref); i++)
+    {
+      fprintf (file, "%s/%i (%s)",
+               ref->referred->asm_name (),
+               ref->referred->order,
+	       ipa_ref_use_name [ref->use]);
+      if (ref->speculative)
+	fprintf (file, " (speculative)");
+    }
+  fprintf (file, "\n");
+}
+
+/* Dump referring in list to FILE.  */
+
+void
+symtab_node::dump_referring (FILE *file)
+{
+  struct ipa_ref *ref = NULL;
+  int i;
+  for (i = 0; iterate_referring(i, ref); i++)
+    {
+      fprintf (file, "%s/%i (%s)",
+               ref->referring->asm_name (),
+               ref->referring->order,
+	       ipa_ref_use_name [ref->use]);
+      if (ref->speculative)
+	fprintf (file, " (speculative)");
+    }
+  fprintf (file, "\n");
+}
+
+/* Return true if list contains an alias.  */
+bool
+symtab_node::has_aliases_p (void)
+{
+  struct ipa_ref *ref = NULL;
+  int i;
+
+  for (i = 0; iterate_referring (i, ref); i++)
+    if (ref->use == IPA_REF_ALIAS)
+      return true;
+  return false;
+}
+
+/* Iterates I-th reference in the list, REF is also set.  */
+
+struct ipa_ref *
+symtab_node::iterate_reference (unsigned i, struct ipa_ref *&ref)
+{
+  vec_safe_iterate (ref_list.references, i, &ref);
+
+  return ref;
+}
+
+/* Iterates I-th referring item in the list, REF is also set.  */
+
+struct ipa_ref *
+symtab_node::iterate_referring (unsigned i, struct ipa_ref *&ref)
+{
+  ref_list.referring.iterate (i, &ref);
+
+  return ref;
+}
+
 static const char * const symtab_type_names[] = {"symbol", "function", "variable"};
 
 /* Dump base fields of symtab nodes.  Not to be used directly.  */
@@ -634,9 +908,9 @@  dump_symtab_base (FILE *f, symtab_node *node)
     }
 
   fprintf (f, "  References: ");
-  ipa_dump_references (f, &node->ref_list);
+  node->dump_references (f);
   fprintf (f, "  Referring: ");
-  ipa_dump_referring (f, &node->ref_list);
+  node->dump_referring (f);
   if (node->lto_file_data)
     fprintf (f, "  Read from file: %s\n",
 	     node->lto_file_data->file_name);
@@ -819,10 +1093,9 @@  verify_symtab_base (symtab_node *node)
       while (n != node);
       if (symtab_comdat_local_p (node))
 	{
-	  struct ipa_ref_list *refs = &node->ref_list;
-	  struct ipa_ref *ref;
+	  struct ipa_ref *ref = NULL;
 
-	  for (int i = 0; ipa_ref_list_referring_iterate (refs, i, ref); ++i)
+	  for (int i = 0; node->iterate_referring (i, ref); ++i)
 	    {
 	      if (!symtab_in_same_comdat_p (ref->referring, node))
 		{
@@ -1354,7 +1627,7 @@  symtab_resolve_alias (symtab_node *node, symtab_node *target)
   node->definition = true;
   node->alias = true;
   node->analyzed = true;
-  ipa_record_reference (node, target, IPA_REF_ALIAS, NULL);
+  node->add_reference (target, IPA_REF_ALIAS, NULL);
 
   /* Add alias into the comdat group of its target unless it is already there.  */
   if (node->same_comdat_group)
@@ -1405,7 +1678,7 @@  symtab_for_node_and_aliases (symtab_node *node,
 
   if (callback (node, data))
     return true;
-  for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list, i, ref); i++)
+  for (i = 0; node->iterate_referring (i, ref); i++)
     if (ref->use == IPA_REF_ALIAS)
       {
 	symtab_node *alias = ref->referring;
diff --git a/gcc/trans-mem.c b/gcc/trans-mem.c
index b728d74..c7669ec 100644
--- a/gcc/trans-mem.c
+++ b/gcc/trans-mem.c
@@ -4857,7 +4857,7 @@  ipa_tm_create_version_alias (struct cgraph_node *node, void *data)
   record_tm_clone_pair (old_decl, new_decl);
 
   if (info->old_node->force_output
-      || ipa_ref_list_first_referring (&info->old_node->ref_list))
+      || info->old_node->ref_list.first_referring ())
     ipa_tm_mark_force_output_node (new_node);
   if (info->old_node->forced_by_abi)
     ipa_tm_mark_forced_by_abi_node (new_node);
@@ -4916,7 +4916,7 @@  ipa_tm_create_version (struct cgraph_node *old_node)
 
   cgraph_call_function_insertion_hooks (new_node);
   if (old_node->force_output
-      || ipa_ref_list_first_referring (&old_node->ref_list))
+      || old_node->ref_list.first_referring ())
     ipa_tm_mark_force_output_node (new_node);
   if (old_node->forced_by_abi)
     ipa_tm_mark_forced_by_abi_node (new_node);
@@ -5436,7 +5436,7 @@  ipa_tm_execute (void)
     {
       struct cgraph_node *caller;
       struct cgraph_edge *e;
-      struct ipa_ref *ref;
+      struct ipa_ref *ref = NULL;
       unsigned j;
 
       if (i > 256 && i == irr_worklist.length () / 8)
@@ -5463,7 +5463,7 @@  ipa_tm_execute (void)
 	}
 
       /* Propagate back to referring aliases as well.  */
-      for (j = 0; ipa_ref_list_referring_iterate (&node->ref_list, j, ref); j++)
+      for (j = 0; node->iterate_referring (j, ref); j++)
 	{
 	  caller = cgraph (ref->referring);
 	  if (ref->use == IPA_REF_ALIAS
diff --git a/gcc/tree-emutls.c b/gcc/tree-emutls.c
index fe1e85d..3a48630 100644
--- a/gcc/tree-emutls.c
+++ b/gcc/tree-emutls.c
@@ -453,7 +453,7 @@  gen_emutls_addr (tree decl, struct lower_emutls_data *d)
 
       /* We may be adding a new reference to a new variable to the function.
          This means we have to play with the ipa-reference web.  */
-      ipa_record_reference (d->cfun_node, cvar, IPA_REF_ADDR, x);
+      d->cfun_node->add_reference (cvar, IPA_REF_ADDR, x);
 
       /* Record this ssa_name for possible use later in the basic block.  */
       access_vars[index] = addr;
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index dbf4b5d..8f42238 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -1791,7 +1791,7 @@  copy_bb (copy_body_data *id, basic_block bb, int frequency_scale,
 							       (old_edge->frequency + indirect->frequency)),
 							 CGRAPH_FREQ_MAX);
 			    }
-			  ipa_clone_ref (ref, id->dst_node, stmt);
+			  id->dst_node->clone_reference (ref, stmt);
 			}
 		      else
 			{
@@ -5168,7 +5168,7 @@  delete_unreachable_blocks_update_callgraph (copy_body_data *id)
 	      struct cgraph_edge *e;
 	      struct cgraph_node *node;
 
-	      ipa_remove_stmt_references (id->dst_node, gsi_stmt (bsi));
+	      id->dst_node->remove_stmt_references (gsi_stmt (bsi));
 
 	      if (gimple_code (gsi_stmt (bsi)) == GIMPLE_CALL
 		  &&(e = cgraph_edge (id->dst_node, gsi_stmt (bsi))) != NULL)
@@ -5182,7 +5182,7 @@  delete_unreachable_blocks_update_callgraph (copy_body_data *id)
 		  && id->dst_node->clones)
 		for (node = id->dst_node->clones; node != id->dst_node;)
 		  {
-		    ipa_remove_stmt_references (node, gsi_stmt (bsi));
+		    node->remove_stmt_references (gsi_stmt (bsi));
 		    if (gimple_code (gsi_stmt (bsi)) == GIMPLE_CALL
 			&& (e = cgraph_edge (node, gsi_stmt (bsi))) != NULL)
 		      {
diff --git a/gcc/varpool.c b/gcc/varpool.c
index f6f8365..b41071f 100644
--- a/gcc/varpool.c
+++ b/gcc/varpool.c
@@ -423,11 +423,12 @@  static void
 assemble_aliases (varpool_node *node)
 {
   int i;
-  struct ipa_ref *ref;
-  for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list, i, ref); i++)
+  struct ipa_ref *ref = NULL;
+
+  for (i = 0; node->iterate_referring (i, ref); i++)
     if (ref->use == IPA_REF_ALIAS)
       {
-	varpool_node *alias = ipa_ref_referring_varpool_node (ref);
+	varpool_node *alias = dyn_cast <varpool_node *> (ref->referring);
 	do_assemble_alias (alias->decl,
 			   DECL_ASSEMBLER_NAME (node->decl));
 	assemble_aliases (alias);
@@ -504,7 +505,7 @@  varpool_remove_unreferenced_decls (void)
   varpool_node *next, *node;
   varpool_node *first = (varpool_node *)(void *)1;
   int i;
-  struct ipa_ref *ref;
+  struct ipa_ref *ref = NULL;
   struct pointer_set_t *referenced = pointer_set_create ();
 
   if (seen_error ())
@@ -542,7 +543,7 @@  varpool_remove_unreferenced_decls (void)
 		enqueue_node (vnext, &first);
 	    }
 	}
-      for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list, i, ref); i++)
+      for (i = 0; node->iterate_reference (i, ref); i++)
 	{
 	  varpool_node *vnode = dyn_cast <varpool_node *> (ref->referred);
 	  if (vnode
@@ -692,14 +693,14 @@  varpool_for_node_and_aliases (varpool_node *node,
 			      bool include_overwritable)
 {
   int i;
-  struct ipa_ref *ref;
+  struct ipa_ref *ref = NULL;
 
   if (callback (node, data))
     return true;
-  for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list, i, ref); i++)
+  for (i = 0; node->iterate_referring (i, ref); i++)
     if (ref->use == IPA_REF_ALIAS)
       {
-	varpool_node *alias = ipa_ref_referring_varpool_node (ref);
+	varpool_node *alias = dyn_cast <varpool_node *> (ref->referring);
 	if (include_overwritable
 	    || cgraph_variable_initializer_availability (alias) > AVAIL_OVERWRITABLE)
           if (varpool_for_node_and_aliases (alias, callback, data,