Hi, The attached patch uses a callback function to unify the integer and floating-point scaling in gcov-tool. (Also fix a bug in fp scaling of ic and dc counters in earlier code).
Tested with spec2006 profiles. OK for checking in? Thanks, -Rong
2014-02-04 Rong Xu <x...@google.com> * gcc/gcov-tool.c (profile_rewrite2): Remove. (profile_rewrite): Merge int and fp scaling. (do_rewrite): Ditto. * libgcc/libgcov-util.c (typedef gcov_type) New. (__gcov_add_counter_op): Merge int and fp scaling. (__gcov_ior_counter_op): Ditto. (__gcov_delta_counter_op): Ditto. (__gcov_single_counter_op): Ditto. (__gcov_icall_topn_op): Ditto. (__gcov_dc_op): Ditto. (fp_scale): Ditto. (int_scale): Ditto. (gcov_profile_scale): Ditto. (gcov_profile_normalize): Ditto. (__gcov_scale2_add): Remove. (__gcov_scale2_ior): Remove. (__gcov_scale2_delta): Remove. (__gcov_scale2_single): Remove. (__gcov_scale2_icall_topn): Remove. (__gcov_scale2_dc): Remove. (gcov_profile_scale2): Remove. Index: gcc/gcov-tool.c =================================================================== --- gcc/gcov-tool.c (revision 207488) +++ gcc/gcov-tool.c (working copy) @@ -43,8 +43,7 @@ see the files COPYING3 and COPYING.RUNTIME respect extern int gcov_profile_merge (struct gcov_info*, struct gcov_info*, int, int); extern int gcov_profile_normalize (struct gcov_info*, gcov_type); -extern int gcov_profile_scale (struct gcov_info*, float); -extern int gcov_profile_scale2 (struct gcov_info*, int, int); +extern int gcov_profile_scale (struct gcov_info*, float, int, int); extern struct gcov_info* gcov_read_profile_dir (const char*, int); extern void gcov_exit (void); extern void set_gcov_list (struct gcov_info *); @@ -227,45 +226,13 @@ do_merge (int argc, char **argv) return ret; } -/* Scale the counters in profile DIR by a factor of N/D. - Result is written to dir OUT. Return 0 on success. */ - -static int -profile_rewrite2 (const char *dir, const char *out, int n, int d) -{ - char *pwd; - int ret; - struct gcov_info * profile; - - - profile = gcov_read_profile_dir (dir, 0); - if (!profile) - return 1; - - /* Output new profile. */ - unlink_profile_dir (out); - mkdir (out, 0755); - pwd = getcwd (NULL, 0); - gcc_assert (pwd); - ret = chdir (out); - gcc_assert (ret == 0); - - gcov_profile_scale2 (profile, n, d); - - set_gcov_list (profile); - gcov_exit (); - - ret = chdir (pwd); - free (pwd); - return 0; -} - /* If N_VAL is no-zero, normalize the profile by setting the largest counter counter value to N_VAL and scale others counters proportionally. Otherwise, multiply the all counters by SCALE. */ static int -profile_rewrite (const char *d1, const char *out, long long n_val, float scale) +profile_rewrite (const char *d1, const char *out, long long n_val, + float scale, int n, int d) { char *pwd; int ret; @@ -287,7 +254,7 @@ static int if (n_val) gcov_profile_normalize (d1_profile, (gcov_type) n_val); else - gcov_profile_scale (d1_profile, scale); + gcov_profile_scale (d1_profile, scale, n, d); set_gcov_list (d1_profile); gcov_exit (); @@ -604,9 +571,9 @@ do_rewrite (int argc, char **argv) if (argc - optind == 1) { if (denominator > 0) - ret = profile_rewrite2 (argv[optind], output_dir, numerator, denominator); + ret = profile_rewrite (argv[optind], output_dir, 0, 0.0, numerator, denominator); else - ret = profile_rewrite (argv[optind], output_dir, normalize_val, scale); + ret = profile_rewrite (argv[optind], output_dir, normalize_val, scale, 0, 0); } else rewrite_usage (); Index: libgcc/libgcov-util.c =================================================================== --- libgcc/libgcov-util.c (revision 207488) +++ libgcc/libgcov-util.c (working copy) @@ -873,39 +873,38 @@ gcov_profile_merge (struct gcov_info *tgt_profile, return 0; } -/* This part of code is to scale profile counters. */ +typedef gcov_type (*counter_op_fn) (gcov_type, void*, void*); -/* Type of function used to normalize counters. */ -typedef void (*gcov_scale_fn) (gcov_type *, gcov_unsigned_t, double); +/* Performing FN upon arc counters. */ -/* Scale arc counters. N_COUNTERS of counter value in COUNTERS array are - multiplied by a factor F. */ - static void -__gcov_scale_add (gcov_type *counters, unsigned n_counters, double f) +__gcov_add_counter_op (gcov_type *counters, unsigned n_counters, + counter_op_fn fn, void *data1, void *data2) { for (; n_counters; counters++, n_counters--) { gcov_type val = *counters; - *counters = val * f; + *counters = fn(val, data1, data2); } } -/* Scale ior counters. */ +/* Performing FN upon ior counters. */ static void -__gcov_scale_ior (gcov_type *counters ATTRIBUTE_UNUSED, - unsigned n_counters ATTRIBUTE_UNUSED, - double f ATTRIBUTE_UNUSED) +__gcov_ior_counter_op (gcov_type *counters ATTRIBUTE_UNUSED, + unsigned n_counters ATTRIBUTE_UNUSED, + counter_op_fn fn ATTRIBUTE_UNUSED, + void *data1 ATTRIBUTE_UNUSED, + void *data2 ATTRIBUTE_UNUSED) { /* Do nothing. */ } -/* Scale delta counters. Multiplied the counters in COUNTERS array - by a factor of F. */ +/* Performaing FN upon delta counters. */ static void -__gcov_scale_delta (gcov_type *counters, unsigned n_counters, double f) +__gcov_delta_counter_op (gcov_type *counters, unsigned n_counters, + counter_op_fn fn, void *data1, void *data2) { unsigned i, n_measures; @@ -913,16 +912,16 @@ static void n_measures = n_counters / 4; for (i = 0; i < n_measures; i++, counters += 4) { - counters[2] *= f; - counters[3] *= f; + counters[2] = fn (counters[2], data1, data2); + counters[3] = fn (counters[3], data1, data2); } } -/* Scale single counters. Multiplied the counters in COUNTERS array - by a factor of F. */ +/* Performing FN upon single counters. */ static void -__gcov_scale_single (gcov_type *counters, unsigned n_counters, double f) +__gcov_single_counter_op (gcov_type *counters, unsigned n_counters, + counter_op_fn fn, void *data1, void *data2) { unsigned i, n_measures; @@ -930,16 +929,16 @@ static void n_measures = n_counters / 3; for (i = 0; i < n_measures; i++, counters += 3) { - counters[1] *= f; - counters[2] *= f; + counters[1] = fn (counters[1], data1, data2); + counters[2] = fn (counters[2], data1, data2); } } -/* Scale indirect-call profile counters. Multiplied the counters in COUNTERS - array by a factor of F. */ +/* Performing FN upon indirect-call profile counters. */ static void -__gcov_scale_icall_topn (gcov_type *counters, unsigned n_counters, double f) +__gcov_icall_topn_op (gcov_type *counters, unsigned n_counters, + counter_op_fn fn, void *data1, void *data2) { unsigned i; @@ -950,41 +949,65 @@ static void gcov_type *value_array = &counters[i + 1]; for (j = 0; j < GCOV_ICALL_TOPN_NCOUNTS - 1; j += 2) - value_array[1] *= f; + value_array[j + 1] = fn (value_array[j + 1], data1, data2); } } -/* Scale direct-call profile counters. Multiplied the counters in COUNTERS - by a factor of F. */ +/* Performing FN upon direct-call profile counters. */ static void -__gcov_scale_dc (gcov_type *counters, unsigned n_counters, double f) +__gcov_dc_op (gcov_type *counters, unsigned n_counters, + counter_op_fn fn, void *data1, void *data2) { unsigned i; gcc_assert (!(n_counters % 2)); for (i = 0; i < n_counters; i += 2) - counters[1] *= f; + counters[i + 1] = fn (counters[i + 1], data1, data2); } -/* Scaling functions for counters. */ -static gcov_scale_fn ctr_scale_functions[GCOV_COUNTERS] = { - __gcov_scale_add, - __gcov_scale_add, - __gcov_scale_add, - __gcov_scale_single, - __gcov_scale_delta, - __gcov_scale_single, - __gcov_scale_add, - __gcov_scale_ior, - __gcov_scale_icall_topn, - __gcov_scale_dc, + +/* Scaling the counter value V by multiplying *(float*) DATA1. */ + +static gcov_type +fp_scale (gcov_type v, void *data1, void *data2 ATTRIBUTE_UNUSED) +{ + float f = *(float *) data1; + return (gcov_type) (v * f); +} + +/* Scaling the counter value V by multiplying DATA2/DATA1. */ + +static gcov_type +int_scale (gcov_type v, void *data1, void *data2) +{ + int n = *(int *) data1; + int d = *(int *) data2; + return (gcov_type) ((v / d) * n); +} + +/* Type of function used to process counters. */ +typedef void (*gcov_counter_fn) (gcov_type *, gcov_unsigned_t, + counter_op_fn, void *, void *); + +/* Function array to process profile counters. */ +static gcov_counter_fn ctr_functions[GCOV_COUNTERS] = { + __gcov_add_counter_op, + __gcov_add_counter_op, + __gcov_add_counter_op, + __gcov_single_counter_op, + __gcov_delta_counter_op, + __gcov_single_counter_op, + __gcov_add_counter_op, + __gcov_ior_counter_op, + __gcov_icall_topn_op, + __gcov_dc_op, }; /* Driver for scaling profile counters. */ int -gcov_profile_scale (struct gcov_info *profile, float scale_factor) +gcov_profile_scale (struct gcov_info *profile, float scale_factor, int n, int d) { struct gcov_info *gi_ptr; unsigned f_ix; @@ -1010,7 +1033,12 @@ int if (!merge) continue; - (*ctr_scale_functions[t_ix]) (ci_ptr->values, ci_ptr->num, scale_factor); + if (d == 0) + (*ctr_functions[t_ix]) (ci_ptr->values, ci_ptr->num, + fp_scale, &scale_factor, NULL); + else + (*ctr_functions[t_ix]) (ci_ptr->values, ci_ptr->num, + int_scale, &n, &d); ci_ptr++; } } @@ -1054,149 +1082,5 @@ gcov_profile_normalize (struct gcov_info *profile, if (verbose) fprintf (stdout, "max_val is %lld\n", (long long) curr_max_val); - return gcov_profile_scale (profile, scale_factor); + return gcov_profile_scale (profile, scale_factor, 0, 0); } - -/* Type of function used to normalize counters. */ -typedef void (*gcov_scale2_fn) (gcov_type *, gcov_unsigned_t, int, int); - -/* Scale2 arc counters. */ - -static void -__gcov_scale2_add (gcov_type *counters, unsigned n_counters, int n, int d) -{ - for (; n_counters; counters++, n_counters--) - { - gcov_type val = *counters; - *counters = (val / d) * n; - } -} - -/* Scale2 ior counters. */ - -static void -__gcov_scale2_ior (gcov_type *counters ATTRIBUTE_UNUSED, - unsigned n_counters ATTRIBUTE_UNUSED, - int n ATTRIBUTE_UNUSED, - int d ATTRIBUTE_UNUSED) -{ - /* do nothing. */ -} - -/* Scale2 delta counters. */ - -static void -__gcov_scale2_delta (gcov_type *counters, unsigned n_counters, int n, int d) -{ - unsigned i, n_measures; - - gcc_assert (!(n_counters % 4)); - n_measures = n_counters / 4; - for (i = 0; i < n_measures; i++, counters += 4) - { - counters[2] = (counters[2] / d) * n; - counters[3] = (counters[3] / d) * n; - } -} - -/* Scale2 single counters. */ - -static void -__gcov_scale2_single (gcov_type *counters, unsigned n_counters, int n, int d) -{ - unsigned i, n_measures; - - gcc_assert (!(n_counters % 3)); - n_measures = n_counters / 3; - for (i = 0; i < n_measures; i++, counters += 3) - { - counters[1] = (counters[1] / d) * n; - counters[2] = (counters[2] / d) * n; - } -} - -/* Scale2 indirect-call profile counters. Multiplied the counters in COUNTERS - array by a factor of F. */ - -static void -__gcov_scale2_icall_topn (gcov_type *counters, unsigned n_counters, int n, int d) -{ - unsigned i; - - gcc_assert (!(n_counters % GCOV_ICALL_TOPN_NCOUNTS)); - for (i = 0; i < n_counters; i += GCOV_ICALL_TOPN_NCOUNTS) - { - unsigned j; - gcov_type *value_array = &counters[i+1]; - - for (j = 0; j < GCOV_ICALL_TOPN_NCOUNTS - 1; j += 2) - value_array[j+1] = (value_array[j+1] / d) * n; - } -} - -/* Scale2 direct-call profile counters. Multiplied the counters in COUNTERS - by a factor of F. */ - -static void -__gcov_scale2_dc (gcov_type *counters, unsigned n_counters, int n, int d) -{ - unsigned i; - - gcc_assert (!(n_counters % 2)); - for (i = 0; i < n_counters; i += 2) - counters[i+1] = (counters[i+1] / d) * n; -} - -/* Scale2 functions for counters. */ -static gcov_scale2_fn ctr_scale2_functions[GCOV_COUNTERS] = { - __gcov_scale2_add, - __gcov_scale2_add, - __gcov_scale2_add, - __gcov_scale2_single, - __gcov_scale2_delta, - __gcov_scale2_single, - __gcov_scale2_add, - __gcov_scale2_ior, - __gcov_scale2_icall_topn, - __gcov_scale2_dc, -}; - -/* Driver for scale2 profile counters. */ - -int -gcov_profile_scale2 (struct gcov_info *profile, int n, int d) -{ - struct gcov_info *gi_ptr; - unsigned f_ix; - - if (verbose) - fprintf (stdout, "scale_factor is %d/%d\n", n, d); - - gcc_assert (n >= 0 && d > 0); - - /* Scale the counters. */ - for (gi_ptr = profile; gi_ptr; gi_ptr = gi_ptr->next) - for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++) - { - unsigned t_ix; - const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix]; - const struct gcov_ctr_info *ci_ptr; - - if (!gfi_ptr || gfi_ptr->key != gi_ptr) - continue; - - ci_ptr = gfi_ptr->ctrs; - for (t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++) - { - gcov_merge_fn merge = gi_ptr->merge[t_ix]; - - if (!merge) - continue; - (*ctr_scale2_functions[t_ix]) (ci_ptr->values, ci_ptr->num, n, d); - ci_ptr++; - } - } - - return 0; -} -