diff options
author | Raksit Ashok <raksit@google.com> | 2010-06-15 15:37:57 +0000 |
---|---|---|
committer | Raksit Ashok <raksit@google.com> | 2010-06-15 15:37:57 +0000 |
commit | 04b3a5f9eaa8d9105e58f86bc16245ea5faaa776 (patch) | |
tree | 62670a7aa99c4757391da4cfecb12d974064f395 | |
parent | 51c965e4d3e73175a3bbf957382507f93e9a4aaf (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.h | 2 | ||||
-rw-r--r-- | gcc/cgraphunit.c | 2 | ||||
-rw-r--r-- | gcc/coverage.c | 14 | ||||
-rw-r--r-- | gcc/dyn-ipa.c | 7 | ||||
-rw-r--r-- | gcc/gcov-io.h | 1 | ||||
-rw-r--r-- | gcc/l-ipo.c | 64 | ||||
-rw-r--r-- | gcc/varpool.c | 2 |
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; |