Hi, while debugging quite werid libgcov issue I noticed that we skip profiling DECL_EXTERNAL functions. THis is not quite correct: if the function gets inlined during the train run, the counters are used and ought to be streamed. With LTO the profile will get merged with the offline copy from other unit, without LTO we can be pretty sure the function will be inlined in -fprofile-use run, too (if it matters) and thus ought to be instrumented as well or we hit problems with empty profile.
I also revisited coverage_compute_profile_id to be non-zero, since function IDs was nonzero before and made it prettier with unique name symbols. Bootstrapped/regtested x86_64-linux, comitted. * coverage.c (coverage_compute_profile_id): Return non-0; also handle symbols with unique name. (coverage_end_function): Do not skip DECL_EXTERNAL functions. Index: coverage.c =================================================================== --- coverage.c (revision 214223) +++ coverage.c (working copy) @@ -579,7 +579,7 @@ coverage_compute_profile_id (struct cgra unsigned chksum; /* Externally visible symbols have unique name. */ - if (TREE_PUBLIC (n->decl) || DECL_EXTERNAL (n->decl)) + if (TREE_PUBLIC (n->decl) || DECL_EXTERNAL (n->decl) || n->unique_name) { chksum = coverage_checksum_string (0, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (n->decl))); @@ -601,8 +601,10 @@ coverage_compute_profile_id (struct cgra (chksum, aux_base_name); } - /* Non-negative integers are hopefully small enough to fit in all targets. */ - return chksum & 0x7fffffff; + /* Non-negative integers are hopefully small enough to fit in all targets. + Gcov file formats wants non-zero function IDs. */ + chksum = chksum & 0x7fffffff; + return chksum + (!chksum); } /* Compute cfg checksum for the function FN given as argument. @@ -692,30 +694,24 @@ coverage_end_function (unsigned lineno_c { struct coverage_data *item = 0; - /* If the function is extern (i.e. extern inline), then we won't - be outputting it, so don't chain it onto the function - list. */ - if (!DECL_EXTERNAL (current_function_decl)) - { - item = ggc_alloc<coverage_data> (); + item = ggc_alloc<coverage_data> (); - if (PARAM_VALUE (PARAM_PROFILE_FUNC_INTERNAL_ID)) - item->ident = current_function_funcdef_no + 1; - else - { - gcc_assert (coverage_node_map_initialized_p ()); - item->ident = cgraph_node::get (cfun->decl)->profile_id; - } - - item->lineno_checksum = lineno_checksum; - item->cfg_checksum = cfg_checksum; - - item->fn_decl = current_function_decl; - item->next = 0; - *functions_tail = item; - functions_tail = &item->next; + if (PARAM_VALUE (PARAM_PROFILE_FUNC_INTERNAL_ID)) + item->ident = current_function_funcdef_no + 1; + else + { + gcc_assert (coverage_node_map_initialized_p ()); + item->ident = cgraph_node::get (cfun->decl)->profile_id; } + item->lineno_checksum = lineno_checksum; + item->cfg_checksum = cfg_checksum; + + item->fn_decl = current_function_decl; + item->next = 0; + *functions_tail = item; + functions_tail = &item->next; + for (i = 0; i != GCOV_COUNTERS; i++) { tree var = fn_v_ctrs[i];