Commit 369451ec by Jan Hubicka Committed by Jan Hubicka

cgraphbuild.c (record_reference_ctx): Add varpool_node.

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

From-SVN: r159097
parent 03a904b5
2010-05-06 Jan Hubicka <jh@suse.cz>
* cgraphbuild.c (record_reference_ctx): Add varpool_node.
(record_reference, mark_address, mark_load, mark_store): Record
references.
(record_references_in_initializer): Update call of record_references.
(rebuild_cgraph_edges): Remove all references before rebuiding.
* cgraph.c (cgraph_create_node): Clear ref list.
(cgraph_remove_node): Remove references.
(dump_cgraph_node): Dump references.
(cgraph_clone_node): Clone references.
* cgraph.h: Include ipa-ref.h and ipa-ref-inline.h
(struct cgraph_node, varpool_node): Add ref_lst.
* ipa-ref.c: New file.
* ipa-ref.h: New file.
* ipa-ref-inline.h: New file.
* lto-cgraph.c (output_varpool): Take cgrag node set argument.
(referenced_from_other_partition_p): New function.
(lto_output_varpool_node): Take set arugment; call
referenced_from_other_partition.
(lto_output_ref): New.
(add_references): New.
(output_refs): New.
(output_cgraph): Compute boundary based on references;
output refs.
(output_varpool): Accept cgraph_node_set argument.
(input_ref): New.
(input_refs): New.
(input_cgraph): Call input_refs.
* lto-section-in.c (lto_section_name): Add refs.
* Makefile.in: (cgraph.h): Include ipa-ref.h and ipa-ref-inline.h
(ipa-ref.o): New file.
* varpool.c (varpool_node): Clear ipa ref list.
(varpool_remove_node): Remove references.
(dump_varpool_node): Dump references.
(varpool_assemble_decl): Only compile finalized ones.
(varpool_extra_name_alias): Initialize ref list.
* lto-streamer.c (lto-get_section_name): Add .refs section.
* lto-streamer.h (lto_section_type): Add LTO_section_refs.
(referenced_from_other_partition_p): Declared.
2010-05-06 Ira Rosen <irar@il.ibm.com> 2010-05-06 Ira Rosen <irar@il.ibm.com>
PR tree-optimization/43901 PR tree-optimization/43901
......
...@@ -904,7 +904,7 @@ CFGLOOP_H = cfgloop.h $(BASIC_BLOCK_H) $(RTL_H) vecprim.h double-int.h ...@@ -904,7 +904,7 @@ CFGLOOP_H = cfgloop.h $(BASIC_BLOCK_H) $(RTL_H) vecprim.h double-int.h
IPA_UTILS_H = ipa-utils.h $(TREE_H) $(CGRAPH_H) IPA_UTILS_H = ipa-utils.h $(TREE_H) $(CGRAPH_H)
IPA_REFERENCE_H = ipa-reference.h $(BITMAP_H) $(TREE_H) IPA_REFERENCE_H = ipa-reference.h $(BITMAP_H) $(TREE_H)
IPA_TYPE_ESCAPE_H = ipa-type-escape.h $(TREE_H) IPA_TYPE_ESCAPE_H = ipa-type-escape.h $(TREE_H)
CGRAPH_H = cgraph.h $(TREE_H) $(BASIC_BLOCK_H) cif-code.def CGRAPH_H = cgraph.h $(TREE_H) $(BASIC_BLOCK_H) cif-code.def ipa-ref.h ipa-ref-inline.h
DF_H = df.h $(BITMAP_H) $(BASIC_BLOCK_H) alloc-pool.h $(TIMEVAR_H) DF_H = df.h $(BITMAP_H) $(BASIC_BLOCK_H) alloc-pool.h $(TIMEVAR_H)
RESOURCE_H = resource.h hard-reg-set.h $(DF_H) RESOURCE_H = resource.h hard-reg-set.h $(DF_H)
DDG_H = ddg.h sbitmap.h $(DF_H) DDG_H = ddg.h sbitmap.h $(DF_H)
...@@ -1425,6 +1425,7 @@ OBJS-archive = \ ...@@ -1425,6 +1425,7 @@ OBJS-archive = \
ipa-prop.o \ ipa-prop.o \
ipa-pure-const.o \ ipa-pure-const.o \
ipa-reference.o \ ipa-reference.o \
ipa-ref.o \
ipa-struct-reorg.o \ ipa-struct-reorg.o \
ipa-type-escape.o \ ipa-type-escape.o \
ipa-utils.o \ ipa-utils.o \
...@@ -2902,6 +2903,9 @@ ipa-prop.o : ipa-prop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ ...@@ -2902,6 +2903,9 @@ ipa-prop.o : ipa-prop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
langhooks.h $(GGC_H) $(TARGET_H) $(CGRAPH_H) $(IPA_PROP_H) $(DIAGNOSTIC_H) \ langhooks.h $(GGC_H) $(TARGET_H) $(CGRAPH_H) $(IPA_PROP_H) $(DIAGNOSTIC_H) \
$(TREE_FLOW_H) $(TM_H) $(TREE_PASS_H) $(FLAGS_H) $(TREE_H) \ $(TREE_FLOW_H) $(TM_H) $(TREE_PASS_H) $(FLAGS_H) $(TREE_H) \
$(TREE_INLINE_H) $(TIMEVAR_H) $(TREE_INLINE_H) $(TIMEVAR_H)
ipa-ref.o : ipa-ref.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
langhooks.h $(GGC_H) $(TARGET_H) $(CGRAPH_H) $(TREE_H) $(TARGET_H) \
$(TREE_FLOW_H) $(TM_H) $(TREE_PASS_H) $(FLAGS_H) $(TREE_H) $(GGC_H)
ipa-cp.o : ipa-cp.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ ipa-cp.o : ipa-cp.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TREE_H) $(TARGET_H) $(CGRAPH_H) $(IPA_PROP_H) $(TREE_FLOW_H) \ $(TREE_H) $(TARGET_H) $(CGRAPH_H) $(IPA_PROP_H) $(TREE_FLOW_H) \
$(TREE_PASS_H) $(FLAGS_H) $(TIMEVAR_H) $(DIAGNOSTIC_H) $(TREE_DUMP_H) \ $(TREE_PASS_H) $(FLAGS_H) $(TIMEVAR_H) $(DIAGNOSTIC_H) $(TREE_DUMP_H) \
...@@ -3584,7 +3588,7 @@ GTFILES = $(CPP_ID_DATA_H) $(srcdir)/input.h $(srcdir)/coretypes.h \ ...@@ -3584,7 +3588,7 @@ GTFILES = $(CPP_ID_DATA_H) $(srcdir)/input.h $(srcdir)/coretypes.h \
$(srcdir)/real.h $(srcdir)/function.h $(srcdir)/insn-addr.h $(srcdir)/hwint.h \ $(srcdir)/real.h $(srcdir)/function.h $(srcdir)/insn-addr.h $(srcdir)/hwint.h \
$(srcdir)/fixed-value.h \ $(srcdir)/fixed-value.h \
$(srcdir)/ipa-reference.h $(srcdir)/output.h $(srcdir)/cfgloop.h \ $(srcdir)/ipa-reference.h $(srcdir)/output.h $(srcdir)/cfgloop.h \
$(srcdir)/cselib.h $(srcdir)/basic-block.h $(srcdir)/cgraph.h \ $(srcdir)/cselib.h $(srcdir)/basic-block.h $(srcdir)/ipa-ref.h $(srcdir)/cgraph.h \
$(srcdir)/reload.h $(srcdir)/caller-save.c \ $(srcdir)/reload.h $(srcdir)/caller-save.c \
$(srcdir)/alias.c $(srcdir)/bitmap.c $(srcdir)/cselib.c $(srcdir)/cgraph.c \ $(srcdir)/alias.c $(srcdir)/bitmap.c $(srcdir)/cselib.c $(srcdir)/cgraph.c \
$(srcdir)/ipa-prop.c $(srcdir)/ipa-cp.c $(srcdir)/ipa-inline.c $(srcdir)/matrix-reorg.c \ $(srcdir)/ipa-prop.c $(srcdir)/ipa-cp.c $(srcdir)/ipa-inline.c $(srcdir)/matrix-reorg.c \
......
...@@ -463,6 +463,7 @@ cgraph_create_node (void) ...@@ -463,6 +463,7 @@ cgraph_create_node (void)
node->previous = NULL; node->previous = NULL;
node->global.estimated_growth = INT_MIN; node->global.estimated_growth = INT_MIN;
node->frequency = NODE_FREQUENCY_NORMAL; node->frequency = NODE_FREQUENCY_NORMAL;
ipa_empty_ref_list (&node->ref_list);
cgraph_nodes = node; cgraph_nodes = node;
cgraph_n_nodes++; cgraph_n_nodes++;
return node; return node;
...@@ -1412,6 +1413,8 @@ cgraph_remove_node (struct cgraph_node *node) ...@@ -1412,6 +1413,8 @@ cgraph_remove_node (struct cgraph_node *node)
cgraph_call_node_removal_hooks (node); cgraph_call_node_removal_hooks (node);
cgraph_node_remove_callers (node); cgraph_node_remove_callers (node);
cgraph_node_remove_callees (node); cgraph_node_remove_callees (node);
ipa_remove_all_references (&node->ref_list);
ipa_remove_all_refering (&node->ref_list);
VEC_free (ipa_opt_pass, heap, VEC_free (ipa_opt_pass, heap,
node->ipa_transforms_to_apply); node->ipa_transforms_to_apply);
...@@ -1853,6 +1856,10 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node) ...@@ -1853,6 +1856,10 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node)
fprintf(f, "(can throw external) "); fprintf(f, "(can throw external) ");
} }
fprintf (f, "\n"); fprintf (f, "\n");
fprintf (f, " References: ");
ipa_dump_references (f, &node->ref_list);
fprintf (f, " Refering this function: ");
ipa_dump_refering (f, &node->ref_list);
for (edge = node->indirect_calls; edge; edge = edge->next_callee) for (edge = node->indirect_calls; edge; edge = edge->next_callee)
indirect_calls_count++; indirect_calls_count++;
...@@ -2081,6 +2088,7 @@ cgraph_clone_node (struct cgraph_node *n, gcov_type count, int freq, ...@@ -2081,6 +2088,7 @@ cgraph_clone_node (struct cgraph_node *n, gcov_type count, int freq,
for (e = n->indirect_calls; e; e = e->next_callee) for (e = n->indirect_calls; e; e = e->next_callee)
cgraph_clone_edge (e, new_node, e->call_stmt, e->lto_stmt_uid, cgraph_clone_edge (e, new_node, e->call_stmt, e->lto_stmt_uid,
count_scale, freq, loop_nest, update_original); count_scale, freq, loop_nest, update_original);
ipa_clone_references (new_node, NULL, &n->ref_list);
new_node->next_sibling_clone = n->clones; new_node->next_sibling_clone = n->clones;
if (n->clones) if (n->clones)
......
...@@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see
#define GCC_CGRAPH_H #define GCC_CGRAPH_H
#include "tree.h" #include "tree.h"
#include "basic-block.h" #include "basic-block.h"
#include "ipa-ref.h"
enum availability enum availability
{ {
...@@ -224,6 +225,7 @@ struct GTY((chain_next ("%h.next"), chain_prev ("%h.previous"))) cgraph_node { ...@@ -224,6 +225,7 @@ struct GTY((chain_next ("%h.next"), chain_prev ("%h.previous"))) cgraph_node {
per-function in order to allow IPA passes to introduce new functions. */ per-function in order to allow IPA passes to introduce new functions. */
VEC(ipa_opt_pass,heap) * GTY((skip)) ipa_transforms_to_apply; VEC(ipa_opt_pass,heap) * GTY((skip)) ipa_transforms_to_apply;
struct ipa_ref_list ref_list;
struct cgraph_local_info local; struct cgraph_local_info local;
struct cgraph_global_info global; struct cgraph_global_info global;
struct cgraph_rtl_info rtl; struct cgraph_rtl_info rtl;
...@@ -427,7 +429,7 @@ DEF_VEC_ALLOC_P(cgraph_edge_p,heap); ...@@ -427,7 +429,7 @@ DEF_VEC_ALLOC_P(cgraph_edge_p,heap);
/* The varpool data structure. /* The varpool data structure.
Each static variable decl has assigned varpool_node. */ Each static variable decl has assigned varpool_node. */
struct GTY((chain_next ("%h.next"))) varpool_node { struct GTY((chain_next ("%h.next"), chain_prev ("%h.prev"))) varpool_node {
tree decl; tree decl;
/* Pointer to the next function in varpool_nodes. */ /* Pointer to the next function in varpool_nodes. */
struct varpool_node *next, *prev; struct varpool_node *next, *prev;
...@@ -436,6 +438,7 @@ struct GTY((chain_next ("%h.next"))) varpool_node { ...@@ -436,6 +438,7 @@ struct GTY((chain_next ("%h.next"))) varpool_node {
/* For normal nodes a pointer to the first extra name alias. For alias /* For normal nodes a pointer to the first extra name alias. For alias
nodes a pointer to the normal node. */ nodes a pointer to the normal node. */
struct varpool_node *extra_name; struct varpool_node *extra_name;
struct ipa_ref_list ref_list;
/* Ordering of all cgraph nodes. */ /* Ordering of all cgraph nodes. */
int order; int order;
...@@ -864,4 +867,6 @@ cgraph_can_remove_if_no_direct_calls_p (struct cgraph_node *node) ...@@ -864,4 +867,6 @@ cgraph_can_remove_if_no_direct_calls_p (struct cgraph_node *node)
/* Constant pool accessor function. */ /* Constant pool accessor function. */
htab_t constant_pool_htab (void); htab_t constant_pool_htab (void);
#include "ipa-ref-inline.h"
#endif /* GCC_CGRAPH_H */ #endif /* GCC_CGRAPH_H */
...@@ -37,6 +37,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -37,6 +37,7 @@ along with GCC; see the file COPYING3. If not see
struct record_reference_ctx struct record_reference_ctx
{ {
bool only_vars; bool only_vars;
struct varpool_node *varpool_node;
}; };
/* Walk tree and record all calls and references to functions/variables. /* Walk tree and record all calls and references to functions/variables.
...@@ -63,15 +64,26 @@ record_reference (tree *tp, int *walk_subtrees, void *data) ...@@ -63,15 +64,26 @@ record_reference (tree *tp, int *walk_subtrees, void *data)
/* Record dereferences to the functions. This makes the /* Record dereferences to the functions. This makes the
functions reachable unconditionally. */ functions reachable unconditionally. */
decl = get_base_var (*tp); decl = get_base_var (*tp);
if (TREE_CODE (decl) == FUNCTION_DECL && !ctx->only_vars) if (TREE_CODE (decl) == FUNCTION_DECL)
cgraph_mark_address_taken_node (cgraph_node (decl)); {
if (!ctx->only_vars)
cgraph_mark_address_taken_node (cgraph_node (decl));
ipa_record_reference (NULL, ctx->varpool_node,
cgraph_node (decl), NULL,
IPA_REF_ADDR, NULL);
}
if (TREE_CODE (decl) == VAR_DECL) if (TREE_CODE (decl) == VAR_DECL)
{ {
gcc_assert (TREE_STATIC (decl) || DECL_EXTERNAL (decl)); struct varpool_node *vnode = varpool_node (decl);
if (lang_hooks.callgraph.analyze_expr) if (lang_hooks.callgraph.analyze_expr)
lang_hooks.callgraph.analyze_expr (&decl, walk_subtrees); lang_hooks.callgraph.analyze_expr (&decl, walk_subtrees);
varpool_mark_needed_node (varpool_node (decl)); varpool_mark_needed_node (vnode);
if (vnode->alias && vnode->extra_name)
vnode = vnode->extra_name;
ipa_record_reference (NULL, ctx->varpool_node,
NULL, vnode,
IPA_REF_ADDR, NULL);
} }
*walk_subtrees = 0; *walk_subtrees = 0;
break; break;
...@@ -148,6 +160,9 @@ mark_address (gimple stmt ATTRIBUTE_UNUSED, tree addr, ...@@ -148,6 +160,9 @@ mark_address (gimple stmt ATTRIBUTE_UNUSED, tree addr,
{ {
struct cgraph_node *node = cgraph_node (addr); struct cgraph_node *node = cgraph_node (addr);
cgraph_mark_address_taken_node (node); cgraph_mark_address_taken_node (node);
ipa_record_reference ((struct cgraph_node *)data, NULL,
node, NULL,
IPA_REF_ADDR, stmt);
} }
else else
{ {
...@@ -161,6 +176,11 @@ mark_address (gimple stmt ATTRIBUTE_UNUSED, tree addr, ...@@ -161,6 +176,11 @@ mark_address (gimple stmt ATTRIBUTE_UNUSED, tree addr,
if (lang_hooks.callgraph.analyze_expr) if (lang_hooks.callgraph.analyze_expr)
lang_hooks.callgraph.analyze_expr (&addr, &walk_subtrees); lang_hooks.callgraph.analyze_expr (&addr, &walk_subtrees);
varpool_mark_needed_node (vnode); varpool_mark_needed_node (vnode);
if (vnode->alias && vnode->extra_name)
vnode = vnode->extra_name;
ipa_record_reference ((struct cgraph_node *)data, NULL,
NULL, vnode,
IPA_REF_ADDR, stmt);
} }
} }
...@@ -183,6 +203,11 @@ mark_load (gimple stmt ATTRIBUTE_UNUSED, tree t, ...@@ -183,6 +203,11 @@ mark_load (gimple stmt ATTRIBUTE_UNUSED, tree t,
if (lang_hooks.callgraph.analyze_expr) if (lang_hooks.callgraph.analyze_expr)
lang_hooks.callgraph.analyze_expr (&t, &walk_subtrees); lang_hooks.callgraph.analyze_expr (&t, &walk_subtrees);
varpool_mark_needed_node (vnode); varpool_mark_needed_node (vnode);
if (vnode->alias && vnode->extra_name)
vnode = vnode->extra_name;
ipa_record_reference ((struct cgraph_node *)data, NULL,
NULL, vnode,
IPA_REF_LOAD, stmt);
} }
return false; return false;
} }
...@@ -203,6 +228,11 @@ mark_store (gimple stmt ATTRIBUTE_UNUSED, tree t, ...@@ -203,6 +228,11 @@ mark_store (gimple stmt ATTRIBUTE_UNUSED, tree t,
if (lang_hooks.callgraph.analyze_expr) if (lang_hooks.callgraph.analyze_expr)
lang_hooks.callgraph.analyze_expr (&t, &walk_subtrees); lang_hooks.callgraph.analyze_expr (&t, &walk_subtrees);
varpool_mark_needed_node (vnode); varpool_mark_needed_node (vnode);
if (vnode->alias && vnode->extra_name)
vnode = vnode->extra_name;
ipa_record_reference ((struct cgraph_node *)data, NULL,
NULL, vnode,
IPA_REF_STORE, NULL);
} }
return false; return false;
} }
...@@ -299,8 +329,10 @@ void ...@@ -299,8 +329,10 @@ void
record_references_in_initializer (tree decl, bool only_vars) record_references_in_initializer (tree decl, bool only_vars)
{ {
struct pointer_set_t *visited_nodes = pointer_set_create (); struct pointer_set_t *visited_nodes = pointer_set_create ();
struct record_reference_ctx ctx = {false}; struct varpool_node *node = varpool_node (decl);
struct record_reference_ctx ctx = {false, NULL};
ctx.varpool_node = node;
ctx.only_vars = only_vars; ctx.only_vars = only_vars;
walk_tree (&DECL_INITIAL (decl), record_reference, walk_tree (&DECL_INITIAL (decl), record_reference,
&ctx, visited_nodes); &ctx, visited_nodes);
...@@ -318,6 +350,7 @@ rebuild_cgraph_edges (void) ...@@ -318,6 +350,7 @@ rebuild_cgraph_edges (void)
gimple_stmt_iterator gsi; gimple_stmt_iterator gsi;
cgraph_node_remove_callees (node); cgraph_node_remove_callees (node);
ipa_remove_all_references (&node->ref_list);
node->count = ENTRY_BLOCK_PTR->count; node->count = ENTRY_BLOCK_PTR->count;
......
/* IPA reference lists.
Copyright (C) 2010
Free Software Foundation, Inc.
Contributed by Jan Hubicka
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
/* Return callgraph node REF is refering. */
static inline struct cgraph_node *
ipa_ref_node (struct ipa_ref *ref)
{
gcc_assert (ref->refered_type == IPA_REF_CGRAPH);
return ref->refered.cgraph_node;
}
/* Return varpool node REF is refering. */
static inline struct varpool_node *
ipa_ref_varpool_node (struct ipa_ref *ref)
{
gcc_assert (ref->refered_type == IPA_REF_VARPOOL);
return ref->refered.varpool_node;
}
/* Return cgraph node REF is in. */
static inline struct cgraph_node *
ipa_ref_refering_node (struct ipa_ref *ref)
{
gcc_assert (ref->refering_type == IPA_REF_CGRAPH);
return ref->refering.cgraph_node;
}
/* Return varpool node REF is in. */
static inline struct varpool_node *
ipa_ref_refering_varpool_node (struct ipa_ref *ref)
{
gcc_assert (ref->refering_type == IPA_REF_VARPOOL);
return ref->refering.varpool_node;
}
/* Return reference list REF is in. */
static inline struct ipa_ref_list *
ipa_ref_refering_ref_list (struct ipa_ref *ref)
{
if (ref->refering_type == IPA_REF_CGRAPH)
return &ipa_ref_refering_node (ref)->ref_list;
else
return &ipa_ref_refering_varpool_node (ref)->ref_list;
}
/* Return reference list REF is in. */
static inline struct ipa_ref_list *
ipa_ref_refered_ref_list (struct ipa_ref *ref)
{
if (ref->refered_type == IPA_REF_CGRAPH)
return &ipa_ref_node (ref)->ref_list;
else
return &ipa_ref_varpool_node (ref)->ref_list;
}
/* Return first reference in LIST or NULL if empty. */
static inline struct ipa_ref *
ipa_ref_list_first_reference (struct ipa_ref_list *list)
{
if (!VEC_length (ipa_ref_t, list->references))
return NULL;
return VEC_index (ipa_ref_t, list->references, 0);
}
/* Return first refering ref in LIST or NULL if empty. */
static inline struct ipa_ref *
ipa_ref_list_first_refering (struct ipa_ref_list *list)
{
if (!VEC_length (ipa_ref_ptr, list->refering))
return NULL;
return VEC_index (ipa_ref_ptr, list->refering, 0);
}
/* Clear reference list. */
static inline void
ipa_empty_ref_list (struct ipa_ref_list *list)
{
list->refering = NULL;
list->references = NULL;
}
/* Clear reference list. */
static inline unsigned int
ipa_ref_list_nreferences (struct ipa_ref_list *list)
{
return VEC_length (ipa_ref_t, list->references);
}
#define ipa_ref_list_reference_iterate(L,I,P) \
VEC_iterate(ipa_ref_t, (L)->references, (I), (P))
#define ipa_ref_list_refering_iterate(L,I,P) \
VEC_iterate(ipa_ref_ptr, (L)->refering, (I), (P))
/* Interprocedural reference lists.
Copyright (C) 2010
Free Software Foundation, Inc.
Contributed by Jan Hubicka
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tree.h"
#include "ggc.h"
#include "target.h"
#include "cgraph.h"
static const char *ipa_ref_use_name[] = {"read","write","addr"};
/* Return ipa reference from REFERING_NODE or REFERING_VARPOOL_NODE
to REFERED_NODE or REFERED_VARPOOL_NODE. USE_TYPE specify type
of the use and STMT the statement (if it exists). */
struct ipa_ref *
ipa_record_reference (struct cgraph_node *refering_node,
struct varpool_node *refering_varpool_node,
struct cgraph_node *refered_node,
struct varpool_node *refered_varpool_node,
enum ipa_ref_use use_type, gimple stmt)
{
struct ipa_ref *ref;
struct ipa_ref_list *list, *list2;
VEC(ipa_ref_t,gc) *old_references;
gcc_assert ((!refering_node) ^ (!refering_varpool_node));
gcc_assert ((!refered_node) ^ (!refered_varpool_node));
gcc_assert (!stmt || refering_node);
list = (refering_node ? &refering_node->ref_list
: &refering_varpool_node->ref_list);
old_references = list->references;
VEC_safe_grow (ipa_ref_t, gc, list->references,
VEC_length (ipa_ref_t, list->references) + 1);
ref = VEC_last (ipa_ref_t, list->references);
list2 = (refered_node ? &refered_node->ref_list
: &refered_varpool_node->ref_list);
VEC_safe_push (ipa_ref_ptr, heap, list2->refering, ref);
ref->refered_index = VEC_length (ipa_ref_ptr, list2->refering) - 1;
if (refering_node)
{
ref->refering.cgraph_node = refering_node;
ref->refering_type = IPA_REF_CGRAPH;
}
else
{
ref->refering.varpool_node = refering_varpool_node;
ref->refering_type = IPA_REF_VARPOOL;
gcc_assert (use_type == IPA_REF_ADDR);
}
if (refered_node)
{
ref->refered.cgraph_node = refered_node;
ref->refered_type = IPA_REF_CGRAPH;
gcc_assert (use_type == IPA_REF_ADDR);
}
else
{
varpool_mark_needed_node (refered_varpool_node);
ref->refered.varpool_node = refered_varpool_node;
ref->refered_type = IPA_REF_VARPOOL;
}
ref->stmt = stmt;
ref->use = use_type;
/* If vector was moved in memory, update pointers. */
if (old_references != list->references)
{
int i;
for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++)
VEC_replace (ipa_ref_ptr,
ipa_ref_refered_ref_list (ref)->refering,
ref->refered_index, ref);
}
return ref;
}
/* Remove reference REF. */
void
ipa_remove_reference (struct ipa_ref *ref)
{
struct ipa_ref_list *list = ipa_ref_refered_ref_list (ref);
struct ipa_ref_list *list2 = ipa_ref_refering_ref_list (ref);
VEC(ipa_ref_t,gc) *old_references = list2->references;
struct ipa_ref *last;
gcc_assert (VEC_index (ipa_ref_ptr, list->refering, ref->refered_index) == ref);
last = VEC_last (ipa_ref_ptr, list->refering);
if (ref != last)
{
VEC_replace (ipa_ref_ptr, list->refering,
ref->refered_index,
VEC_last (ipa_ref_ptr, list->refering));
VEC_index (ipa_ref_ptr, list->refering,
ref->refered_index)->refered_index = ref->refered_index;
}
VEC_pop (ipa_ref_ptr, list->refering);
last = VEC_last (ipa_ref_t, list2->references);
if (ref != last)
{
*ref = *last;
VEC_replace (ipa_ref_ptr,
ipa_ref_refered_ref_list (ref)->refering,
ref->refered_index, ref);
}
VEC_pop (ipa_ref_t, list2->references);
gcc_assert (list2->references == old_references);
}
/* Remove all references in ref list LIST. */
void
ipa_remove_all_references (struct ipa_ref_list *list)
{
while (VEC_length (ipa_ref_t, list->references))
ipa_remove_reference (VEC_last (ipa_ref_t, list->references));
VEC_free (ipa_ref_t, gc, list->references);
list->references = NULL;
}
/* Remove all references in ref list LIST. */
void
ipa_remove_all_refering (struct ipa_ref_list *list)
{
while (VEC_length (ipa_ref_ptr, list->refering))
ipa_remove_reference (VEC_last (ipa_ref_ptr, list->refering));
VEC_free (ipa_ref_ptr, heap, list->refering);
list->refering = NULL;
}
/* Dump references in LIST to FILE. */
void
ipa_dump_references (FILE * file, struct ipa_ref_list *list)
{
struct ipa_ref *ref;
int i;
for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++)
{
if (ref->refered_type == IPA_REF_CGRAPH)
{
fprintf (file, " fn:%s/%i (%s)", cgraph_node_name (ipa_ref_node (ref)),
ipa_ref_node (ref)->uid,
ipa_ref_use_name [ref->use]);
}
else
fprintf (file, " var:%s (%s)",
varpool_node_name (ipa_ref_varpool_node (ref)),
ipa_ref_use_name [ref->use]);
}
fprintf (file, "\n");
}
/* Dump refering in LIST to FILE. */
void
ipa_dump_refering (FILE * file, struct ipa_ref_list *list)
{
struct ipa_ref *ref;
int i;
for (i = 0; ipa_ref_list_refering_iterate (list, i, ref); i++)
{
if (ref->refering_type == IPA_REF_CGRAPH)
fprintf (file, " fn:%s/%i (%s)",
cgraph_node_name (ipa_ref_refering_node (ref)),
ipa_ref_refering_node (ref)->uid,
ipa_ref_use_name [ref->use]);
else
fprintf (file, " var:%s (%s)",
varpool_node_name (ipa_ref_refering_varpool_node (ref)),
ipa_ref_use_name [ref->use]);
}
fprintf (file, "\n");
}
/* Clone all references from SRC to DEST_NODE or DEST_VARPOL_NODE. */
void
ipa_clone_references (struct cgraph_node *dest_node,
struct varpool_node *dest_varpool_node,
struct ipa_ref_list *src)
{
struct ipa_ref *ref;
int i;
for (i = 0; ipa_ref_list_reference_iterate (src, i, ref); i++)
ipa_record_reference (dest_node, dest_varpool_node,
ref->refered_type == IPA_REF_CGRAPH
? ipa_ref_node (ref) : NULL,
ref->refered_type == IPA_REF_VARPOOL
? ipa_ref_varpool_node (ref) : NULL,
ref->use, ref->stmt);
}
/* Clone all refering from SRC to DEST_NODE or DEST_VARPOL_NODE. */
void
ipa_clone_refering (struct cgraph_node *dest_node,
struct varpool_node *dest_varpool_node,
struct ipa_ref_list *src)
{
struct ipa_ref *ref;
int i;
for (i = 0; ipa_ref_list_refering_iterate (src, i, ref); i++)
ipa_record_reference (
ref->refering_type == IPA_REF_CGRAPH
? ipa_ref_refering_node (ref) : NULL,
ref->refering_type == IPA_REF_VARPOOL
? ipa_ref_refering_varpool_node (ref) : NULL,
dest_node, dest_varpool_node,
ref->use, ref->stmt);
}
/* IPA reference lists.
Copyright (C) 2010
Free Software Foundation, Inc.
Contributed by Jan Hubicka
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
struct cgraph_node;
struct varpool_node;
/* How the reference is done. */
enum GTY(()) ipa_ref_use
{
IPA_REF_LOAD,
IPA_REF_STORE,
IPA_REF_ADDR
};
/* Type of refering or refered type. */
enum GTY(()) ipa_ref_type
{
IPA_REF_CGRAPH,
IPA_REF_VARPOOL
};
/* We can have references spanning both callgraph and varpool,
so all pointers needs to be of both types. */
union GTY(()) ipa_ref_ptr_u
{
struct cgraph_node * GTY((tag ("IPA_REF_CGRAPH"))) cgraph_node;
struct varpool_node * GTY((tag ("IPA_REF_VARPOOL"))) varpool_node;
};
/* Record of reference in callgraph or varpool. */
struct GTY(()) ipa_ref
{
union ipa_ref_ptr_u GTY ((desc ("%1.refering_type"))) refering;
union ipa_ref_ptr_u GTY ((desc ("%1.refered_type"))) refered;
gimple stmt;
unsigned int refered_index;
ENUM_BITFIELD (ipa_ref_type) refering_type:1;
ENUM_BITFIELD (ipa_ref_type) refered_type:1;
ENUM_BITFIELD (ipa_ref_use) use:2;
};
typedef struct ipa_ref ipa_ref_t;
typedef struct ipa_ref *ipa_ref_ptr;
DEF_VEC_O(ipa_ref_t);
DEF_VEC_ALLOC_O(ipa_ref_t,gc);
DEF_VEC_P(ipa_ref_ptr);
DEF_VEC_ALLOC_P(ipa_ref_ptr,heap);
/* List of references. This is stored in both callgraph and varpool nodes. */
struct GTY(()) ipa_ref_list
{
/* Store actual references in references vector. */
VEC(ipa_ref_t,gc) *references;
/* Refering is vector of pointers to references. It must not live in GGC space
or GGC will try to mark middle of references vectors. */
VEC(ipa_ref_ptr,heap) * GTY((skip)) refering;
};
struct ipa_ref * ipa_record_reference (struct cgraph_node *,
struct varpool_node *,
struct cgraph_node *,
struct varpool_node *,
enum ipa_ref_use, gimple);
void ipa_remove_reference (struct ipa_ref *);
void ipa_remove_all_references (struct ipa_ref_list *);
void ipa_remove_all_refering (struct ipa_ref_list *);
void ipa_dump_references (FILE *, struct ipa_ref_list *);
void ipa_dump_refering (FILE *, struct ipa_ref_list *);
void ipa_clone_references (struct cgraph_node *, struct varpool_node *, struct ipa_ref_list *);
void ipa_clone_refering (struct cgraph_node *, struct varpool_node *, struct ipa_ref_list *);
...@@ -53,6 +53,7 @@ const char *lto_section_name[LTO_N_SECTION_TYPES] = ...@@ -53,6 +53,7 @@ const char *lto_section_name[LTO_N_SECTION_TYPES] =
"static_initializer", "static_initializer",
"cgraph", "cgraph",
"varpool", "varpool",
"refs",
"jump_funcs" "jump_funcs"
"ipa_pure_const", "ipa_pure_const",
"ipa_reference", "ipa_reference",
......
...@@ -163,6 +163,9 @@ lto_get_section_name (int section_type, const char *name) ...@@ -163,6 +163,9 @@ lto_get_section_name (int section_type, const char *name)
case LTO_section_varpool: case LTO_section_varpool:
return concat (LTO_SECTION_NAME_PREFIX, ".vars", NULL); return concat (LTO_SECTION_NAME_PREFIX, ".vars", NULL);
case LTO_section_refs:
return concat (LTO_SECTION_NAME_PREFIX, ".refs", NULL);
case LTO_section_jump_functions: case LTO_section_jump_functions:
return concat (LTO_SECTION_NAME_PREFIX, ".jmpfuncs", NULL); return concat (LTO_SECTION_NAME_PREFIX, ".jmpfuncs", NULL);
......
...@@ -257,6 +257,7 @@ enum lto_section_type ...@@ -257,6 +257,7 @@ enum lto_section_type
LTO_section_static_initializer, LTO_section_static_initializer,
LTO_section_cgraph, LTO_section_cgraph,
LTO_section_varpool, LTO_section_varpool,
LTO_section_refs,
LTO_section_jump_functions, LTO_section_jump_functions,
LTO_section_ipa_pure_const, LTO_section_ipa_pure_const,
LTO_section_ipa_reference, LTO_section_ipa_reference,
...@@ -855,6 +856,9 @@ bool lto_varpool_encoder_encode_initializer_p (lto_varpool_encoder_t, ...@@ -855,6 +856,9 @@ bool lto_varpool_encoder_encode_initializer_p (lto_varpool_encoder_t,
struct varpool_node *); struct varpool_node *);
void output_cgraph (cgraph_node_set, varpool_node_set); void output_cgraph (cgraph_node_set, varpool_node_set);
void input_cgraph (void); void input_cgraph (void);
bool referenced_from_other_partition_p (struct ipa_ref_list *,
cgraph_node_set,
varpool_node_set vset);
/* In lto-symtab.c. */ /* In lto-symtab.c. */
......
...@@ -214,6 +214,8 @@ lto_cgraph_replace_node (struct cgraph_node *node, ...@@ -214,6 +214,8 @@ lto_cgraph_replace_node (struct cgraph_node *node,
next = e->next_caller; next = e->next_caller;
cgraph_redirect_edge_callee (e, prevailing_node); cgraph_redirect_edge_callee (e, prevailing_node);
} }
/* Redirect incomming references. */
ipa_clone_refering (prevailing_node, NULL, &node->ref_list);
if (node->same_body) if (node->same_body)
{ {
...@@ -273,6 +275,12 @@ lto_varpool_replace_node (struct varpool_node *vnode, ...@@ -273,6 +275,12 @@ lto_varpool_replace_node (struct varpool_node *vnode,
gcc_assert (!vnode->finalized || prevailing_node->finalized); gcc_assert (!vnode->finalized || prevailing_node->finalized);
gcc_assert (!vnode->analyzed || prevailing_node->analyzed); gcc_assert (!vnode->analyzed || prevailing_node->analyzed);
/* When replacing by an alias, the references goes to the original
variable. */
if (prevailing_node->alias && prevailing_node->extra_name)
prevailing_node = prevailing_node->extra_name;
ipa_clone_refering (NULL, prevailing_node, &vnode->ref_list);
/* Finally remove the replaced node. */ /* Finally remove the replaced node. */
varpool_remove_node (vnode); varpool_remove_node (vnode);
} }
......
2010-05-05 Jan Hubicka <jh@suse.cz> 2010-05-05 Jan Hubicka <jh@suse.cz>
* lto.c (lto_promote_cross_file_statics): Compute boundary based on refs.
2010-05-05 Jan Hubicka <jh@suse.cz>
* lto.c (lto_1_to_1_map): Partition only needed nodes. * lto.c (lto_1_to_1_map): Partition only needed nodes.
2010-04-30 Jan Hubicka <jh@suse.cz> 2010-04-30 Jan Hubicka <jh@suse.cz>
......
...@@ -718,36 +718,30 @@ lto_promote_cross_file_statics (void) ...@@ -718,36 +718,30 @@ lto_promote_cross_file_statics (void)
struct varpool_node *vnode; struct varpool_node *vnode;
unsigned i, n_sets; unsigned i, n_sets;
cgraph_node_set set; cgraph_node_set set;
varpool_node_set vset;
cgraph_node_set_iterator csi; cgraph_node_set_iterator csi;
varpool_node_set_iterator vsi;
gcc_assert (flag_wpa); gcc_assert (flag_wpa);
/* At moment we make no attempt to figure out who is refering the variables,
so all must become global.
Constant pool references use internal labels and thus can not be made global.
It is sensible to keep those ltrans local to allow better optimization. */
for (vnode = varpool_nodes; vnode; vnode = vnode->next)
if (!vnode->externally_visible && vnode->analyzed
&& !DECL_IN_CONSTANT_POOL (vnode->decl))
{
TREE_PUBLIC (vnode->decl) = 1;
DECL_VISIBILITY (vnode->decl) = VISIBILITY_HIDDEN;
}
n_sets = VEC_length (cgraph_node_set, lto_cgraph_node_sets); n_sets = VEC_length (cgraph_node_set, lto_cgraph_node_sets);
for (i = 0; i < n_sets; i++) for (i = 0; i < n_sets; i++)
{ {
set = VEC_index (cgraph_node_set, lto_cgraph_node_sets, i); set = VEC_index (cgraph_node_set, lto_cgraph_node_sets, i);
vset = VEC_index (varpool_node_set, lto_varpool_node_sets, i);
/* If node has either address taken (and we have no clue from where) /* If node has either address taken (and we have no clue from where)
or it is called from other partition, it needs to be globalized. */ or it is called from other partition, it needs to be globalized. */
for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi)) for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi))
{ {
struct cgraph_node *node = csi_node (csi); struct cgraph_node *node = csi_node (csi);
bool globalize = node->address_taken || node->local.vtable_method; bool globalize = node->local.vtable_method;
struct cgraph_edge *e; struct cgraph_edge *e;
if (node->local.externally_visible) if (node->local.externally_visible)
continue; continue;
if (!globalize
&& referenced_from_other_partition_p (&node->ref_list, set, vset))
globalize = true;
for (e = node->callers; e && !globalize; e = e->next_caller) for (e = node->callers; e && !globalize; e = e->next_caller)
{ {
struct cgraph_node *caller = e->caller; struct cgraph_node *caller = e->caller;
...@@ -758,6 +752,7 @@ lto_promote_cross_file_statics (void) ...@@ -758,6 +752,7 @@ lto_promote_cross_file_statics (void)
} }
if (globalize) if (globalize)
{ {
gcc_assert (flag_wpa);
TREE_PUBLIC (node->decl) = 1; TREE_PUBLIC (node->decl) = 1;
DECL_VISIBILITY (node->decl) = VISIBILITY_HIDDEN; DECL_VISIBILITY (node->decl) = VISIBILITY_HIDDEN;
if (node->same_body) if (node->same_body)
...@@ -772,6 +767,21 @@ lto_promote_cross_file_statics (void) ...@@ -772,6 +767,21 @@ lto_promote_cross_file_statics (void)
} }
} }
} }
for (vsi = vsi_start (vset); !vsi_end_p (vsi); vsi_next (&vsi))
{
vnode = vsi_node (vsi);
/* Constant pool references use internal labels and thus can not
be made global. It is sensible to keep those ltrans local to
allow better optimization. */
if (!DECL_IN_CONSTANT_POOL (vnode->decl)
&& !vnode->externally_visible && vnode->analyzed
&& referenced_from_other_partition_p (&vnode->ref_list, set, vset))
{
gcc_assert (flag_wpa);
TREE_PUBLIC (vnode->decl) = 1;
DECL_VISIBILITY (vnode->decl) = VISIBILITY_HIDDEN;
}
}
} }
} }
...@@ -1457,7 +1467,7 @@ lto_fixup_tree (tree *tp, int *walk_subtrees, void *data) ...@@ -1457,7 +1467,7 @@ lto_fixup_tree (tree *tp, int *walk_subtrees, void *data)
t = *tp; t = *tp;
*walk_subtrees = 0; *walk_subtrees = 0;
if (pointer_set_contains (fixup_data->seen, t)) if (!t || pointer_set_contains (fixup_data->seen, t))
return NULL; return NULL;
if (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == FUNCTION_DECL) if (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == FUNCTION_DECL)
......
...@@ -141,6 +141,7 @@ varpool_node (tree decl) ...@@ -141,6 +141,7 @@ varpool_node (tree decl)
node->decl = decl; node->decl = decl;
node->order = cgraph_order++; node->order = cgraph_order++;
node->next = varpool_nodes; node->next = varpool_nodes;
ipa_empty_ref_list (&node->ref_list);
if (varpool_nodes) if (varpool_nodes)
varpool_nodes->prev = node; varpool_nodes->prev = node;
varpool_nodes = node; varpool_nodes = node;
...@@ -193,6 +194,8 @@ varpool_remove_node (struct varpool_node *node) ...@@ -193,6 +194,8 @@ varpool_remove_node (struct varpool_node *node)
gcc_assert (varpool_nodes_queue == node); gcc_assert (varpool_nodes_queue == node);
varpool_nodes_queue = node->next_needed; varpool_nodes_queue = node->next_needed;
} }
ipa_remove_all_references (&node->ref_list);
ipa_remove_all_refering (&node->ref_list);
if (DECL_INITIAL (node->decl)) if (DECL_INITIAL (node->decl))
DECL_INITIAL (node->decl) = error_mark_node; DECL_INITIAL (node->decl) = error_mark_node;
ggc_free (node); ggc_free (node);
...@@ -228,6 +231,10 @@ dump_varpool_node (FILE *f, struct varpool_node *node) ...@@ -228,6 +231,10 @@ dump_varpool_node (FILE *f, struct varpool_node *node)
else if (node->used_from_other_partition) else if (node->used_from_other_partition)
fprintf (f, " used_from_other_partition"); fprintf (f, " used_from_other_partition");
fprintf (f, "\n"); fprintf (f, "\n");
fprintf (f, " References: ");
ipa_dump_references (f, &node->ref_list);
fprintf (f, " Refering this var: ");
ipa_dump_refering (f, &node->ref_list);
} }
/* Dump the variable pool. */ /* Dump the variable pool. */
...@@ -633,6 +640,7 @@ varpool_extra_name_alias (tree alias, tree decl) ...@@ -633,6 +640,7 @@ varpool_extra_name_alias (tree alias, tree decl)
alias_node->alias = 1; alias_node->alias = 1;
alias_node->extra_name = decl_node; alias_node->extra_name = decl_node;
alias_node->next = decl_node->extra_name; alias_node->next = decl_node->extra_name;
ipa_empty_ref_list (&alias_node->ref_list);
if (decl_node->extra_name) if (decl_node->extra_name)
decl_node->extra_name->prev = alias_node; decl_node->extra_name->prev = alias_node;
decl_node->extra_name = alias_node; decl_node->extra_name = alias_node;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment