Re: Fix build with inhibit_libc (was Re: [PATCH 2/4] Implement N disk counters for single value and indirect call counters.)
On 6/10/19 11:53 PM, Jakub Jelinek wrote: > On Mon, Jun 10, 2019 at 08:02:26PM +0200, Jakub Jelinek wrote: >> This change broke build without target libc. >> >> ../../../../libgcc/libgcov-merge.c:37:6: error: conflicting types for >> ‘__gcov_merge_single’ >>37 | void __gcov_merge_single (gcov_type *counters __attribute__ >> ((unused))) >> | ^~~ >> In file included from ../../../../libgcc/libgcov-merge.c:26: >> ../../../../libgcc/libgcov.h:263:13: note: previous declaration of >> ‘__gcov_merge_single’ was here >> 263 | extern void __gcov_merge_single (gcov_type *, unsigned) >> ATTRIBUTE_HIDDEN; >> | ^~~ >> >> It is unclear why it has been changed, when the callers haven't been >> adjusted, nor the prototype. >> >> So, I'd like to revert this hunk. Tested with x86_64-linux -> nvptx-none >> cross build, ok for trunk? > > Additionally successfully bootstrapped/regtested on x86_64-linux. Thank you for the patch. It's correct, I really accidentally changed the signature. Martin > >> 2019-06-10 Jakub Jelinek >> >> * libgcov-merge.c (__gcov_merge_single): Revert previous change. >> >> --- libgcc/libgcov-merge.c.jj2019-06-10 19:39:29.291363550 +0200 >> +++ libgcc/libgcov-merge.c 2019-06-10 19:58:36.731524778 +0200 >> @@ -34,9 +34,8 @@ void __gcov_merge_add (gcov_type *counte >> #endif >> >> #ifdef L_gcov_merge_single >> -void __gcov_merge_single (gcov_type *counters __attribute__ ((unused))) >> -{ >> -} >> +void __gcov_merge_single (gcov_type *counters __attribute__ ((unused)), >> + unsigned n_counters __attribute__ ((unused))) {} >> #endif >> >> #else > > Jakub >
Re: Fix build with inhibit_libc (was Re: [PATCH 2/4] Implement N disk counters for single value and indirect call counters.)
On Mon, Jun 10, 2019 at 08:02:26PM +0200, Jakub Jelinek wrote: > This change broke build without target libc. > > ../../../../libgcc/libgcov-merge.c:37:6: error: conflicting types for > ‘__gcov_merge_single’ >37 | void __gcov_merge_single (gcov_type *counters __attribute__ > ((unused))) > | ^~~ > In file included from ../../../../libgcc/libgcov-merge.c:26: > ../../../../libgcc/libgcov.h:263:13: note: previous declaration of > ‘__gcov_merge_single’ was here > 263 | extern void __gcov_merge_single (gcov_type *, unsigned) > ATTRIBUTE_HIDDEN; > | ^~~ > > It is unclear why it has been changed, when the callers haven't been > adjusted, nor the prototype. > > So, I'd like to revert this hunk. Tested with x86_64-linux -> nvptx-none > cross build, ok for trunk? Additionally successfully bootstrapped/regtested on x86_64-linux. > 2019-06-10 Jakub Jelinek > > * libgcov-merge.c (__gcov_merge_single): Revert previous change. > > --- libgcc/libgcov-merge.c.jj 2019-06-10 19:39:29.291363550 +0200 > +++ libgcc/libgcov-merge.c2019-06-10 19:58:36.731524778 +0200 > @@ -34,9 +34,8 @@ void __gcov_merge_add (gcov_type *counte > #endif > > #ifdef L_gcov_merge_single > -void __gcov_merge_single (gcov_type *counters __attribute__ ((unused))) > -{ > -} > +void __gcov_merge_single (gcov_type *counters __attribute__ ((unused)), > + unsigned n_counters __attribute__ ((unused))) {} > #endif > > #else Jakub
Fix build with inhibit_libc (was Re: [PATCH 2/4] Implement N disk counters for single value and indirect call counters.)
On Fri, Jun 07, 2019 at 11:10:59AM +0200, Martin Liška wrote: > libgcc/ChangeLog: > > 2019-06-04 Martin Liska > > * Makefile.in: Add __gcov_one_value_profiler_v2, > __gcov_one_value_profiler_v2_atomic and > __gcov_indirect_call_profiler_v4. > * libgcov-merge.c (__gcov_merge_single): Change > function signature. > diff --git a/libgcc/libgcov-merge.c b/libgcc/libgcov-merge.c > index 702a69f8349..42416341b4d 100644 > --- a/libgcc/libgcov-merge.c > +++ b/libgcc/libgcov-merge.c > @@ -34,8 +34,9 @@ void __gcov_merge_add (gcov_type *counters __attribute__ > ((unused)), > #endif > > #ifdef L_gcov_merge_single > -void __gcov_merge_single (gcov_type *counters __attribute__ ((unused)), > - unsigned n_counters __attribute__ ((unused))) {} > +void __gcov_merge_single (gcov_type *counters __attribute__ ((unused))) > +{ > +} > #endif > > #else This change broke build without target libc. ../../../../libgcc/libgcov-merge.c:37:6: error: conflicting types for ‘__gcov_merge_single’ 37 | void __gcov_merge_single (gcov_type *counters __attribute__ ((unused))) | ^~~ In file included from ../../../../libgcc/libgcov-merge.c:26: ../../../../libgcc/libgcov.h:263:13: note: previous declaration of ‘__gcov_merge_single’ was here 263 | extern void __gcov_merge_single (gcov_type *, unsigned) ATTRIBUTE_HIDDEN; | ^~~ It is unclear why it has been changed, when the callers haven't been adjusted, nor the prototype. So, I'd like to revert this hunk. Tested with x86_64-linux -> nvptx-none cross build, ok for trunk? 2019-06-10 Jakub Jelinek * libgcov-merge.c (__gcov_merge_single): Revert previous change. --- libgcc/libgcov-merge.c.jj 2019-06-10 19:39:29.291363550 +0200 +++ libgcc/libgcov-merge.c 2019-06-10 19:58:36.731524778 +0200 @@ -34,9 +34,8 @@ void __gcov_merge_add (gcov_type *counte #endif #ifdef L_gcov_merge_single -void __gcov_merge_single (gcov_type *counters __attribute__ ((unused))) -{ -} +void __gcov_merge_single (gcov_type *counters __attribute__ ((unused)), + unsigned n_counters __attribute__ ((unused))) {} #endif #else Jakub
Re: [PATCH 2/4] Implement N disk counters for single value and indirect call counters.
On 6/7/19 3:58 PM, Jan Hubicka wrote: >> >> Because I removed hist->hvalue.counters[2] where we stored total number of >> executions. >> It's back again so that _atomic suffix version makes sense again. > > OK and we do not care about race conditions on the other two counters? We do care, but one can't probably implement that without a locking of the critical section: 117 static inline void 118 __gcov_one_value_profiler_body (gcov_type *counters, gcov_type value, 119 int use_atomic) 120 { 121if (value == counters[1]) 122 counters[2]++; 123else if (counters[2] == 0) 124 { 125counters[2] = 1; 126counters[1] = value; 127 } 128else 129 counters[2]--; Here you operate with 2 values which can change during a parallel execution. >> >> After we discussed that I decided to live with all counters in memory. >> Reason is that >> in write_one_data we would have to allocate temporary buffers and fill up >> them here: >> >>304tag = gcov_read_unsigned (); >>305length = gcov_read_unsigned (); >>306if (tag != GCOV_TAG_FOR_COUNTER (t_ix) >>307|| length != GCOV_TAG_COUNTER_LENGTH (ci_ptr->num)) >>308 goto read_mismatch; >>309(*merge) (ci_ptr->values, ci_ptr->num); >>310ci_ptr++; >> >> It would be quite nasty and I would like to mitigate libgcov profile crashes. > > Hmm, I see, if code was organized to directly write the output, it would > be easier. I guess it is not overly important. > > Patch is OK Thanks for the approval. Martin > Honza >
Re: [PATCH 2/4] Implement N disk counters for single value and indirect call counters.
> > Because I removed hist->hvalue.counters[2] where we stored total number of > executions. > It's back again so that _atomic suffix version makes sense again. OK and we do not care about race conditions on the other two counters? > > After we discussed that I decided to live with all counters in memory. Reason > is that > in write_one_data we would have to allocate temporary buffers and fill up > them here: > >304tag = gcov_read_unsigned (); >305length = gcov_read_unsigned (); >306if (tag != GCOV_TAG_FOR_COUNTER (t_ix) >307|| length != GCOV_TAG_COUNTER_LENGTH (ci_ptr->num)) >308 goto read_mismatch; >309(*merge) (ci_ptr->values, ci_ptr->num); >310ci_ptr++; > > It would be quite nasty and I would like to mitigate libgcov profile crashes. Hmm, I see, if code was organized to directly write the output, it would be easier. I guess it is not overly important. Patch is OK Honza
Re: [PATCH 2/4] Implement N disk counters for single value and indirect call counters.
; >> + for (unsigned i = 0; i < GCOV_DISK_SINGLE_VALUES; i++) >> +{ >> + fprintf (dump_file, "[%" PRId64 ":%" PRId64 "]", >> + (int64_t) hist->hvalue.counters[2 * i], >> + (int64_t) hist->hvalue.counters[2 * i + 1]); >> + if (i != GCOV_DISK_SINGLE_VALUES - 1) >> +fprintf (dump_file, ", "); >> +} > Unless there are some compelling reasons, I would still include in dump what > is > meaning of the values - not everyone is fluent in that ;) I improved that. >> @@ -758,23 +779,19 @@ gimple_divmod_fixed_value_transform >> (gimple_stmt_iterator *si) >>if (!histogram) >> return false; >> >> + if (!get_most_common_single_value (histogram, &val, &count)) >> +return false; >> + >>value = histogram->hvalue.value; >> - val = histogram->hvalue.counters[0]; >> - count = histogram->hvalue.counters[1]; >> - all = histogram->hvalue.counters[2]; >> + all = gimple_bb (stmt)->count.ipa ().to_gcov_type (); > > Here it is safe to use gimple_bb (stmt)->count.ipa ().to_gcov_type () under an > assumptions that profile is consistent - I am not sure how often one gets > mismatches with -fprofile-correction at multithreaded programs, maybe it would > be worth to check before we drop the code logging it to dumps. > > In ipa-profile it is not quite the case since we do CFG optimization and other > transforms between profile instrumentaiton and IPA passes. I would remember > probability within stmt histogram (like we do for speculative edges) that is > safe WRT BB profile updates. I put back the total number of executions, now sitting at hist->hvalue.counters[0]. > > So in your implementation we store 4 times as many vlaue counters in memory > during runtime? Originally I had in mind a variant where in memory everything > works as before, but in on-disk format one save the section for indirect > call counters multiple times implementing the update logic. > This should not be that hard do something: > > for secno = 1...4 >for every counter > read counter2 from disk > if (counter has non-zero exec count) >if counter2 is invalid >clear counter >else if counter and counter2 values match > increase counter2 hitrate >clear counter >else if counter2 has zero count >rewrite counter2 by counter >clear counter >else if secno==5 >mark counter2 as invalid >clear ocunter > write counter2 to disk > > So you do not really need to keep duplicates in memory at runtime. > You will still be able to tell if there was too many counters by checking > the last copy (instead of first as you do in your implementation) After we discussed that I decided to live with all counters in memory. Reason is that in write_one_data we would have to allocate temporary buffers and fill up them here: 304tag = gcov_read_unsigned (); 305length = gcov_read_unsigned (); 306if (tag != GCOV_TAG_FOR_COUNTER (t_ix) 307|| length != GCOV_TAG_COUNTER_LENGTH (ci_ptr->num)) 308 goto read_mismatch; 309 (*merge) (ci_ptr->values, ci_ptr->num); 310ci_ptr++; It would be quite nasty and I would like to mitigate libgcov profile crashes. >> + value = gcov_get_counter_target (); >> + counter = gcov_get_counter (); >> + >> + if (counter == -1) >> +{ >> + counters[1] = -1; >> + /* We can't return as we need to read all counters. */ >> + continue; >> +} >> + else if (counter == 0 || counters[1] == -1) >> +{ >> + /* We can't return as we need to read all counters. */ >> + continue; >> +} > gcov_get_counter scales by gcov_get_merge_weight and thus it will > not reliably read -1 when you store -1 Ah, you are right. I've fixed that. I'm sending next version of the patch which I've been testing. Martin > > Honza > >From 241d4042c542fb64f38ccb602631d5e7bd689684 Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Thu, 6 Jun 2019 10:17:13 +0200 Subject: [PATCH 2/4] Implement N disk counters for single value and indirect call counters. gcc/ChangeLog: 2019-06-04 Martin Liska * gcov-io.h (GCOV_DISK_SINGLE_VALUES): New. (GCOV_SINGLE_VALUE_COUNTERS): Likewise. * ipa-profile.c (ipa_profile_generate_summary): Use get_most_common_single_value. * tree-profile.c (gimple_init_gcov_profiler): Instrument with __gcov_one_value_profiler_v2 and __gcov_indirect
Re: [PATCH 2/4] Implement N disk counters for single value and indirect call counters.
> > gcc/ChangeLog: > > 2019-06-04 Martin Liska > > * gcov-io.h (GCOV_DISK_SINGLE_VALUES): New. > (GCOV_SINGLE_VALUE_COUNTERS): Likewise. > * ipa-profile.c (ipa_profile_generate_summary): > Use get_most_common_single_value. > * tree-profile.c (gimple_init_gcov_profiler): > Instrument with __gcov_one_value_profiler_v2 > and __gcov_indirect_call_profiler_v4. > * value-prof.c (dump_histogram_value): > Print all values for HIST_TYPE_SINGLE_VALUE. > (stream_in_histogram_value): Set number of > counters for HIST_TYPE_SINGLE_VALUE. > (get_most_common_single_value): New. > (gimple_divmod_fixed_value_transform): > Use get_most_common_single_value. > (gimple_ic_transform): Likewise. > (gimple_stringops_transform): Likewise. > (gimple_find_values_to_profile): Set number > of counters for HIST_TYPE_SINGLE_VALUE. > * value-prof.h (get_most_common_single_value): > New. > > libgcc/ChangeLog: > > 2019-06-04 Martin Liska > > * Makefile.in: Add __gcov_one_value_profiler_v2 and > __gcov_indirect_call_profiler_v4. > * libgcov-merge.c (__gcov_merge_single): Change > function signature. > (merge_single_value_set): New. > * libgcov-profiler.c (__gcov_one_value_profiler_body): > Do not update counters[2]. > (__gcov_one_value_profiler): Remove. > (__gcov_one_value_profiler_atomic): Rename to ... > (__gcov_one_value_profiler_v2): ... this. > (__gcov_indirect_call_profiler_v3): Rename to ... > (__gcov_indirect_call_profiler_v4): ... this. > * libgcov.h (__gcov_one_value_profiler): Remove. > (__gcov_one_value_profiler_atomic): Remove. > (__gcov_indirect_call_profiler_v3): Remove. > (__gcov_one_value_profiler_v2): New. > (__gcov_indirect_call_profiler_v4): New. > --- > gcc/gcov-io.h | 7 +++ > gcc/ipa-profile.c | 13 +++-- > gcc/tree-profile.c| 9 ++- > gcc/value-prof.c | 120 -- > gcc/value-prof.h | 2 + > libgcc/Makefile.in| 5 +- > libgcc/libgcov-merge.c| 77 > libgcc/libgcov-profiler.c | 43 +++--- > libgcc/libgcov.h | 5 +- > 9 files changed, 147 insertions(+), 134 deletions(-) > > diff --git a/gcc/tree-profile.c b/gcc/tree-profile.c > index f2cf4047579..008a1271979 100644 > --- a/gcc/tree-profile.c > +++ b/gcc/tree-profile.c > @@ -165,10 +165,9 @@ gimple_init_gcov_profiler (void) > = build_function_type_list (void_type_node, > gcov_type_ptr, gcov_type_node, > NULL_TREE); > - fn_name = concat ("__gcov_one_value_profiler", fn_suffix, NULL); > - tree_one_value_profiler_fn = build_fn_decl (fn_name, > - one_value_profiler_fn_type); > - free (CONST_CAST (char *, fn_name)); > + tree_one_value_profiler_fn > + = build_fn_decl ("__gcov_one_value_profiler_v2", > + one_value_profiler_fn_type); Why you no longer need the optional atomic suffix here? > diff --git a/gcc/value-prof.c b/gcc/value-prof.c > index 1e14e532070..e893ca084c9 100644 > --- a/gcc/value-prof.c > +++ b/gcc/value-prof.c > @@ -259,15 +259,19 @@ dump_histogram_value (FILE *dump_file, histogram_value > hist) >break; > > case HIST_TYPE_SINGLE_VALUE: > - fprintf (dump_file, "Single value "); > +case HIST_TYPE_INDIR_CALL: > + fprintf (dump_file, (hist->type == HIST_TYPE_SINGLE_VALUE > +? "Single values " : "Indirect call ")); >if (hist->hvalue.counters) > { > -fprintf (dump_file, "value:%" PRId64 > - " match:%" PRId64 > - " wrong:%" PRId64, > - (int64_t) hist->hvalue.counters[0], > - (int64_t) hist->hvalue.counters[1], > - (int64_t) hist->hvalue.counters[2]); > + for (unsigned i = 0; i < GCOV_DISK_SINGLE_VALUES; i++) > + { > + fprintf (dump_file, "[%" PRId64 ":%" PRId64 "]", > +(int64_t) hist->hvalue.counters[2 * i], > +(int64_t) hist->hvalue.counters[2 * i + 1]); > + if (i != GCOV_DISK_SINGLE_VALUES - 1) > + fprintf (dump_file, ", "); > + } Unless there are some compelling reasons, I would still include in dump what is meaning of the values - not everyone is fluent in that ;) > @@ -758,23 +779,19 @@ gimple_divmod_fixed_value_transform > (gimple_stmt_iterator *si) >if (!histogram) > return false; > > + if (!get_most_common_single_value (histogram, &val, &count)) > +return false; > + >value = histogram->hvalue.value; > - val = histogram->hvalue.counters[0]; > - count = histogram->hvalue.counters[1]; > - all = histogram->hvalue.counters[2]; > + all = gim
[PATCH 2/4] Implement N disk counters for single value and indirect call counters.
gcc/ChangeLog: 2019-06-04 Martin Liska * gcov-io.h (GCOV_DISK_SINGLE_VALUES): New. (GCOV_SINGLE_VALUE_COUNTERS): Likewise. * ipa-profile.c (ipa_profile_generate_summary): Use get_most_common_single_value. * tree-profile.c (gimple_init_gcov_profiler): Instrument with __gcov_one_value_profiler_v2 and __gcov_indirect_call_profiler_v4. * value-prof.c (dump_histogram_value): Print all values for HIST_TYPE_SINGLE_VALUE. (stream_in_histogram_value): Set number of counters for HIST_TYPE_SINGLE_VALUE. (get_most_common_single_value): New. (gimple_divmod_fixed_value_transform): Use get_most_common_single_value. (gimple_ic_transform): Likewise. (gimple_stringops_transform): Likewise. (gimple_find_values_to_profile): Set number of counters for HIST_TYPE_SINGLE_VALUE. * value-prof.h (get_most_common_single_value): New. libgcc/ChangeLog: 2019-06-04 Martin Liska * Makefile.in: Add __gcov_one_value_profiler_v2 and __gcov_indirect_call_profiler_v4. * libgcov-merge.c (__gcov_merge_single): Change function signature. (merge_single_value_set): New. * libgcov-profiler.c (__gcov_one_value_profiler_body): Do not update counters[2]. (__gcov_one_value_profiler): Remove. (__gcov_one_value_profiler_atomic): Rename to ... (__gcov_one_value_profiler_v2): ... this. (__gcov_indirect_call_profiler_v3): Rename to ... (__gcov_indirect_call_profiler_v4): ... this. * libgcov.h (__gcov_one_value_profiler): Remove. (__gcov_one_value_profiler_atomic): Remove. (__gcov_indirect_call_profiler_v3): Remove. (__gcov_one_value_profiler_v2): New. (__gcov_indirect_call_profiler_v4): New. --- gcc/gcov-io.h | 7 +++ gcc/ipa-profile.c | 13 +++-- gcc/tree-profile.c| 9 ++- gcc/value-prof.c | 120 -- gcc/value-prof.h | 2 + libgcc/Makefile.in| 5 +- libgcc/libgcov-merge.c| 77 libgcc/libgcov-profiler.c | 43 +++--- libgcc/libgcov.h | 5 +- 9 files changed, 147 insertions(+), 134 deletions(-) diff --git a/gcc/gcov-io.h b/gcc/gcov-io.h index 69c9a73dba8..161518176a0 100644 --- a/gcc/gcov-io.h +++ b/gcc/gcov-io.h @@ -266,6 +266,13 @@ GCOV_COUNTERS #define GCOV_N_VALUE_COUNTERS \ (GCOV_LAST_VALUE_COUNTER - GCOV_FIRST_VALUE_COUNTER + 1) +/* Number of single value histogram values that live + on disk representation. */ +#define GCOV_DISK_SINGLE_VALUES 4 + +/* Total number of single value counters. */ +#define GCOV_SINGLE_VALUE_COUNTERS (2 * GCOV_DISK_SINGLE_VALUES) + /* Convert a counter index to a tag. */ #define GCOV_TAG_FOR_COUNTER(COUNT)\ (GCOV_TAG_COUNTER_BASE + ((gcov_unsigned_t)(COUNT) << 17)) diff --git a/gcc/ipa-profile.c b/gcc/ipa-profile.c index de9563d808c..fc2ffbd84f7 100644 --- a/gcc/ipa-profile.c +++ b/gcc/ipa-profile.c @@ -191,17 +191,18 @@ ipa_profile_generate_summary (void) takes away bad histograms. */ if (h) { - /* counter 0 is target, counter 1 is number of execution we called target, - counter 2 is total number of executions. */ - if (h->hvalue.counters[2]) + gcov_type val, count; + if (get_most_common_single_value (h, &val, &count)) { struct cgraph_edge * e = node->get_edge (stmt); if (e && !e->indirect_unknown_callee) continue; - e->indirect_info->common_target_id - = h->hvalue.counters [0]; + + gcov_type all + = gimple_bb (stmt)->count.ipa ().to_gcov_type (); + e->indirect_info->common_target_id = val; e->indirect_info->common_target_probability - = GCOV_COMPUTE_SCALE (h->hvalue.counters [1], h->hvalue.counters [2]); + = GCOV_COMPUTE_SCALE (count, all); if (e->indirect_info->common_target_probability > REG_BR_PROB_BASE) { if (dump_file) diff --git a/gcc/tree-profile.c b/gcc/tree-profile.c index f2cf4047579..008a1271979 100644 --- a/gcc/tree-profile.c +++ b/gcc/tree-profile.c @@ -165,10 +165,9 @@ gimple_init_gcov_profiler (void) = build_function_type_list (void_type_node, gcov_type_ptr, gcov_type_node, NULL_TREE); - fn_name = concat ("__gcov_one_value_profiler", fn_suffix, NULL); - tree_one_value_profiler_fn = build_fn_decl (fn_name, - one_value_profiler_fn_type); - free (CONST_CAST (char *, fn_name)); + tree_one_value_profiler_fn + = build_fn_decl ("__gcov_one_value_profiler_v2", + one_value_profiler_fn_type); TREE_NOTHROW (tree_one_value_profiler_fn) = 1; DECL_ATTRIBUTES (tree_one_value_profiler_fn) = tree_cons (get_identifier ("leaf"), NULL, @@ -182,7 +181,7 @@ gimple_init_gcov_profiler (void) gcov_type_node, ptr_type_node, NULL_TREE);