Add overlap functionality to gcov-tool.

2014-10-08  Rong Xu  <xur@google.com>

	* gcc/gcov-tool.c (profile_overlap): New driver function
        to compute profile overlap. 
	(print_overlap_usage_message): New.
	(overlap_usage): New.
	(do_overlap): New.
	(print_usage): Add calls to overlap function.
	(main): Ditto.
	* libgcc/libgcov-util.c (read_gcda_file): Fix format.
	(find_match_gcov_info): Ditto.
	(calculate_2_entries): New.
	(compute_one_gcov): Ditto.
	(gcov_info_count_all_cold): Ditto.
	(gcov_info_count_all_zero): Ditto.
	(extract_file_basename): Ditto.
	(get_file_basename): Ditto.
	(set_flag): Ditto.
	(matched_gcov_info): Ditto.
	(calculate_overlap): Ditto.
	(gcov_profile_overlap): Ditto.
	* libgcc/libgcov-driver.c (compute_summary): Make
        it avavilable for external calls.
	* gcc/doc/gcov-tool.texi: Add documentation.

From-SVN: r216015
This commit is contained in:
Rong Xu 2014-10-08 21:51:41 +00:00 committed by Rong Xu
parent a41bb2c947
commit 9b84e7a836
6 changed files with 759 additions and 43 deletions

View File

@ -1,3 +1,14 @@
2014-10-08 Rong Xu <xur@google.com>
* gcov-tool.c (profile_overlap): New driver function
to compute profile overlap.
(print_overlap_usage_message): New.
(overlap_usage): New.
(do_overlap): New.
(print_usage): Add calls to overlap function.
(main): Ditto.
* doc/gcov-tool.texi: Add documentation.
2014-10-08 Steve Ellcey <sellcey@mips.com>
* config/mips/mti-linux.h (DRIVER_SELF_SPECS): Change

View File

@ -103,8 +103,7 @@ in these kind of counters.
@section Invoking @command{gcov-tool}
@smallexample
gcov-tool @r{[}@var{global-options}@r{]} SUB_COMMAND
@r{[}@var{sub_command-options}@r{]} @var{profile_dir}
gcov-tool @r{[}@var{global-options}@r{]} SUB_COMMAND @r{[}@var{sub_command-options}@r{]} @var{profile_dir}
@end smallexample
@command{gcov-tool} accepts the following options:
@ -123,6 +122,15 @@ gcov-tool rewrite [rewrite-options] @var{directory}
[@option{-o}|@option{--output} @var{directory}]
[@option{-s}|@option{--scale} @var{float_or_simple-frac_value}]
[@option{-n}|@option{--normalize} @var{long_long_value}]
gcov-tool overlap [overlap-options] @var{directory1} @var{directory2}
[@option{-v}|@option{--verbose}]
[@option{-h}|@option{--hotonly}]
[@option{-f}|@option{--function}]
[@option{-F}|@option{--fullname}]
[@option{-o}|@option{--object}]
[@option{-t}|@option{--hot_threshold}] @var{float}
@c man end
@c man begin SEEALSO
gpl(7), gfdl(7), fsf-funding(7), gcc(1), gcov(1) and the Info entry for
@ -182,8 +190,42 @@ or simple fraction value form, such 1, 2, 2/3, and 5/3.
@itemx --normalize <long_long_value>
Normalize the profile. The specified value is the max counter value
in the new profile.
@end table
@item overlap
Computer the overlap score between the two specified profile directories.
The overlap score is computed based on the arc profiles. It is defined as
the sum of min (p1_counter[i] / p1_sum_all, p2_counter[i] / p2_sum_all),
for all arc counter i, where p1_counter[i] and p2_counter[i] are two
matched counters and p1_sum_all and p2_sum_all are the sum of counter
values in profile 1 and profile 2, respectively.
@table @gcctabopt
@item -v
@itemx --verbose
Set the verbose mode.
@item -h
@itemx --hotonly
Only print info for hot objects/functions.
@item -f
@itemx --function
Print function level overlap score.
@item -F
@itemx --fullname
Print full gcda filename.
@item -o
@itemx --object
Print object level overlap score.
@item -t @var{float}
@itemx --hot_threshold <float>
Set the threshold for hot counter value.
@end table
@end table
@c man end

View File

@ -39,6 +39,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include <getopt.h>
extern int gcov_profile_merge (struct gcov_info*, struct gcov_info*, int, int);
extern int gcov_profile_overlap (struct gcov_info*, struct gcov_info*);
extern int gcov_profile_normalize (struct gcov_info*, gcov_type);
extern int gcov_profile_scale (struct gcov_info*, float, int, int);
extern struct gcov_info* gcov_read_profile_dir (const char*, int);
@ -368,6 +369,121 @@ do_rewrite (int argc, char **argv)
return ret;
}
/* Driver function to computer the overlap score b/w profile D1 and D2.
Return 1 on error and 0 if OK. */
static int
profile_overlap (const char *d1, const char *d2)
{
struct gcov_info *d1_profile;
struct gcov_info *d2_profile;
d1_profile = gcov_read_profile_dir (d1, 0);
if (!d1_profile)
return 1;
if (d2)
{
d2_profile = gcov_read_profile_dir (d2, 0);
if (!d2_profile)
return 1;
return gcov_profile_overlap (d1_profile, d2_profile);
}
return 1;
}
/* Usage message for profile overlap. */
static void
print_overlap_usage_message (int error_p)
{
FILE *file = error_p ? stderr : stdout;
fnotice (file, " overlap [options] <dir1> <dir2> Compute the overlap of two profiles\n");
fnotice (file, " -v, --verbose Verbose mode\n");
fnotice (file, " -h, --hotonly Only print info for hot objects/functions\n");
fnotice (file, " -f, --function Print function level info\n");
fnotice (file, " -F, --fullname Print full filename\n");
fnotice (file, " -o, --object Print object level info\n");
fnotice (file, " -t <float>, --hot_threshold <float> Set the threshold for hotness\n");
}
static const struct option overlap_options[] =
{
{ "verbose", no_argument, NULL, 'v' },
{ "function", no_argument, NULL, 'f' },
{ "fullname", no_argument, NULL, 'F' },
{ "object", no_argument, NULL, 'o' },
{ "hotonly", no_argument, NULL, 'h' },
{ "hot_threshold", required_argument, NULL, 't' },
{ 0, 0, 0, 0 }
};
/* Print overlap usage and exit. */
static void
overlap_usage (void)
{
fnotice (stderr, "Overlap subcomand usage:");
print_overlap_usage_message (true);
exit (FATAL_EXIT_CODE);
}
int overlap_func_level;
int overlap_obj_level;
int overlap_hot_only;
int overlap_use_fullname;
double overlap_hot_threshold = 0.005;
/* Driver for profile overlap sub-command. */
static int
do_overlap (int argc, char **argv)
{
int opt;
int ret;
optind = 0;
while ((opt = getopt_long (argc, argv, "vfFoht:", overlap_options, NULL)) != -1)
{
switch (opt)
{
case 'v':
verbose = true;
gcov_set_verbose ();
break;
case 'f':
overlap_func_level = 1;
break;
case 'F':
overlap_use_fullname = 1;
break;
case 'o':
overlap_obj_level = 1;
break;
case 'h':
overlap_hot_only = 1;
break;
case 't':
overlap_hot_threshold = atof (optarg);
break;
default:
overlap_usage ();
}
}
if (argc - optind == 2)
ret = profile_overlap (argv[optind], argv[optind+1]);
else
overlap_usage ();
return ret;
}
/* Print a usage message and exit. If ERROR_P is nonzero, this is an error,
otherwise the output of --help. */
@ -383,6 +499,7 @@ print_usage (int error_p)
fnotice (file, " -v, --version Print version number, then exit\n");
print_merge_usage_message (error_p);
print_rewrite_usage_message (error_p);
print_overlap_usage_message (error_p);
fnotice (file, "\nFor bug reporting instructions, please see:\n%s.\n",
bug_report_url);
exit (status);
@ -471,6 +588,8 @@ main (int argc, char **argv)
return do_merge (argc - optind, argv + optind);
else if (!strcmp (sub_command, "rewrite"))
return do_rewrite (argc - optind, argv + optind);
else if (!strcmp (sub_command, "overlap"))
return do_overlap (argc - optind, argv + optind);
print_usage (true);
}

View File

@ -1,3 +1,20 @@
2014-10-08 Rong Xu <xur@google.com>
* libgcov-util.c (read_gcda_file): Fix format.
(find_match_gcov_info): Ditto.
(calculate_2_entries): New.
(compute_one_gcov): Ditto.
(gcov_info_count_all_cold): Ditto.
(gcov_info_count_all_zero): Ditto.
(extract_file_basename): Ditto.
(get_file_basename): Ditto.
(set_flag): Ditto.
(matched_gcov_info): Ditto.
(calculate_overlap): Ditto.
(gcov_profile_overlap): Ditto.
* libgcov-driver.c (compute_summary): Make
it avavilable for external calls.
2014-10-06 Rong Xu <xur@google.com>
* Makefile.in: Ditto.

View File

@ -274,7 +274,10 @@ static struct gcov_summary_buffer *sum_buffer;
It computes and returns CRC32 and stored summary in THIS_PRG.
Also determines the longest filename length of the info files. */
static gcov_unsigned_t
#if !IN_GCOV_TOOL
static
#endif
gcov_unsigned_t
compute_summary (struct gcov_info *list, struct gcov_summary *this_prg,
size_t *max_length)
{

View File

@ -319,59 +319,59 @@ read_gcda_file (const char *filename)
tag = gcov_read_unsigned ();
if (!tag)
break;
break;
length = gcov_read_unsigned ();
base = gcov_position ();
mask = GCOV_TAG_MASK (tag) >> 1;
for (tag_depth = 4; mask; mask >>= 8)
{
if (((mask & 0xff) != 0xff))
{
warning (0, "%s:tag `%x' is invalid\n", filename, tag);
break;
}
tag_depth--;
}
{
if (((mask & 0xff) != 0xff))
{
warning (0, "%s:tag `%x' is invalid\n", filename, tag);
break;
}
tag_depth--;
}
for (format = tag_table; format->name; format++)
if (format->tag == tag)
goto found;
if (format->tag == tag)
goto found;
format = &tag_table[GCOV_TAG_IS_COUNTER (tag) ? 2 : 1];
found:;
if (tag)
{
if (depth && depth < tag_depth)
{
if (!GCOV_TAG_IS_SUBTAG (tags[depth - 1], tag))
warning (0, "%s:tag `%x' is incorrectly nested\n",
filename, tag);
}
depth = tag_depth;
tags[depth - 1] = tag;
}
{
if (depth && depth < tag_depth)
{
if (!GCOV_TAG_IS_SUBTAG (tags[depth - 1], tag))
warning (0, "%s:tag `%x' is incorrectly nested\n",
filename, tag);
}
depth = tag_depth;
tags[depth - 1] = tag;
}
if (format->proc)
{
unsigned long actual_length;
unsigned long actual_length;
(*format->proc) (tag, length);
(*format->proc) (tag, length);
actual_length = gcov_position () - base;
if (actual_length > length)
warning (0, "%s:record size mismatch %lu bytes overread\n",
filename, actual_length - length);
else if (length > actual_length)
warning (0, "%s:record size mismatch %lu bytes unread\n",
filename, length - actual_length);
}
actual_length = gcov_position () - base;
if (actual_length > length)
warning (0, "%s:record size mismatch %lu bytes overread\n",
filename, actual_length - length);
else if (length > actual_length)
warning (0, "%s:record size mismatch %lu bytes unread\n",
filename, length - actual_length);
}
gcov_sync (base, length);
if ((error = gcov_is_error ()))
{
warning (0, error < 0 ? "%s:counter overflow at %lu\n" :
"%s:read error at %lu\n", filename,
(long unsigned) gcov_position ());
break;
}
{
warning (0, error < 0 ? "%s:counter overflow at %lu\n" :
"%s:read error at %lu\n", filename,
(long unsigned) gcov_position ());
break;
}
}
read_gcda_finalize (obj_info);
@ -577,7 +577,8 @@ gcov_merge (struct gcov_info *info1, struct gcov_info *info2, int w)
Return NULL if there is no match. */
static struct gcov_info *
find_match_gcov_info (struct gcov_info **array, int size, struct gcov_info *info)
find_match_gcov_info (struct gcov_info **array, int size,
struct gcov_info *info)
{
struct gcov_info *gi_ptr;
struct gcov_info *ret = NULL;
@ -872,7 +873,530 @@ gcov_profile_normalize (struct gcov_info *profile, gcov_type max_val)
scale_factor = (float)max_val / curr_max_val;
if (verbose)
fnotice (stdout, "max_val is %lld\n", (long long) curr_max_val);
fnotice (stdout, "max_val is %"PRId64"\n", curr_max_val);
return gcov_profile_scale (profile, scale_factor, 0, 0);
}
/* The following variables are defined in gcc/gcov-tool.c. */
extern int overlap_func_level;
extern int overlap_obj_level;
extern int overlap_hot_only;
extern int overlap_use_fullname;
extern double overlap_hot_threshold;
/* Compute the overlap score of two values. The score is defined as:
min (V1/SUM_1, V2/SUM_2) */
static double
calculate_2_entries (const unsigned long v1, const unsigned long v2,
const double sum_1, const double sum_2)
{
double val1 = (sum_1 == 0.0 ? 0.0 : v1/sum_1);
double val2 = (sum_2 == 0.0 ? 0.0 : v2/sum_2);
if (val2 < val1)
val1 = val2;
return val1;
}
/* Compute the overlap score between GCOV_INFO1 and GCOV_INFO2.
SUM_1 is the sum_all for profile1 where GCOV_INFO1 belongs.
SUM_2 is the sum_all for profile2 where GCOV_INFO2 belongs.
This function also updates cumulative score CUM_1_RESULT and
CUM_2_RESULT. */
static double
compute_one_gcov (const struct gcov_info *gcov_info1,
const struct gcov_info *gcov_info2,
const double sum_1, const double sum_2,
double *cum_1_result, double *cum_2_result)
{
unsigned f_ix;
double ret = 0;
double cum_1 = 0, cum_2 = 0;
const struct gcov_info *gcov_info = 0;
double *cum_p;
double sum;
gcc_assert (gcov_info1 || gcov_info2);
if (!gcov_info1)
{
gcov_info = gcov_info2;
cum_p = cum_2_result;
sum = sum_2;
*cum_1_result = 0;
} else
if (!gcov_info2)
{
gcov_info = gcov_info1;
cum_p = cum_1_result;
sum = sum_1;
*cum_2_result = 0;
}
if (gcov_info)
{
for (f_ix = 0; f_ix < gcov_info->n_functions; f_ix++)
{
unsigned t_ix;
const struct gcov_fn_info *gfi_ptr = gcov_info->functions[f_ix];
if (!gfi_ptr || gfi_ptr->key != gcov_info)
continue;
const struct gcov_ctr_info *ci_ptr = gfi_ptr->ctrs;
for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++)
{
unsigned c_num;
if (!gcov_info->merge[t_ix])
continue;
for (c_num = 0; c_num < ci_ptr->num; c_num++)
{
cum_1 += ci_ptr->values[c_num] / sum;
}
ci_ptr++;
}
}
*cum_p = cum_1;
return 0.0;
}
for (f_ix = 0; f_ix < gcov_info1->n_functions; f_ix++)
{
unsigned t_ix;
double func_cum_1 = 0.0;
double func_cum_2 = 0.0;
double func_val = 0.0;
int nonzero = 0;
int hot = 0;
const struct gcov_fn_info *gfi_ptr1 = gcov_info1->functions[f_ix];
const struct gcov_fn_info *gfi_ptr2 = gcov_info2->functions[f_ix];
if (!gfi_ptr1 || gfi_ptr1->key != gcov_info1)
continue;
if (!gfi_ptr2 || gfi_ptr2->key != gcov_info2)
continue;
const struct gcov_ctr_info *ci_ptr1 = gfi_ptr1->ctrs;
const struct gcov_ctr_info *ci_ptr2 = gfi_ptr2->ctrs;
for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++)
{
unsigned c_num;
if (!gcov_info1->merge[t_ix])
continue;
for (c_num = 0; c_num < ci_ptr1->num; c_num++)
{
if (ci_ptr1->values[c_num] | ci_ptr2->values[c_num])
{
func_val += calculate_2_entries (ci_ptr1->values[c_num],
ci_ptr2->values[c_num],
sum_1, sum_2);
func_cum_1 += ci_ptr1->values[c_num] / sum_1;
func_cum_2 += ci_ptr2->values[c_num] / sum_2;
nonzero = 1;
if (ci_ptr1->values[c_num] / sum_1 >= overlap_hot_threshold ||
ci_ptr2->values[c_num] / sum_2 >= overlap_hot_threshold)
hot = 1;
}
}
ci_ptr1++;
ci_ptr2++;
}
ret += func_val;
cum_1 += func_cum_1;
cum_2 += func_cum_2;
if (overlap_func_level && nonzero && (!overlap_hot_only || hot))
{
printf(" \tfunc_id=%10d \toverlap =%6.5f%% (%5.5f%% %5.5f%%)\n",
gfi_ptr1->ident, func_val*100, func_cum_1*100, func_cum_2*100);
}
}
*cum_1_result = cum_1;
*cum_2_result = cum_2;
return ret;
}
/* Test if all counter values in this GCOV_INFO are cold.
"Cold" is defined as the counter value being less than
or equal to THRESHOLD. */
static bool
gcov_info_count_all_cold (const struct gcov_info *gcov_info,
gcov_type threshold)
{
unsigned f_ix;
for (f_ix = 0; f_ix < gcov_info->n_functions; f_ix++)
{
unsigned t_ix;
const struct gcov_fn_info *gfi_ptr = gcov_info->functions[f_ix];
if (!gfi_ptr || gfi_ptr->key != gcov_info)
continue;
const struct gcov_ctr_info *ci_ptr = gfi_ptr->ctrs;
for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++)
{
unsigned c_num;
if (!gcov_info->merge[t_ix])
continue;
for (c_num = 0; c_num < ci_ptr->num; c_num++)
{
if (ci_ptr->values[c_num] > threshold)
return false;
}
ci_ptr++;
}
}
return true;
}
/* Test if all counter values in this GCOV_INFO are 0. */
static bool
gcov_info_count_all_zero (const struct gcov_info *gcov_info)
{
return gcov_info_count_all_cold (gcov_info, 0);
}
/* A pair of matched GCOV_INFO.
The flag is a bitvector:
b0: obj1's all counts are 0;
b1: obj1's all counts are cold (but no 0);
b2: obj1 is hot;
b3: no obj1 to match obj2;
b4: obj2's all counts are 0;
b5: obj2's all counts are cold (but no 0);
b6: obj2 is hot;
b7: no obj2 to match obj1;
*/
struct overlap_t {
const struct gcov_info *obj1;
const struct gcov_info *obj2;
char flag;
};
#define FLAG_BOTH_ZERO(flag) ((flag & 0x1) && (flag & 0x10))
#define FLAG_BOTH_COLD(flag) ((flag & 0x2) && (flag & 0x20))
#define FLAG_ONE_HOT(flag) ((flag & 0x4) || (flag & 0x40))
/* Cumlative overlap dscore for profile1 and profile2. */
static double overlap_sum_1, overlap_sum_2;
/* sum_all for profile1 and profile2. */
static gcov_type p1_sum_all, p2_sum_all;
/* run_max for profile1 and profile2. */
static gcov_type p1_run_max, p2_run_max;
/* The number of gcda files in the profiles. */
static unsigned gcda_files[2];
/* The number of unique gcda files in the profiles
(not existing in the other profile). */
static unsigned unique_gcda_files[2];
/* The number of gcda files that all counter values are 0. */
static unsigned zero_gcda_files[2];
/* The number of gcda files that all counter values are cold (but not 0). */
static unsigned cold_gcda_files[2];
/* The number of gcda files that includes hot counter values. */
static unsigned hot_gcda_files[2];
/* The number of gcda files with hot count value in either profiles. */
static unsigned both_hot_cnt;
/* The number of gcda files with all counts cold (but not 0) in
both profiles. */
static unsigned both_cold_cnt;
/* The number of gcda files with all counts 0 in both profiles. */
static unsigned both_zero_cnt;
/* Extract the basename of the filename NAME. */
static char *
extract_file_basename (const char *name)
{
char *str;
int len = 0;
char *path = xstrdup (name);
char sep_str[2];
sep_str[0] = DIR_SEPARATOR;
sep_str[1] = 0;
str = strstr(path, sep_str);
do{
len = strlen(str) + 1;
path = &path[strlen(path) - len + 2];
str = strstr(path, sep_str);
} while(str);
return path;
}
/* Utility function to get the filename. */
static const char *
get_file_basename (const char *name)
{
if (overlap_use_fullname)
return name;
return extract_file_basename (name);
}
/* A utility function to set the flag for the gcda files. */
static void
set_flag (struct overlap_t *e)
{
char flag = 0;
if (!e->obj1)
{
unique_gcda_files[1]++;
flag = 0x8;
}
else
{
gcda_files[0]++;
if (gcov_info_count_all_zero (e->obj1))
{
zero_gcda_files[0]++;
flag = 0x1;
}
else
if (gcov_info_count_all_cold (e->obj1, overlap_sum_1
* overlap_hot_threshold))
{
cold_gcda_files[0]++;
flag = 0x2;
}
else
{
hot_gcda_files[0]++;
flag = 0x4;
}
}
if (!e->obj2)
{
unique_gcda_files[0]++;
flag |= (0x8 << 4);
}
else
{
gcda_files[1]++;
if (gcov_info_count_all_zero (e->obj2))
{
zero_gcda_files[1]++;
flag |= (0x1 << 4);
}
else
if (gcov_info_count_all_cold (e->obj2, overlap_sum_2
* overlap_hot_threshold))
{
cold_gcda_files[1]++;
flag |= (0x2 << 4);
}
else
{
hot_gcda_files[1]++;
flag |= (0x4 << 4);
}
}
gcc_assert (flag);
e->flag = flag;
}
/* Test if INFO1 and INFO2 are from the matched source file.
Return 1 if they match; return 0 otherwise. */
static int
matched_gcov_info (const struct gcov_info *info1, const struct gcov_info *info2)
{
/* For FDO, we have to match the name. This can be expensive.
Maybe we should use hash here. */
if (strcmp (info1->filename, info2->filename))
return 0;
if (info1->n_functions != info2->n_functions)
{
fnotice (stderr, "mismatched profiles in %s (%d functions"
" vs %d functions)\n",
info1->filename,
info1->n_functions,
info2->n_functions);
return 0;
}
return 1;
}
/* Defined in libgcov-driver.c. */
extern gcov_unsigned_t compute_summary (struct gcov_info *,
struct gcov_summary *, size_t *);
/* Compute the overlap score of two profiles with the head of GCOV_LIST1 and
GCOV_LIST1. Return a number ranging from [0.0, 1.0], with 0.0 meaning no
match and 1.0 meaning a perfect match. */
static double
calculate_overlap (struct gcov_info *gcov_list1,
struct gcov_info *gcov_list2)
{
struct gcov_summary this_prg;
unsigned list1_cnt = 0, list2_cnt= 0, all_cnt;
unsigned int i, j;
size_t max_length;
const struct gcov_info *gi_ptr;
struct overlap_t *all_infos;
compute_summary (gcov_list1, &this_prg, &max_length);
overlap_sum_1 = (double) (this_prg.ctrs[0].sum_all);
p1_sum_all = this_prg.ctrs[0].sum_all;
p1_run_max = this_prg.ctrs[0].run_max;
compute_summary (gcov_list2, &this_prg, &max_length);
overlap_sum_2 = (double) (this_prg.ctrs[0].sum_all);
p2_sum_all = this_prg.ctrs[0].sum_all;
p2_run_max = this_prg.ctrs[0].run_max;
for (gi_ptr = gcov_list1; gi_ptr; gi_ptr = gi_ptr->next)
list1_cnt++;
for (gi_ptr = gcov_list2; gi_ptr; gi_ptr = gi_ptr->next)
list2_cnt++;
all_cnt = list1_cnt + list2_cnt;
all_infos = (struct overlap_t *) xmalloc (sizeof (struct overlap_t)
* all_cnt * 2);
gcc_assert (all_infos);
i = 0;
for (gi_ptr = gcov_list1; gi_ptr; gi_ptr = gi_ptr->next, i++)
{
all_infos[i].obj1 = gi_ptr;
all_infos[i].obj2 = 0;
}
for (gi_ptr = gcov_list2; gi_ptr; gi_ptr = gi_ptr->next, i++)
{
all_infos[i].obj1 = 0;
all_infos[i].obj2 = gi_ptr;
}
for (i = list1_cnt; i < all_cnt; i++)
{
if (all_infos[i].obj2 == 0)
continue;
for (j = 0; j < list1_cnt; j++)
{
if (all_infos[j].obj2 != 0)
continue;
if (matched_gcov_info (all_infos[i].obj2, all_infos[j].obj1))
{
all_infos[j].obj2 = all_infos[i].obj2;
all_infos[i].obj2 = 0;
break;
}
}
}
for (i = 0; i < all_cnt; i++)
if (all_infos[i].obj1 || all_infos[i].obj2)
{
set_flag (all_infos + i);
if (FLAG_ONE_HOT (all_infos[i].flag))
both_hot_cnt++;
if (FLAG_BOTH_COLD(all_infos[i].flag))
both_cold_cnt++;
if (FLAG_BOTH_ZERO(all_infos[i].flag))
both_zero_cnt++;
}
double prg_val = 0;
double sum_val = 0;
double sum_cum_1 = 0;
double sum_cum_2 = 0;
for (i = 0; i < all_cnt; i++)
{
double val;
double cum_1, cum_2;
const char *filename;
if (all_infos[i].obj1 == 0 && all_infos[i].obj2 == 0)
continue;
if (FLAG_BOTH_ZERO (all_infos[i].flag))
continue;
if (all_infos[i].obj1)
filename = get_file_basename (all_infos[i].obj1->filename);
else
filename = get_file_basename (all_infos[i].obj2->filename);
if (overlap_func_level)
printf("\n processing %36s:\n", filename);
val = compute_one_gcov (all_infos[i].obj1, all_infos[i].obj2,
overlap_sum_1, overlap_sum_2, &cum_1, &cum_2);
if (overlap_obj_level && (!overlap_hot_only || FLAG_ONE_HOT (all_infos[i].flag)))
{
printf(" obj=%36s overlap = %6.2f%% (%5.2f%% %5.2f%%)\n",
filename, val*100, cum_1*100, cum_2*100);
sum_val += val;
sum_cum_1 += cum_1;
sum_cum_2 += cum_2;
}
prg_val += val;
}
if (overlap_obj_level)
printf(" SUM:%36s overlap = %6.2f%% (%5.2f%% %5.2f%%)\n",
"", sum_val*100, sum_cum_1*100, sum_cum_2*100);
printf (" Statistics:\n"
" profile1_# profile2_# overlap_#\n");
printf (" gcda files: %12u\t%12u\t%12u\n", gcda_files[0], gcda_files[1],
gcda_files[0]-unique_gcda_files[0]);
printf (" unique files: %12u\t%12u\n", unique_gcda_files[0],
unique_gcda_files[1]);
printf (" hot files: %12u\t%12u\t%12u\n", hot_gcda_files[0],
hot_gcda_files[1], both_hot_cnt);
printf (" cold files: %12u\t%12u\t%12u\n", cold_gcda_files[0],
cold_gcda_files[1], both_cold_cnt);
printf (" zero files: %12u\t%12u\t%12u\n", zero_gcda_files[0],
zero_gcda_files[1], both_zero_cnt);
printf (" sum_all: %12"PRId64"\t%12"PRId64"\n", p1_sum_all, p2_sum_all);
printf (" run_max: %12"PRId64"\t%12"PRId64"\n", p1_run_max, p2_run_max);
return prg_val;
}
/* Computer the overlap score of two lists of gcov_info objects PROFILE1 and PROFILE2.
Return 0 on success: without mismatch. Reutrn 1 on error. */
int
gcov_profile_overlap (struct gcov_info *profile1, struct gcov_info *profile2)
{
double result;
result = calculate_overlap (profile1, profile2);
if (result > 0)
{
printf("\nProgram level overlap result is %3.2f%%\n\n", result*100);
return 0;
}
return 1;
}