aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRaksit Ashok <raksit@google.com>2010-06-15 15:37:57 +0000
committerRaksit Ashok <raksit@google.com>2010-06-15 15:37:57 +0000
commit04b3a5f9eaa8d9105e58f86bc16245ea5faaa776 (patch)
tree62670a7aa99c4757391da4cfecb12d974064f395
parent51c965e4d3e73175a3bbf957382507f93e9a4aaf (diff)
Fix a bug where weak decls could be multiply emitted, and another which caused bogus function IDs in direct call profiling.lw-ipo-4_5
git-svn-id: https://gcc.gnu.org/svn/gcc/branches/lw-ipo-4_5@160794 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/cgraph.h2
-rw-r--r--gcc/cgraphunit.c2
-rw-r--r--gcc/coverage.c14
-rw-r--r--gcc/dyn-ipa.c7
-rw-r--r--gcc/gcov-io.h1
-rw-r--r--gcc/l-ipo.c64
-rw-r--r--gcc/varpool.c2
7 files changed, 71 insertions, 21 deletions
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 67073f96e20..d601df5a7d0 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -555,6 +555,8 @@ struct varpool_node *real_varpool_node (tree decl);
bool varpool_is_auxiliary (struct varpool_node *node);
void varpool_get_referenced_asm_ids (VEC(tree, gc) **);
void varpool_clear_asm_id_reference_bit (void);
+void varpool_reset_queue (void);
+void varpool_remove_duplicate_weak_decls (void);
bool cgraph_decide_is_function_needed (struct cgraph_node *, tree);
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index d226d80efa3..acd50f5ae34 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -1856,6 +1856,7 @@ cgraph_output_in_order (void)
nodes = XCNEWVEC (struct cgraph_order_sort, max);
varpool_analyze_pending_decls ();
+ varpool_remove_duplicate_weak_decls ();
for (pf = cgraph_nodes; pf; pf = pf->next)
{
@@ -2068,6 +2069,7 @@ cgraph_optimize (void)
cgraph_expand_all_functions ();
varpool_remove_unreferenced_decls ();
+ varpool_remove_duplicate_weak_decls ();
varpool_assemble_pending_decls ();
}
diff --git a/gcc/coverage.c b/gcc/coverage.c
index 4fa49486fd8..f0b360450d1 100644
--- a/gcc/coverage.c
+++ b/gcc/coverage.c
@@ -62,6 +62,7 @@ struct function_list
unsigned ident; /* function ident */
unsigned checksum; /* function checksum */
unsigned n_ctrs[GCOV_COUNTERS];/* number of counters. */
+ unsigned dc_offset; /* offset of counters to direct calls. */
};
/* Linked list of -D/-U/-imacro/-include strings for a source module. */
@@ -982,6 +983,7 @@ coverage_dc_end_function (void)
}
item->n_ctrs[idx] += fn_n_ctrs[idx];
+ item->dc_offset = prg_n_ctrs[idx];
prg_n_ctrs[idx] += fn_n_ctrs[idx];
fn_n_ctrs[idx] = fn_b_ctrs[idx] = 0;
prg_ctr_mask |= fn_ctr_mask;
@@ -1009,6 +1011,12 @@ build_fn_info_type (unsigned int counters)
TREE_CHAIN (field) = fields;
fields = field;
+ /* dc offset */
+ field = build_decl (BUILTINS_LOCATION,
+ FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
+ TREE_CHAIN (field) = fields;
+ fields = field;
+
array_type = build_int_cst (NULL_TREE, counters - 1);
array_type = build_index_type (array_type);
array_type = build_array_type (get_gcov_unsigned_t (), array_type);
@@ -1046,6 +1054,11 @@ build_fn_info_value (const struct function_list *function, tree type)
function->checksum), value);
fields = TREE_CHAIN (fields);
+ /* dc offset */
+ value = tree_cons (fields, build_int_cstu (get_gcov_unsigned_t (),
+ function->dc_offset), value);
+ fields = TREE_CHAIN (fields);
+
/* counters */
for (ix = 0; ix != GCOV_COUNTERS; ix++)
if (prg_ctr_mask & (1 << ix))
@@ -1898,3 +1911,4 @@ coverage_has_asm_stmt (void)
}
#include "gt-coverage.h"
+
diff --git a/gcc/dyn-ipa.c b/gcc/dyn-ipa.c
index 99ceb43174c..b610fe26f78 100644
--- a/gcc/dyn-ipa.c
+++ b/gcc/dyn-ipa.c
@@ -489,9 +489,12 @@ gcov_build_callgraph (void)
caller = &the_dyn_call_graph.call_graph_nodes[m_ix][fi_ptr->ident];
if (dcall_profile_values)
{
+ unsigned offset;
n_counts = fi_ptr->n_ctrs[dp_cix];
- gcov_build_callgraph_dc_fn (caller, dcall_profile_values, n_counts);
- dcall_profile_values += n_counts;
+ offset = fi_ptr->dc_offset;
+ gcov_build_callgraph_dc_fn (caller,
+ dcall_profile_values + offset,
+ n_counts);
}
if (icall_profile_values)
{
diff --git a/gcc/gcov-io.h b/gcc/gcov-io.h
index a9932d5037c..90c74a3d897 100644
--- a/gcc/gcov-io.h
+++ b/gcc/gcov-io.h
@@ -499,6 +499,7 @@ struct gcov_fn_info
{
gcov_unsigned_t ident; /* unique ident of function */
gcov_unsigned_t checksum; /* function checksum */
+ gcov_unsigned_t dc_offset; /* direct call offset */
unsigned n_ctrs[0]; /* instrumented counters */
};
diff --git a/gcc/l-ipo.c b/gcc/l-ipo.c
index ff6fdbae6a1..acfba1379a7 100644
--- a/gcc/l-ipo.c
+++ b/gcc/l-ipo.c
@@ -1734,12 +1734,8 @@ promote_static_var_func (unsigned module_id, tree decl, bool is_extern)
/* Externalize global variables from aux modules and promote
static variables.
- WEAK variables need special treatment. If there is a definition in the
- primary module, all the definitions of this weak variable in auxiliary
- modules are externalized. Otherwise, all but one definition in the
- auxiliary modules is externalized. For this reason, before the first
- call to this function, we must have a record of all the weak variables
- emitted from the primary module. */
+ WEAK variables are treated especially in
+ varpool_remove_duplicate_weak_decls. */
static void
process_module_scope_static_var (struct varpool_node *vnode)
@@ -1751,11 +1747,8 @@ process_module_scope_static_var (struct varpool_node *vnode)
gcc_assert (vnode->module_id != primary_module_id);
if (TREE_PUBLIC (decl))
{
- /* Externalize non-weak variables, and those weak variables that
- we have seen one non-external copy of. */
- if (!DECL_WEAK (decl)
- || (!DECL_EXTERNAL (decl)
- && get_name_seq_num (IDENTIFIER_POINTER (DECL_NAME (decl)))))
+ /* Externalize non-weak variables. */
+ if (!DECL_WEAK (decl))
{
DECL_EXTERNAL (decl) = 1;
TREE_STATIC (decl) = 0;
@@ -1827,13 +1820,6 @@ cgraph_process_module_scope_statics (void)
promo_ent_eq, promo_ent_del);
/* Process variable first. */
- /* Keep track of weak variables emitted from the primary module (see
- comment for the process_module_scope_static_var function for why
- this needs to be done). We use the get_name_seq_name function for
- this. */
- for (pv = varpool_nodes_queue; pv; pv = pv->next_needed)
- if (!varpool_is_auxiliary (pv) && DECL_WEAK (pv->decl) && !DECL_EXTERNAL (pv->decl))
- get_name_seq_num (IDENTIFIER_POINTER (DECL_NAME (pv->decl)));
for (pv = varpool_nodes_queue; pv; pv = pv->next_needed)
process_module_scope_static_var (pv);
@@ -1843,6 +1829,48 @@ cgraph_process_module_scope_statics (void)
htab_delete (promo_ent_hash_tab);
}
+/* There could be duplicate non-extern WEAK decls in the varpool queue,
+ coming from different modules. All but one of these need to be externalized
+ and removed from the varpool queue.
+ Duplicate WEAK decls can be added to varpool queue as late as
+ cgraph_expand_function, when a WEAK decl is marked referenced as assembler
+ is being output. Therefore, a call to this function should be made after
+ cgraph_expand_function. */
+
+void
+varpool_remove_duplicate_weak_decls (void)
+{
+ struct varpool_node *next, *node = varpool_nodes_queue;
+
+ if (!L_IPO_COMP_MODE)
+ return;
+
+ varpool_reset_queue ();
+
+ promo_ent_hash_tab = htab_create (10, promo_ent_hash,
+ promo_ent_eq, promo_ent_del);
+
+ while (node)
+ {
+ tree decl = node->decl;
+ next = node->next_needed;
+ node->needed = 0;
+ if (TREE_PUBLIC (decl) && DECL_WEAK (decl) && !DECL_EXTERNAL (decl)
+ && get_name_seq_num (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))))
+ {
+ DECL_EXTERNAL (decl) = 1;
+ TREE_STATIC (decl) = 0;
+ DECL_INITIAL (decl) = NULL;
+ DECL_CONTEXT (decl) = NULL;
+ }
+ else
+ varpool_mark_needed_node (node);
+ node = next;
+ }
+
+ htab_delete (promo_ent_hash_tab);
+}
+
static GTY((param_is (struct varpool_node))) htab_t varpool_symtab;
/* Hash function for varpool node. */
diff --git a/gcc/varpool.c b/gcc/varpool.c
index bbcdff01d61..72331271b50 100644
--- a/gcc/varpool.c
+++ b/gcc/varpool.c
@@ -219,7 +219,7 @@ varpool_mark_needed_node (struct varpool_node *node)
}
/* Reset the queue of needed nodes. */
-static void
+void
varpool_reset_queue (void)
{
varpool_last_needed_node = NULL;