Home | History | Annotate | Line # | Download | only in libgcc
libgcov-util.c revision 1.1.1.6
      1      1.1  mrg /* Utility functions for reading gcda files into in-memory
      2      1.1  mrg    gcov_info structures and offline profile processing. */
      3  1.1.1.6  mrg /* Copyright (C) 2014-2020 Free Software Foundation, Inc.
      4      1.1  mrg    Contributed by Rong Xu <xur (at) google.com>.
      5      1.1  mrg 
      6      1.1  mrg This file is part of GCC.
      7      1.1  mrg 
      8      1.1  mrg GCC is free software; you can redistribute it and/or modify it under
      9      1.1  mrg the terms of the GNU General Public License as published by the Free
     10      1.1  mrg Software Foundation; either version 3, or (at your option) any later
     11      1.1  mrg version.
     12      1.1  mrg 
     13      1.1  mrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
     14      1.1  mrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
     15      1.1  mrg FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     16      1.1  mrg for more details.
     17      1.1  mrg 
     18      1.1  mrg Under Section 7 of GPL version 3, you are granted additional
     19      1.1  mrg permissions described in the GCC Runtime Library Exception, version
     20      1.1  mrg 3.1, as published by the Free Software Foundation.
     21      1.1  mrg 
     22      1.1  mrg You should have received a copy of the GNU General Public License and
     23      1.1  mrg a copy of the GCC Runtime Library Exception along with this program;
     24      1.1  mrg see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     25      1.1  mrg <http://www.gnu.org/licenses/>.  */
     26      1.1  mrg 
     27      1.1  mrg 
     28      1.1  mrg #define IN_GCOV_TOOL 1
     29      1.1  mrg 
     30      1.1  mrg #include "libgcov.h"
     31      1.1  mrg #include "intl.h"
     32      1.1  mrg #include "diagnostic.h"
     33      1.1  mrg #include "version.h"
     34      1.1  mrg #include "demangle.h"
     35  1.1.1.5  mrg #include "gcov-io.h"
     36      1.1  mrg 
     37      1.1  mrg /* Borrowed from basic-block.h.  */
     38      1.1  mrg #define RDIV(X,Y) (((X) + (Y) / 2) / (Y))
     39      1.1  mrg 
     40      1.1  mrg extern gcov_position_t gcov_position();
     41      1.1  mrg extern int gcov_is_error();
     42      1.1  mrg 
     43      1.1  mrg /* Verbose mode for debug.  */
     44      1.1  mrg static int verbose;
     45      1.1  mrg 
     46      1.1  mrg /* Set verbose flag.  */
     47      1.1  mrg void gcov_set_verbose (void)
     48      1.1  mrg {
     49      1.1  mrg   verbose = 1;
     50      1.1  mrg }
     51      1.1  mrg 
     52      1.1  mrg /* The following part is to read Gcda and reconstruct GCOV_INFO.  */
     53      1.1  mrg 
     54      1.1  mrg #include "obstack.h"
     55      1.1  mrg #include <unistd.h>
     56      1.1  mrg #ifdef HAVE_FTW_H
     57      1.1  mrg #include <ftw.h>
     58      1.1  mrg #endif
     59      1.1  mrg 
     60      1.1  mrg static void tag_function (unsigned, unsigned);
     61      1.1  mrg static void tag_blocks (unsigned, unsigned);
     62      1.1  mrg static void tag_arcs (unsigned, unsigned);
     63      1.1  mrg static void tag_lines (unsigned, unsigned);
     64      1.1  mrg static void tag_counters (unsigned, unsigned);
     65      1.1  mrg static void tag_summary (unsigned, unsigned);
     66      1.1  mrg 
     67      1.1  mrg /* The gcov_info for the first module.  */
     68      1.1  mrg static struct gcov_info *curr_gcov_info;
     69      1.1  mrg /* The gcov_info being processed.  */
     70      1.1  mrg static struct gcov_info *gcov_info_head;
     71      1.1  mrg /* This variable contains all the functions in current module.  */
     72      1.1  mrg static struct obstack fn_info;
     73      1.1  mrg /* The function being processed.  */
     74      1.1  mrg static struct gcov_fn_info *curr_fn_info;
     75      1.1  mrg /* The number of functions seen so far.  */
     76      1.1  mrg static unsigned num_fn_info;
     77      1.1  mrg /* This variable contains all the counters for current module.  */
     78      1.1  mrg static int k_ctrs_mask[GCOV_COUNTERS];
     79      1.1  mrg /* The kind of counters that have been seen.  */
     80      1.1  mrg static struct gcov_ctr_info k_ctrs[GCOV_COUNTERS];
     81      1.1  mrg /* Number of kind of counters that have been seen.  */
     82      1.1  mrg static int k_ctrs_types;
     83  1.1.1.5  mrg /* The object summary being processed.  */
     84  1.1.1.5  mrg static struct gcov_summary *curr_object_summary;
     85      1.1  mrg 
     86      1.1  mrg /* Merge functions for counters.  */
     87      1.1  mrg #define DEF_GCOV_COUNTER(COUNTER, NAME, FN_TYPE) __gcov_merge ## FN_TYPE,
     88      1.1  mrg static gcov_merge_fn ctr_merge_functions[GCOV_COUNTERS] = {
     89      1.1  mrg #include "gcov-counter.def"
     90      1.1  mrg };
     91      1.1  mrg #undef DEF_GCOV_COUNTER
     92      1.1  mrg 
     93      1.1  mrg /* Set the ctrs field in gcov_fn_info object FN_INFO.  */
     94      1.1  mrg 
     95      1.1  mrg static void
     96      1.1  mrg set_fn_ctrs (struct gcov_fn_info *fn_info)
     97      1.1  mrg {
     98      1.1  mrg   int j = 0, i;
     99      1.1  mrg 
    100      1.1  mrg   for (i = 0; i < GCOV_COUNTERS; i++)
    101      1.1  mrg     {
    102      1.1  mrg       if (k_ctrs_mask[i] == 0)
    103      1.1  mrg         continue;
    104      1.1  mrg       fn_info->ctrs[j].num = k_ctrs[i].num;
    105      1.1  mrg       fn_info->ctrs[j].values = k_ctrs[i].values;
    106      1.1  mrg       j++;
    107      1.1  mrg     }
    108      1.1  mrg   if (k_ctrs_types == 0)
    109      1.1  mrg     k_ctrs_types = j;
    110      1.1  mrg   else
    111      1.1  mrg     gcc_assert (j == k_ctrs_types);
    112      1.1  mrg }
    113      1.1  mrg 
    114      1.1  mrg /* For each tag in gcda file, we have an entry here.
    115      1.1  mrg    TAG is the tag value; NAME is the tag name; and
    116      1.1  mrg    PROC is the handler function.  */
    117      1.1  mrg 
    118      1.1  mrg typedef struct tag_format
    119      1.1  mrg {
    120      1.1  mrg     unsigned tag;
    121      1.1  mrg     char const *name;
    122      1.1  mrg     void (*proc) (unsigned, unsigned);
    123      1.1  mrg } tag_format_t;
    124      1.1  mrg 
    125      1.1  mrg /* Handler table for various Tags.  */
    126      1.1  mrg 
    127      1.1  mrg static const tag_format_t tag_table[] =
    128      1.1  mrg {
    129      1.1  mrg   {0, "NOP", NULL},
    130      1.1  mrg   {0, "UNKNOWN", NULL},
    131      1.1  mrg   {0, "COUNTERS", tag_counters},
    132      1.1  mrg   {GCOV_TAG_FUNCTION, "FUNCTION", tag_function},
    133      1.1  mrg   {GCOV_TAG_BLOCKS, "BLOCKS", tag_blocks},
    134      1.1  mrg   {GCOV_TAG_ARCS, "ARCS", tag_arcs},
    135      1.1  mrg   {GCOV_TAG_LINES, "LINES", tag_lines},
    136      1.1  mrg   {GCOV_TAG_OBJECT_SUMMARY, "OBJECT_SUMMARY", tag_summary},
    137      1.1  mrg   {0, NULL, NULL}
    138      1.1  mrg };
    139      1.1  mrg 
    140      1.1  mrg /* Handler for reading function tag.  */
    141      1.1  mrg 
    142      1.1  mrg static void
    143      1.1  mrg tag_function (unsigned tag ATTRIBUTE_UNUSED, unsigned length ATTRIBUTE_UNUSED)
    144      1.1  mrg {
    145      1.1  mrg   int i;
    146      1.1  mrg 
    147      1.1  mrg   /* write out previous fn_info.  */
    148      1.1  mrg   if (num_fn_info)
    149      1.1  mrg     {
    150      1.1  mrg       set_fn_ctrs (curr_fn_info);
    151      1.1  mrg       obstack_ptr_grow (&fn_info, curr_fn_info);
    152      1.1  mrg     }
    153      1.1  mrg 
    154      1.1  mrg   /* Here we over allocate a bit, using GCOV_COUNTERS instead of the actual active
    155      1.1  mrg      counter types.  */
    156      1.1  mrg   curr_fn_info = (struct gcov_fn_info *) xcalloc (sizeof (struct gcov_fn_info)
    157      1.1  mrg                    + GCOV_COUNTERS * sizeof (struct gcov_ctr_info), 1);
    158      1.1  mrg 
    159      1.1  mrg   for (i = 0; i < GCOV_COUNTERS; i++)
    160      1.1  mrg      k_ctrs[i].num = 0;
    161      1.1  mrg   k_ctrs_types = 0;
    162      1.1  mrg 
    163      1.1  mrg   curr_fn_info->key = curr_gcov_info;
    164      1.1  mrg   curr_fn_info->ident = gcov_read_unsigned ();
    165      1.1  mrg   curr_fn_info->lineno_checksum = gcov_read_unsigned ();
    166      1.1  mrg   curr_fn_info->cfg_checksum = gcov_read_unsigned ();
    167      1.1  mrg   num_fn_info++;
    168      1.1  mrg 
    169      1.1  mrg   if (verbose)
    170      1.1  mrg     fnotice (stdout, "tag one function id=%d\n", curr_fn_info->ident);
    171      1.1  mrg }
    172      1.1  mrg 
    173      1.1  mrg /* Handler for reading block tag.  */
    174      1.1  mrg 
    175      1.1  mrg static void
    176      1.1  mrg tag_blocks (unsigned tag ATTRIBUTE_UNUSED, unsigned length ATTRIBUTE_UNUSED)
    177      1.1  mrg {
    178      1.1  mrg   /* TBD: gcov-tool currently does not handle gcno files. Assert here.  */
    179      1.1  mrg   gcc_unreachable ();
    180      1.1  mrg }
    181      1.1  mrg 
    182      1.1  mrg /* Handler for reading flow arc tag.  */
    183      1.1  mrg 
    184      1.1  mrg static void
    185      1.1  mrg tag_arcs (unsigned tag ATTRIBUTE_UNUSED, unsigned length ATTRIBUTE_UNUSED)
    186      1.1  mrg {
    187      1.1  mrg   /* TBD: gcov-tool currently does not handle gcno files. Assert here.  */
    188      1.1  mrg   gcc_unreachable ();
    189      1.1  mrg }
    190      1.1  mrg 
    191      1.1  mrg /* Handler for reading line tag.  */
    192      1.1  mrg 
    193      1.1  mrg static void
    194      1.1  mrg tag_lines (unsigned tag ATTRIBUTE_UNUSED, unsigned length ATTRIBUTE_UNUSED)
    195      1.1  mrg {
    196      1.1  mrg   /* TBD: gcov-tool currently does not handle gcno files. Assert here.  */
    197      1.1  mrg   gcc_unreachable ();
    198      1.1  mrg }
    199      1.1  mrg 
    200      1.1  mrg /* Handler for reading counters array tag with value as TAG and length of LENGTH.  */
    201      1.1  mrg 
    202      1.1  mrg static void
    203      1.1  mrg tag_counters (unsigned tag, unsigned length)
    204      1.1  mrg {
    205      1.1  mrg   unsigned n_counts = GCOV_TAG_COUNTER_NUM (length);
    206      1.1  mrg   gcov_type *values;
    207      1.1  mrg   unsigned ix;
    208      1.1  mrg   unsigned tag_ix;
    209      1.1  mrg 
    210      1.1  mrg   tag_ix = GCOV_COUNTER_FOR_TAG (tag);
    211      1.1  mrg   gcc_assert (tag_ix < GCOV_COUNTERS);
    212      1.1  mrg   k_ctrs_mask [tag_ix] = 1;
    213      1.1  mrg   gcc_assert (k_ctrs[tag_ix].num == 0);
    214      1.1  mrg   k_ctrs[tag_ix].num = n_counts;
    215      1.1  mrg 
    216      1.1  mrg   k_ctrs[tag_ix].values = values = (gcov_type *) xmalloc (n_counts * sizeof (gcov_type));
    217      1.1  mrg   gcc_assert (values);
    218      1.1  mrg 
    219      1.1  mrg   for (ix = 0; ix != n_counts; ix++)
    220      1.1  mrg     values[ix] = gcov_read_counter ();
    221      1.1  mrg }
    222      1.1  mrg 
    223      1.1  mrg /* Handler for reading summary tag.  */
    224      1.1  mrg 
    225      1.1  mrg static void
    226      1.1  mrg tag_summary (unsigned tag ATTRIBUTE_UNUSED, unsigned length ATTRIBUTE_UNUSED)
    227      1.1  mrg {
    228  1.1.1.5  mrg   curr_object_summary = (gcov_summary *) xcalloc (sizeof (gcov_summary), 1);
    229  1.1.1.5  mrg   gcov_read_summary (curr_object_summary);
    230      1.1  mrg }
    231      1.1  mrg 
    232      1.1  mrg /* This function is called at the end of reading a gcda file.
    233      1.1  mrg    It flushes the contents in curr_fn_info to gcov_info object OBJ_INFO.  */
    234      1.1  mrg 
    235      1.1  mrg static void
    236      1.1  mrg read_gcda_finalize (struct gcov_info *obj_info)
    237      1.1  mrg {
    238      1.1  mrg   int i;
    239      1.1  mrg 
    240      1.1  mrg   set_fn_ctrs (curr_fn_info);
    241      1.1  mrg   obstack_ptr_grow (&fn_info, curr_fn_info);
    242      1.1  mrg 
    243  1.1.1.5  mrg   /* We set the following fields: merge, n_functions, functions
    244  1.1.1.5  mrg      and summary.  */
    245      1.1  mrg   obj_info->n_functions = num_fn_info;
    246      1.1  mrg   obj_info->functions = (const struct gcov_fn_info**) obstack_finish (&fn_info);
    247      1.1  mrg 
    248      1.1  mrg   /* wrap all the counter array.  */
    249      1.1  mrg   for (i=0; i< GCOV_COUNTERS; i++)
    250      1.1  mrg     {
    251      1.1  mrg       if (k_ctrs_mask[i])
    252      1.1  mrg         obj_info->merge[i] = ctr_merge_functions[i];
    253      1.1  mrg     }
    254      1.1  mrg }
    255      1.1  mrg 
    256      1.1  mrg /* Read the content of a gcda file FILENAME, and return a gcov_info data structure.
    257      1.1  mrg    Program level summary CURRENT_SUMMARY will also be updated.  */
    258      1.1  mrg 
    259      1.1  mrg static struct gcov_info *
    260      1.1  mrg read_gcda_file (const char *filename)
    261      1.1  mrg {
    262      1.1  mrg   unsigned tags[4];
    263      1.1  mrg   unsigned depth = 0;
    264  1.1.1.6  mrg   unsigned version;
    265      1.1  mrg   struct gcov_info *obj_info;
    266      1.1  mrg   int i;
    267      1.1  mrg 
    268      1.1  mrg   for (i=0; i< GCOV_COUNTERS; i++)
    269      1.1  mrg     k_ctrs_mask[i] = 0;
    270      1.1  mrg   k_ctrs_types = 0;
    271      1.1  mrg 
    272      1.1  mrg   if (!gcov_open (filename))
    273      1.1  mrg     {
    274      1.1  mrg       fnotice (stderr, "%s:cannot open\n", filename);
    275      1.1  mrg       return NULL;
    276      1.1  mrg     }
    277      1.1  mrg 
    278      1.1  mrg   /* Read magic.  */
    279  1.1.1.6  mrg   if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
    280      1.1  mrg     {
    281      1.1  mrg       fnotice (stderr, "%s:not a gcov data file\n", filename);
    282      1.1  mrg       gcov_close ();
    283      1.1  mrg       return NULL;
    284      1.1  mrg     }
    285      1.1  mrg 
    286      1.1  mrg   /* Read version.  */
    287      1.1  mrg   version = gcov_read_unsigned ();
    288      1.1  mrg   if (version != GCOV_VERSION)
    289      1.1  mrg     {
    290      1.1  mrg       fnotice (stderr, "%s:incorrect gcov version %d vs %d \n", filename, version, GCOV_VERSION);
    291      1.1  mrg       gcov_close ();
    292      1.1  mrg       return NULL;
    293      1.1  mrg     }
    294      1.1  mrg 
    295      1.1  mrg   /* Instantiate a gcov_info object.  */
    296      1.1  mrg   curr_gcov_info = obj_info = (struct gcov_info *) xcalloc (sizeof (struct gcov_info) +
    297      1.1  mrg              sizeof (struct gcov_ctr_info) * GCOV_COUNTERS, 1);
    298      1.1  mrg 
    299      1.1  mrg   obj_info->version = version;
    300      1.1  mrg   obstack_init (&fn_info);
    301      1.1  mrg   num_fn_info = 0;
    302      1.1  mrg   curr_fn_info = 0;
    303  1.1.1.5  mrg   curr_object_summary = NULL;
    304      1.1  mrg   {
    305      1.1  mrg     size_t len = strlen (filename) + 1;
    306      1.1  mrg     char *str_dup = (char*) xmalloc (len);
    307      1.1  mrg 
    308      1.1  mrg     memcpy (str_dup, filename, len);
    309      1.1  mrg     obj_info->filename = str_dup;
    310      1.1  mrg   }
    311      1.1  mrg 
    312      1.1  mrg   /* Read stamp.  */
    313      1.1  mrg   obj_info->stamp = gcov_read_unsigned ();
    314      1.1  mrg 
    315      1.1  mrg   while (1)
    316      1.1  mrg     {
    317      1.1  mrg       gcov_position_t base;
    318      1.1  mrg       unsigned tag, length;
    319      1.1  mrg       tag_format_t const *format;
    320      1.1  mrg       unsigned tag_depth;
    321      1.1  mrg       int error;
    322      1.1  mrg       unsigned mask;
    323      1.1  mrg 
    324      1.1  mrg       tag = gcov_read_unsigned ();
    325      1.1  mrg       if (!tag)
    326      1.1  mrg         break;
    327      1.1  mrg       length = gcov_read_unsigned ();
    328      1.1  mrg       base = gcov_position ();
    329      1.1  mrg       mask = GCOV_TAG_MASK (tag) >> 1;
    330      1.1  mrg       for (tag_depth = 4; mask; mask >>= 8)
    331      1.1  mrg         {
    332      1.1  mrg           if (((mask & 0xff) != 0xff))
    333      1.1  mrg             {
    334  1.1.1.6  mrg 	      warning (0, "%s:tag %qx is invalid", filename, tag);
    335      1.1  mrg               break;
    336      1.1  mrg             }
    337      1.1  mrg           tag_depth--;
    338      1.1  mrg         }
    339      1.1  mrg       for (format = tag_table; format->name; format++)
    340      1.1  mrg         if (format->tag == tag)
    341      1.1  mrg           goto found;
    342      1.1  mrg       format = &tag_table[GCOV_TAG_IS_COUNTER (tag) ? 2 : 1];
    343      1.1  mrg     found:;
    344      1.1  mrg       if (tag)
    345      1.1  mrg         {
    346      1.1  mrg           if (depth && depth < tag_depth)
    347      1.1  mrg             {
    348      1.1  mrg               if (!GCOV_TAG_IS_SUBTAG (tags[depth - 1], tag))
    349  1.1.1.6  mrg 	        warning (0, "%s:tag %qx is incorrectly nested",
    350      1.1  mrg                          filename, tag);
    351      1.1  mrg             }
    352      1.1  mrg           depth = tag_depth;
    353      1.1  mrg           tags[depth - 1] = tag;
    354      1.1  mrg         }
    355      1.1  mrg 
    356      1.1  mrg       if (format->proc)
    357      1.1  mrg         {
    358      1.1  mrg           unsigned long actual_length;
    359      1.1  mrg 
    360      1.1  mrg           (*format->proc) (tag, length);
    361      1.1  mrg 
    362      1.1  mrg           actual_length = gcov_position () - base;
    363      1.1  mrg           if (actual_length > length)
    364  1.1.1.6  mrg 	    warning (0, "%s:record size mismatch %lu bytes overread",
    365      1.1  mrg                      filename, actual_length - length);
    366      1.1  mrg           else if (length > actual_length)
    367  1.1.1.6  mrg 	    warning (0, "%s:record size mismatch %lu bytes unread",
    368      1.1  mrg                      filename, length - actual_length);
    369      1.1  mrg        }
    370      1.1  mrg 
    371      1.1  mrg       gcov_sync (base, length);
    372      1.1  mrg       if ((error = gcov_is_error ()))
    373      1.1  mrg         {
    374  1.1.1.6  mrg 	  warning (0, error < 0 ? "%s:counter overflow at %lu" :
    375  1.1.1.6  mrg 	                          "%s:read error at %lu", filename,
    376      1.1  mrg                    (long unsigned) gcov_position ());
    377      1.1  mrg           break;
    378      1.1  mrg         }
    379      1.1  mrg     }
    380      1.1  mrg 
    381      1.1  mrg   read_gcda_finalize (obj_info);
    382      1.1  mrg   gcov_close ();
    383      1.1  mrg 
    384      1.1  mrg   return obj_info;
    385      1.1  mrg }
    386      1.1  mrg 
    387      1.1  mrg #ifdef HAVE_FTW_H
    388      1.1  mrg /* This will be called by ftw(). It opens and read a gcda file FILENAME.
    389      1.1  mrg    Return a non-zero value to stop the tree walk.  */
    390      1.1  mrg 
    391      1.1  mrg static int
    392      1.1  mrg ftw_read_file (const char *filename,
    393      1.1  mrg                const struct stat *status ATTRIBUTE_UNUSED,
    394      1.1  mrg                int type)
    395      1.1  mrg {
    396      1.1  mrg   int filename_len;
    397      1.1  mrg   int suffix_len;
    398      1.1  mrg   struct gcov_info *obj_info;
    399      1.1  mrg 
    400      1.1  mrg   /* Only read regular files.  */
    401      1.1  mrg   if (type != FTW_F)
    402      1.1  mrg     return 0;
    403      1.1  mrg 
    404      1.1  mrg   filename_len = strlen (filename);
    405      1.1  mrg   suffix_len = strlen (GCOV_DATA_SUFFIX);
    406      1.1  mrg 
    407      1.1  mrg   if (filename_len <= suffix_len)
    408      1.1  mrg     return 0;
    409      1.1  mrg 
    410      1.1  mrg   if (strcmp(filename + filename_len - suffix_len, GCOV_DATA_SUFFIX))
    411      1.1  mrg     return 0;
    412      1.1  mrg 
    413      1.1  mrg   if (verbose)
    414      1.1  mrg     fnotice (stderr, "reading file: %s\n", filename);
    415      1.1  mrg 
    416      1.1  mrg   obj_info = read_gcda_file (filename);
    417      1.1  mrg   if (!obj_info)
    418      1.1  mrg     return 0;
    419      1.1  mrg 
    420      1.1  mrg   obj_info->next = gcov_info_head;
    421      1.1  mrg   gcov_info_head = obj_info;
    422      1.1  mrg 
    423      1.1  mrg   return 0;
    424      1.1  mrg }
    425      1.1  mrg #endif
    426      1.1  mrg 
    427      1.1  mrg /* Initializer for reading a profile dir.  */
    428      1.1  mrg 
    429      1.1  mrg static inline void
    430      1.1  mrg read_profile_dir_init (void)
    431      1.1  mrg {
    432      1.1  mrg   gcov_info_head = 0;
    433      1.1  mrg }
    434      1.1  mrg 
    435      1.1  mrg /* Driver for read a profile directory and convert into gcov_info list in memory.
    436      1.1  mrg    Return NULL on error,
    437      1.1  mrg    Return the head of gcov_info list on success.  */
    438      1.1  mrg 
    439      1.1  mrg struct gcov_info *
    440      1.1  mrg gcov_read_profile_dir (const char* dir_name, int recompute_summary ATTRIBUTE_UNUSED)
    441      1.1  mrg {
    442      1.1  mrg   char *pwd;
    443      1.1  mrg   int ret;
    444      1.1  mrg 
    445      1.1  mrg   read_profile_dir_init ();
    446      1.1  mrg 
    447      1.1  mrg   if (access (dir_name, R_OK) != 0)
    448      1.1  mrg     {
    449      1.1  mrg       fnotice (stderr, "cannot access directory %s\n", dir_name);
    450      1.1  mrg       return NULL;
    451      1.1  mrg     }
    452      1.1  mrg   pwd = getcwd (NULL, 0);
    453      1.1  mrg   gcc_assert (pwd);
    454      1.1  mrg   ret = chdir (dir_name);
    455      1.1  mrg   if (ret !=0)
    456      1.1  mrg     {
    457      1.1  mrg       fnotice (stderr, "%s is not a directory\n", dir_name);
    458      1.1  mrg       return NULL;
    459      1.1  mrg     }
    460      1.1  mrg #ifdef HAVE_FTW_H
    461      1.1  mrg   ftw (".", ftw_read_file, 50);
    462      1.1  mrg #endif
    463  1.1.1.6  mrg   chdir (pwd);
    464      1.1  mrg   free (pwd);
    465      1.1  mrg 
    466      1.1  mrg   return gcov_info_head;;
    467      1.1  mrg }
    468      1.1  mrg 
    469      1.1  mrg /* This part of the code is to merge profile counters. These
    470      1.1  mrg    variables are set in merge_wrapper and to be used by
    471      1.1  mrg    global function gcov_read_counter_mem() and gcov_get_merge_weight.  */
    472      1.1  mrg 
    473      1.1  mrg /* We save the counter value address to this variable.  */
    474      1.1  mrg static gcov_type *gcov_value_buf;
    475      1.1  mrg 
    476      1.1  mrg /* The number of counter values to be read by current merging.  */
    477      1.1  mrg static gcov_unsigned_t gcov_value_buf_size;
    478      1.1  mrg 
    479      1.1  mrg /* The index of counter values being read.  */
    480      1.1  mrg static gcov_unsigned_t gcov_value_buf_pos;
    481      1.1  mrg 
    482      1.1  mrg /* The weight of current merging.  */
    483      1.1  mrg static unsigned gcov_merge_weight;
    484      1.1  mrg 
    485      1.1  mrg /* Read a counter value from gcov_value_buf array.  */
    486      1.1  mrg 
    487      1.1  mrg gcov_type
    488      1.1  mrg gcov_read_counter_mem (void)
    489      1.1  mrg {
    490      1.1  mrg   gcov_type ret;
    491      1.1  mrg   gcc_assert (gcov_value_buf_pos < gcov_value_buf_size);
    492      1.1  mrg   ret = *(gcov_value_buf + gcov_value_buf_pos);
    493      1.1  mrg   ++gcov_value_buf_pos;
    494      1.1  mrg   return ret;
    495      1.1  mrg }
    496      1.1  mrg 
    497      1.1  mrg /* Return the recorded merge weight.  */
    498      1.1  mrg 
    499      1.1  mrg unsigned
    500      1.1  mrg gcov_get_merge_weight (void)
    501      1.1  mrg {
    502      1.1  mrg   return gcov_merge_weight;
    503      1.1  mrg }
    504      1.1  mrg 
    505      1.1  mrg /* A wrapper function for merge functions. It sets up the
    506      1.1  mrg    value buffer and weights and then calls the merge function.  */
    507      1.1  mrg 
    508      1.1  mrg static void
    509      1.1  mrg merge_wrapper (gcov_merge_fn f, gcov_type *v1, gcov_unsigned_t n,
    510      1.1  mrg                gcov_type *v2, unsigned w)
    511      1.1  mrg {
    512      1.1  mrg   gcov_value_buf = v2;
    513      1.1  mrg   gcov_value_buf_pos = 0;
    514      1.1  mrg   gcov_value_buf_size = n;
    515      1.1  mrg   gcov_merge_weight = w;
    516      1.1  mrg   (*f) (v1, n);
    517      1.1  mrg }
    518      1.1  mrg 
    519      1.1  mrg /* Offline tool to manipulate profile data.
    520      1.1  mrg    This tool targets on matched profiles. But it has some tolerance on
    521      1.1  mrg    unmatched profiles.
    522      1.1  mrg    When merging p1 to p2 (p2 is the dst),
    523      1.1  mrg    * m.gcda in p1 but not in p2: append m.gcda to p2 with specified weight;
    524      1.1  mrg      emit warning
    525      1.1  mrg    * m.gcda in p2 but not in p1: keep m.gcda in p2 and multiply by
    526      1.1  mrg      specified weight; emit warning.
    527      1.1  mrg    * m.gcda in both p1 and p2:
    528      1.1  mrg    ** p1->m.gcda->f checksum matches p2->m.gcda->f: simple merge.
    529      1.1  mrg    ** p1->m.gcda->f checksum does not matches p2->m.gcda->f: keep
    530      1.1  mrg       p2->m.gcda->f and
    531      1.1  mrg       drop p1->m.gcda->f. A warning is emitted.  */
    532      1.1  mrg 
    533      1.1  mrg /* Add INFO2's counter to INFO1, multiplying by weight W.  */
    534      1.1  mrg 
    535      1.1  mrg static int
    536      1.1  mrg gcov_merge (struct gcov_info *info1, struct gcov_info *info2, int w)
    537      1.1  mrg {
    538      1.1  mrg   unsigned f_ix;
    539      1.1  mrg   unsigned n_functions = info1->n_functions;
    540      1.1  mrg   int has_mismatch = 0;
    541      1.1  mrg 
    542      1.1  mrg   gcc_assert (info2->n_functions == n_functions);
    543      1.1  mrg   for (f_ix = 0; f_ix < n_functions; f_ix++)
    544      1.1  mrg     {
    545      1.1  mrg       unsigned t_ix;
    546      1.1  mrg       const struct gcov_fn_info *gfi_ptr1 = info1->functions[f_ix];
    547      1.1  mrg       const struct gcov_fn_info *gfi_ptr2 = info2->functions[f_ix];
    548      1.1  mrg       const struct gcov_ctr_info *ci_ptr1, *ci_ptr2;
    549      1.1  mrg 
    550      1.1  mrg       if (!gfi_ptr1 || gfi_ptr1->key != info1)
    551      1.1  mrg         continue;
    552      1.1  mrg       if (!gfi_ptr2 || gfi_ptr2->key != info2)
    553      1.1  mrg         continue;
    554      1.1  mrg 
    555      1.1  mrg       if (gfi_ptr1->cfg_checksum != gfi_ptr2->cfg_checksum)
    556      1.1  mrg         {
    557      1.1  mrg           fnotice (stderr, "in %s, cfg_checksum mismatch, skipping\n",
    558      1.1  mrg                   info1->filename);
    559      1.1  mrg           has_mismatch = 1;
    560      1.1  mrg           continue;
    561      1.1  mrg         }
    562      1.1  mrg       ci_ptr1 = gfi_ptr1->ctrs;
    563      1.1  mrg       ci_ptr2 = gfi_ptr2->ctrs;
    564      1.1  mrg       for (t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++)
    565      1.1  mrg         {
    566      1.1  mrg           gcov_merge_fn merge1 = info1->merge[t_ix];
    567      1.1  mrg           gcov_merge_fn merge2 = info2->merge[t_ix];
    568      1.1  mrg 
    569      1.1  mrg           gcc_assert (merge1 == merge2);
    570      1.1  mrg           if (!merge1)
    571      1.1  mrg             continue;
    572      1.1  mrg           gcc_assert (ci_ptr1->num == ci_ptr2->num);
    573      1.1  mrg           merge_wrapper (merge1, ci_ptr1->values, ci_ptr1->num, ci_ptr2->values, w);
    574      1.1  mrg           ci_ptr1++;
    575      1.1  mrg           ci_ptr2++;
    576      1.1  mrg         }
    577      1.1  mrg     }
    578      1.1  mrg 
    579      1.1  mrg   return has_mismatch;
    580      1.1  mrg }
    581      1.1  mrg 
    582      1.1  mrg /* Find and return the match gcov_info object for INFO from ARRAY.
    583      1.1  mrg    SIZE is the length of ARRAY.
    584      1.1  mrg    Return NULL if there is no match.  */
    585      1.1  mrg 
    586      1.1  mrg static struct gcov_info *
    587      1.1  mrg find_match_gcov_info (struct gcov_info **array, int size,
    588      1.1  mrg 		      struct gcov_info *info)
    589      1.1  mrg {
    590      1.1  mrg   struct gcov_info *gi_ptr;
    591      1.1  mrg   struct gcov_info *ret = NULL;
    592      1.1  mrg   int i;
    593      1.1  mrg 
    594      1.1  mrg   for (i = 0; i < size; i++)
    595      1.1  mrg     {
    596      1.1  mrg       gi_ptr = array[i];
    597      1.1  mrg       if (gi_ptr == 0)
    598      1.1  mrg         continue;
    599      1.1  mrg       if (!strcmp (gi_ptr->filename, info->filename))
    600      1.1  mrg         {
    601      1.1  mrg           ret = gi_ptr;
    602      1.1  mrg           array[i] = 0;
    603      1.1  mrg           break;
    604      1.1  mrg         }
    605      1.1  mrg     }
    606      1.1  mrg 
    607      1.1  mrg   if (ret && ret->n_functions != info->n_functions)
    608      1.1  mrg     {
    609      1.1  mrg       fnotice (stderr, "mismatched profiles in %s (%d functions"
    610      1.1  mrg                        " vs %d functions)\n",
    611      1.1  mrg                        ret->filename,
    612      1.1  mrg                        ret->n_functions,
    613      1.1  mrg                        info->n_functions);
    614      1.1  mrg       ret = NULL;
    615      1.1  mrg     }
    616      1.1  mrg   return ret;
    617      1.1  mrg }
    618      1.1  mrg 
    619      1.1  mrg /* Merge the list of gcov_info objects from SRC_PROFILE to TGT_PROFILE.
    620      1.1  mrg    Return 0 on success: without mismatch.
    621      1.1  mrg    Reutrn 1 on error.  */
    622      1.1  mrg 
    623      1.1  mrg int
    624      1.1  mrg gcov_profile_merge (struct gcov_info *tgt_profile, struct gcov_info *src_profile,
    625      1.1  mrg                     int w1, int w2)
    626      1.1  mrg {
    627      1.1  mrg   struct gcov_info *gi_ptr;
    628      1.1  mrg   struct gcov_info **tgt_infos;
    629      1.1  mrg   struct gcov_info *tgt_tail;
    630      1.1  mrg   struct gcov_info **in_src_not_tgt;
    631      1.1  mrg   unsigned tgt_cnt = 0, src_cnt = 0;
    632      1.1  mrg   unsigned unmatch_info_cnt = 0;
    633      1.1  mrg   unsigned int i;
    634      1.1  mrg 
    635      1.1  mrg   for (gi_ptr = tgt_profile; gi_ptr; gi_ptr = gi_ptr->next)
    636      1.1  mrg     tgt_cnt++;
    637      1.1  mrg   for (gi_ptr = src_profile; gi_ptr; gi_ptr = gi_ptr->next)
    638      1.1  mrg     src_cnt++;
    639      1.1  mrg   tgt_infos = (struct gcov_info **) xmalloc (sizeof (struct gcov_info *)
    640      1.1  mrg                  * tgt_cnt);
    641      1.1  mrg   gcc_assert (tgt_infos);
    642      1.1  mrg   in_src_not_tgt = (struct gcov_info **) xmalloc (sizeof (struct gcov_info *)
    643      1.1  mrg                      * src_cnt);
    644      1.1  mrg   gcc_assert (in_src_not_tgt);
    645      1.1  mrg 
    646      1.1  mrg   for (gi_ptr = tgt_profile, i = 0; gi_ptr; gi_ptr = gi_ptr->next, i++)
    647      1.1  mrg     tgt_infos[i] = gi_ptr;
    648      1.1  mrg 
    649      1.1  mrg   tgt_tail = tgt_infos[tgt_cnt - 1];
    650      1.1  mrg 
    651      1.1  mrg   /* First pass on tgt_profile, we multiply w1 to all counters.  */
    652      1.1  mrg   if (w1 > 1)
    653      1.1  mrg     {
    654      1.1  mrg        for (i = 0; i < tgt_cnt; i++)
    655      1.1  mrg          gcov_merge (tgt_infos[i], tgt_infos[i], w1-1);
    656      1.1  mrg     }
    657      1.1  mrg 
    658      1.1  mrg   /* Second pass, add src_profile to the tgt_profile.  */
    659      1.1  mrg   for (gi_ptr = src_profile; gi_ptr; gi_ptr = gi_ptr->next)
    660      1.1  mrg     {
    661      1.1  mrg       struct gcov_info *gi_ptr1;
    662      1.1  mrg 
    663      1.1  mrg       gi_ptr1 = find_match_gcov_info (tgt_infos, tgt_cnt, gi_ptr);
    664      1.1  mrg       if (gi_ptr1 == NULL)
    665      1.1  mrg         {
    666      1.1  mrg           in_src_not_tgt[unmatch_info_cnt++] = gi_ptr;
    667      1.1  mrg           continue;
    668      1.1  mrg         }
    669      1.1  mrg       gcov_merge (gi_ptr1, gi_ptr, w2);
    670      1.1  mrg     }
    671      1.1  mrg 
    672      1.1  mrg   /* For modules in src but not in tgt. We adjust the counter and append.  */
    673      1.1  mrg   for (i = 0; i < unmatch_info_cnt; i++)
    674      1.1  mrg     {
    675      1.1  mrg       gi_ptr = in_src_not_tgt[i];
    676      1.1  mrg       gcov_merge (gi_ptr, gi_ptr, w2 - 1);
    677  1.1.1.3  mrg       gi_ptr->next = NULL;
    678      1.1  mrg       tgt_tail->next = gi_ptr;
    679      1.1  mrg       tgt_tail = gi_ptr;
    680      1.1  mrg     }
    681      1.1  mrg 
    682  1.1.1.6  mrg   free (in_src_not_tgt);
    683  1.1.1.6  mrg   free (tgt_infos);
    684  1.1.1.6  mrg 
    685      1.1  mrg   return 0;
    686      1.1  mrg }
    687      1.1  mrg 
    688      1.1  mrg typedef gcov_type (*counter_op_fn) (gcov_type, void*, void*);
    689      1.1  mrg 
    690      1.1  mrg /* Performing FN upon arc counters.  */
    691      1.1  mrg 
    692      1.1  mrg static void
    693      1.1  mrg __gcov_add_counter_op (gcov_type *counters, unsigned n_counters,
    694      1.1  mrg                        counter_op_fn fn, void *data1, void *data2)
    695      1.1  mrg {
    696      1.1  mrg   for (; n_counters; counters++, n_counters--)
    697      1.1  mrg     {
    698      1.1  mrg       gcov_type val = *counters;
    699      1.1  mrg       *counters = fn(val, data1, data2);
    700      1.1  mrg     }
    701      1.1  mrg }
    702      1.1  mrg 
    703      1.1  mrg /* Performing FN upon ior counters.  */
    704      1.1  mrg 
    705      1.1  mrg static void
    706      1.1  mrg __gcov_ior_counter_op (gcov_type *counters ATTRIBUTE_UNUSED,
    707      1.1  mrg                        unsigned n_counters ATTRIBUTE_UNUSED,
    708      1.1  mrg                        counter_op_fn fn ATTRIBUTE_UNUSED,
    709      1.1  mrg                        void *data1 ATTRIBUTE_UNUSED,
    710      1.1  mrg                        void *data2 ATTRIBUTE_UNUSED)
    711      1.1  mrg {
    712      1.1  mrg   /* Do nothing.  */
    713      1.1  mrg }
    714      1.1  mrg 
    715      1.1  mrg /* Performing FN upon time-profile counters.  */
    716      1.1  mrg 
    717      1.1  mrg static void
    718      1.1  mrg __gcov_time_profile_counter_op (gcov_type *counters ATTRIBUTE_UNUSED,
    719      1.1  mrg                                 unsigned n_counters ATTRIBUTE_UNUSED,
    720      1.1  mrg                                 counter_op_fn fn ATTRIBUTE_UNUSED,
    721      1.1  mrg                                 void *data1 ATTRIBUTE_UNUSED,
    722      1.1  mrg                                 void *data2 ATTRIBUTE_UNUSED)
    723      1.1  mrg {
    724      1.1  mrg   /* Do nothing.  */
    725      1.1  mrg }
    726      1.1  mrg 
    727  1.1.1.6  mrg /* Performing FN upon TOP N counters.  */
    728      1.1  mrg 
    729      1.1  mrg static void
    730  1.1.1.6  mrg __gcov_topn_counter_op (gcov_type *counters, unsigned n_counters,
    731  1.1.1.6  mrg 			counter_op_fn fn, void *data1, void *data2)
    732      1.1  mrg {
    733      1.1  mrg   unsigned i, n_measures;
    734      1.1  mrg 
    735      1.1  mrg   gcc_assert (!(n_counters % 3));
    736      1.1  mrg   n_measures = n_counters / 3;
    737      1.1  mrg   for (i = 0; i < n_measures; i++, counters += 3)
    738      1.1  mrg     {
    739      1.1  mrg       counters[1] = fn (counters[1], data1, data2);
    740      1.1  mrg       counters[2] = fn (counters[2], data1, data2);
    741      1.1  mrg     }
    742      1.1  mrg }
    743      1.1  mrg 
    744      1.1  mrg /* Scaling the counter value V by multiplying *(float*) DATA1.  */
    745      1.1  mrg 
    746      1.1  mrg static gcov_type
    747      1.1  mrg fp_scale (gcov_type v, void *data1, void *data2 ATTRIBUTE_UNUSED)
    748      1.1  mrg {
    749      1.1  mrg   float f = *(float *) data1;
    750      1.1  mrg   return (gcov_type) (v * f);
    751      1.1  mrg }
    752      1.1  mrg 
    753      1.1  mrg /* Scaling the counter value V by multiplying DATA2/DATA1.  */
    754      1.1  mrg 
    755      1.1  mrg static gcov_type
    756      1.1  mrg int_scale (gcov_type v, void *data1, void *data2)
    757      1.1  mrg {
    758      1.1  mrg   int n = *(int *) data1;
    759      1.1  mrg   int d = *(int *) data2;
    760      1.1  mrg   return (gcov_type) ( RDIV (v,d) * n);
    761      1.1  mrg }
    762      1.1  mrg 
    763      1.1  mrg /* Type of function used to process counters.  */
    764      1.1  mrg typedef void (*gcov_counter_fn) (gcov_type *, gcov_unsigned_t,
    765      1.1  mrg                           counter_op_fn, void *, void *);
    766      1.1  mrg 
    767      1.1  mrg /* Function array to process profile counters.  */
    768      1.1  mrg #define DEF_GCOV_COUNTER(COUNTER, NAME, FN_TYPE) \
    769      1.1  mrg   __gcov ## FN_TYPE ## _counter_op,
    770      1.1  mrg static gcov_counter_fn ctr_functions[GCOV_COUNTERS] = {
    771      1.1  mrg #include "gcov-counter.def"
    772      1.1  mrg };
    773      1.1  mrg #undef DEF_GCOV_COUNTER
    774      1.1  mrg 
    775      1.1  mrg /* Driver for scaling profile counters.  */
    776      1.1  mrg 
    777      1.1  mrg int
    778      1.1  mrg gcov_profile_scale (struct gcov_info *profile, float scale_factor, int n, int d)
    779      1.1  mrg {
    780      1.1  mrg   struct gcov_info *gi_ptr;
    781      1.1  mrg   unsigned f_ix;
    782      1.1  mrg 
    783      1.1  mrg   if (verbose)
    784      1.1  mrg     fnotice (stdout, "scale_factor is %f or %d/%d\n", scale_factor, n, d);
    785      1.1  mrg 
    786      1.1  mrg   /* Scaling the counters.  */
    787      1.1  mrg   for (gi_ptr = profile; gi_ptr; gi_ptr = gi_ptr->next)
    788      1.1  mrg     for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++)
    789      1.1  mrg       {
    790      1.1  mrg         unsigned t_ix;
    791      1.1  mrg         const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix];
    792      1.1  mrg         const struct gcov_ctr_info *ci_ptr;
    793      1.1  mrg 
    794      1.1  mrg         if (!gfi_ptr || gfi_ptr->key != gi_ptr)
    795      1.1  mrg           continue;
    796      1.1  mrg 
    797      1.1  mrg         ci_ptr = gfi_ptr->ctrs;
    798      1.1  mrg         for (t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++)
    799      1.1  mrg           {
    800      1.1  mrg             gcov_merge_fn merge = gi_ptr->merge[t_ix];
    801      1.1  mrg 
    802      1.1  mrg             if (!merge)
    803      1.1  mrg               continue;
    804      1.1  mrg             if (d == 0)
    805      1.1  mrg               (*ctr_functions[t_ix]) (ci_ptr->values, ci_ptr->num,
    806      1.1  mrg                                       fp_scale, &scale_factor, NULL);
    807      1.1  mrg             else
    808      1.1  mrg               (*ctr_functions[t_ix]) (ci_ptr->values, ci_ptr->num,
    809      1.1  mrg                                       int_scale, &n, &d);
    810      1.1  mrg             ci_ptr++;
    811      1.1  mrg           }
    812      1.1  mrg       }
    813      1.1  mrg 
    814      1.1  mrg   return 0;
    815      1.1  mrg }
    816      1.1  mrg 
    817      1.1  mrg /* Driver to normalize profile counters.  */
    818      1.1  mrg 
    819      1.1  mrg int
    820      1.1  mrg gcov_profile_normalize (struct gcov_info *profile, gcov_type max_val)
    821      1.1  mrg {
    822      1.1  mrg   struct gcov_info *gi_ptr;
    823      1.1  mrg   gcov_type curr_max_val = 0;
    824      1.1  mrg   unsigned f_ix;
    825      1.1  mrg   unsigned int i;
    826      1.1  mrg   float scale_factor;
    827      1.1  mrg 
    828      1.1  mrg   /* Find the largest count value.  */
    829      1.1  mrg   for (gi_ptr = profile; gi_ptr; gi_ptr = gi_ptr->next)
    830      1.1  mrg     for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++)
    831      1.1  mrg       {
    832      1.1  mrg         unsigned t_ix;
    833      1.1  mrg         const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix];
    834      1.1  mrg         const struct gcov_ctr_info *ci_ptr;
    835      1.1  mrg 
    836      1.1  mrg         if (!gfi_ptr || gfi_ptr->key != gi_ptr)
    837      1.1  mrg           continue;
    838      1.1  mrg 
    839      1.1  mrg         ci_ptr = gfi_ptr->ctrs;
    840      1.1  mrg         for (t_ix = 0; t_ix < 1; t_ix++)
    841      1.1  mrg           {
    842      1.1  mrg             for (i = 0; i < ci_ptr->num; i++)
    843      1.1  mrg               if (ci_ptr->values[i] > curr_max_val)
    844      1.1  mrg                 curr_max_val = ci_ptr->values[i];
    845      1.1  mrg             ci_ptr++;
    846      1.1  mrg           }
    847      1.1  mrg       }
    848      1.1  mrg 
    849      1.1  mrg   scale_factor = (float)max_val / curr_max_val;
    850      1.1  mrg   if (verbose)
    851  1.1.1.2  mrg     fnotice (stdout, "max_val is %" PRId64 "\n", curr_max_val);
    852      1.1  mrg 
    853      1.1  mrg   return gcov_profile_scale (profile, scale_factor, 0, 0);
    854      1.1  mrg }
    855      1.1  mrg 
    856      1.1  mrg /* The following variables are defined in gcc/gcov-tool.c.  */
    857      1.1  mrg extern int overlap_func_level;
    858      1.1  mrg extern int overlap_obj_level;
    859      1.1  mrg extern int overlap_hot_only;
    860      1.1  mrg extern int overlap_use_fullname;
    861      1.1  mrg extern double overlap_hot_threshold;
    862      1.1  mrg 
    863      1.1  mrg /* Compute the overlap score of two values. The score is defined as:
    864      1.1  mrg     min (V1/SUM_1, V2/SUM_2)  */
    865      1.1  mrg 
    866      1.1  mrg static double
    867      1.1  mrg calculate_2_entries (const unsigned long v1, const unsigned long v2,
    868      1.1  mrg                      const double sum_1, const double sum_2)
    869      1.1  mrg {
    870      1.1  mrg   double val1 = (sum_1 == 0.0 ? 0.0 : v1/sum_1);
    871      1.1  mrg   double val2 = (sum_2 == 0.0 ? 0.0 : v2/sum_2);
    872      1.1  mrg 
    873      1.1  mrg   if (val2 < val1)
    874      1.1  mrg     val1 = val2;
    875      1.1  mrg 
    876      1.1  mrg   return val1;
    877      1.1  mrg }
    878      1.1  mrg 
    879      1.1  mrg /*  Compute the overlap score between GCOV_INFO1 and GCOV_INFO2.
    880      1.1  mrg     This function also updates cumulative score CUM_1_RESULT and
    881      1.1  mrg     CUM_2_RESULT.  */
    882      1.1  mrg 
    883      1.1  mrg static double
    884      1.1  mrg compute_one_gcov (const struct gcov_info *gcov_info1,
    885      1.1  mrg                   const struct gcov_info *gcov_info2,
    886      1.1  mrg                   const double sum_1, const double sum_2,
    887      1.1  mrg                   double *cum_1_result, double *cum_2_result)
    888      1.1  mrg {
    889      1.1  mrg   unsigned f_ix;
    890      1.1  mrg   double ret = 0;
    891      1.1  mrg   double cum_1 = 0, cum_2 = 0;
    892      1.1  mrg   const struct gcov_info *gcov_info = 0;
    893      1.1  mrg   double *cum_p;
    894      1.1  mrg   double sum;
    895      1.1  mrg 
    896      1.1  mrg   gcc_assert (gcov_info1 || gcov_info2);
    897      1.1  mrg   if (!gcov_info1)
    898      1.1  mrg     {
    899      1.1  mrg       gcov_info = gcov_info2;
    900      1.1  mrg       cum_p = cum_2_result;
    901      1.1  mrg       sum = sum_2;
    902      1.1  mrg       *cum_1_result = 0;
    903      1.1  mrg     } else
    904      1.1  mrg   if (!gcov_info2)
    905      1.1  mrg     {
    906      1.1  mrg       gcov_info = gcov_info1;
    907      1.1  mrg       cum_p = cum_1_result;
    908      1.1  mrg       sum = sum_1;
    909      1.1  mrg       *cum_2_result = 0;
    910      1.1  mrg     }
    911      1.1  mrg 
    912      1.1  mrg   if (gcov_info)
    913      1.1  mrg   {
    914      1.1  mrg     for (f_ix = 0; f_ix < gcov_info->n_functions; f_ix++)
    915      1.1  mrg       {
    916      1.1  mrg         const struct gcov_fn_info *gfi_ptr = gcov_info->functions[f_ix];
    917      1.1  mrg         if (!gfi_ptr || gfi_ptr->key != gcov_info)
    918      1.1  mrg           continue;
    919      1.1  mrg         const struct gcov_ctr_info *ci_ptr = gfi_ptr->ctrs;
    920  1.1.1.5  mrg 	unsigned c_num;
    921  1.1.1.5  mrg 	for (c_num = 0; c_num < ci_ptr->num; c_num++)
    922  1.1.1.5  mrg 	  cum_1 += ci_ptr->values[c_num] / sum;
    923      1.1  mrg       }
    924      1.1  mrg     *cum_p = cum_1;
    925      1.1  mrg     return 0.0;
    926      1.1  mrg   }
    927      1.1  mrg 
    928      1.1  mrg   for (f_ix = 0; f_ix < gcov_info1->n_functions; f_ix++)
    929      1.1  mrg     {
    930      1.1  mrg       double func_cum_1 = 0.0;
    931      1.1  mrg       double func_cum_2 = 0.0;
    932      1.1  mrg       double func_val = 0.0;
    933      1.1  mrg       int nonzero = 0;
    934      1.1  mrg       int hot = 0;
    935      1.1  mrg       const struct gcov_fn_info *gfi_ptr1 = gcov_info1->functions[f_ix];
    936      1.1  mrg       const struct gcov_fn_info *gfi_ptr2 = gcov_info2->functions[f_ix];
    937      1.1  mrg 
    938      1.1  mrg       if (!gfi_ptr1 || gfi_ptr1->key != gcov_info1)
    939      1.1  mrg         continue;
    940      1.1  mrg       if (!gfi_ptr2 || gfi_ptr2->key != gcov_info2)
    941      1.1  mrg         continue;
    942      1.1  mrg 
    943      1.1  mrg       const struct gcov_ctr_info *ci_ptr1 = gfi_ptr1->ctrs;
    944      1.1  mrg       const struct gcov_ctr_info *ci_ptr2 = gfi_ptr2->ctrs;
    945  1.1.1.5  mrg       unsigned c_num;
    946  1.1.1.5  mrg       for (c_num = 0; c_num < ci_ptr1->num; c_num++)
    947  1.1.1.5  mrg 	{
    948  1.1.1.5  mrg 	  if (ci_ptr1->values[c_num] | ci_ptr2->values[c_num])
    949  1.1.1.5  mrg 	    {
    950  1.1.1.5  mrg 	      func_val += calculate_2_entries (ci_ptr1->values[c_num],
    951  1.1.1.5  mrg 					       ci_ptr2->values[c_num],
    952  1.1.1.5  mrg 					       sum_1, sum_2);
    953  1.1.1.5  mrg 
    954  1.1.1.5  mrg 	      func_cum_1 += ci_ptr1->values[c_num] / sum_1;
    955  1.1.1.5  mrg 	      func_cum_2 += ci_ptr2->values[c_num] / sum_2;
    956  1.1.1.5  mrg 	      nonzero = 1;
    957  1.1.1.5  mrg 	      if (ci_ptr1->values[c_num] / sum_1 >= overlap_hot_threshold
    958  1.1.1.5  mrg 		  || ci_ptr2->values[c_num] / sum_2 >= overlap_hot_threshold)
    959  1.1.1.5  mrg 		hot = 1;
    960  1.1.1.5  mrg 	    }
    961  1.1.1.5  mrg 	}
    962      1.1  mrg 
    963      1.1  mrg       ret += func_val;
    964      1.1  mrg       cum_1 += func_cum_1;
    965      1.1  mrg       cum_2 += func_cum_2;
    966      1.1  mrg       if (overlap_func_level && nonzero && (!overlap_hot_only || hot))
    967      1.1  mrg         {
    968      1.1  mrg           printf("   \tfunc_id=%10d \toverlap =%6.5f%% (%5.5f%% %5.5f%%)\n",
    969      1.1  mrg                  gfi_ptr1->ident, func_val*100, func_cum_1*100, func_cum_2*100);
    970      1.1  mrg         }
    971      1.1  mrg     }
    972      1.1  mrg   *cum_1_result = cum_1;
    973      1.1  mrg   *cum_2_result = cum_2;
    974      1.1  mrg   return ret;
    975      1.1  mrg }
    976      1.1  mrg 
    977      1.1  mrg /* Test if all counter values in this GCOV_INFO are cold.
    978      1.1  mrg    "Cold" is defined as the counter value being less than
    979      1.1  mrg    or equal to THRESHOLD.  */
    980      1.1  mrg 
    981      1.1  mrg static bool
    982      1.1  mrg gcov_info_count_all_cold (const struct gcov_info *gcov_info,
    983      1.1  mrg                           gcov_type threshold)
    984      1.1  mrg {
    985      1.1  mrg   unsigned f_ix;
    986      1.1  mrg 
    987      1.1  mrg   for (f_ix = 0; f_ix < gcov_info->n_functions; f_ix++)
    988      1.1  mrg     {
    989      1.1  mrg       const struct gcov_fn_info *gfi_ptr = gcov_info->functions[f_ix];
    990      1.1  mrg 
    991      1.1  mrg       if (!gfi_ptr || gfi_ptr->key != gcov_info)
    992      1.1  mrg         continue;
    993      1.1  mrg       const struct gcov_ctr_info *ci_ptr = gfi_ptr->ctrs;
    994  1.1.1.5  mrg       for (unsigned c_num = 0; c_num < ci_ptr->num; c_num++)
    995  1.1.1.5  mrg 	if (ci_ptr->values[c_num] > threshold)
    996  1.1.1.5  mrg 	  return false;
    997      1.1  mrg     }
    998      1.1  mrg 
    999      1.1  mrg   return true;
   1000      1.1  mrg }
   1001      1.1  mrg 
   1002      1.1  mrg /* Test if all counter values in this GCOV_INFO are 0.  */
   1003      1.1  mrg 
   1004      1.1  mrg static bool
   1005      1.1  mrg gcov_info_count_all_zero (const struct gcov_info *gcov_info)
   1006      1.1  mrg {
   1007      1.1  mrg   return gcov_info_count_all_cold (gcov_info, 0);
   1008      1.1  mrg }
   1009      1.1  mrg 
   1010      1.1  mrg /* A pair of matched GCOV_INFO.
   1011      1.1  mrg    The flag is a bitvector:
   1012      1.1  mrg      b0: obj1's all counts are 0;
   1013      1.1  mrg      b1: obj1's all counts are cold (but no 0);
   1014      1.1  mrg      b2: obj1 is hot;
   1015      1.1  mrg      b3: no obj1 to match obj2;
   1016      1.1  mrg      b4: obj2's all counts are 0;
   1017      1.1  mrg      b5: obj2's all counts are cold (but no 0);
   1018      1.1  mrg      b6: obj2 is hot;
   1019      1.1  mrg      b7: no obj2 to match obj1;
   1020      1.1  mrg  */
   1021      1.1  mrg struct overlap_t {
   1022      1.1  mrg    const struct gcov_info *obj1;
   1023      1.1  mrg    const struct gcov_info *obj2;
   1024      1.1  mrg    char flag;
   1025      1.1  mrg };
   1026      1.1  mrg 
   1027      1.1  mrg #define FLAG_BOTH_ZERO(flag) ((flag & 0x1) && (flag & 0x10))
   1028      1.1  mrg #define FLAG_BOTH_COLD(flag) ((flag & 0x2) && (flag & 0x20))
   1029      1.1  mrg #define FLAG_ONE_HOT(flag) ((flag & 0x4) || (flag & 0x40))
   1030      1.1  mrg 
   1031      1.1  mrg /* Cumlative overlap dscore for profile1 and profile2.  */
   1032      1.1  mrg static double overlap_sum_1, overlap_sum_2;
   1033      1.1  mrg 
   1034      1.1  mrg /* The number of gcda files in the profiles.  */
   1035      1.1  mrg static unsigned gcda_files[2];
   1036      1.1  mrg 
   1037      1.1  mrg /* The number of unique gcda files in the profiles
   1038      1.1  mrg    (not existing in the other profile).  */
   1039      1.1  mrg static unsigned unique_gcda_files[2];
   1040      1.1  mrg 
   1041      1.1  mrg /* The number of gcda files that all counter values are 0.  */
   1042      1.1  mrg static unsigned zero_gcda_files[2];
   1043      1.1  mrg 
   1044      1.1  mrg /* The number of gcda files that all counter values are cold (but not 0).  */
   1045      1.1  mrg static unsigned cold_gcda_files[2];
   1046      1.1  mrg 
   1047      1.1  mrg /* The number of gcda files that includes hot counter values.  */
   1048      1.1  mrg static unsigned hot_gcda_files[2];
   1049      1.1  mrg 
   1050      1.1  mrg /* The number of gcda files with hot count value in either profiles.  */
   1051      1.1  mrg static unsigned both_hot_cnt;
   1052      1.1  mrg 
   1053      1.1  mrg /* The number of gcda files with all counts cold (but not 0) in
   1054      1.1  mrg    both profiles. */
   1055      1.1  mrg static unsigned both_cold_cnt;
   1056      1.1  mrg 
   1057      1.1  mrg /* The number of gcda files with all counts 0 in both profiles.  */
   1058      1.1  mrg static unsigned both_zero_cnt;
   1059      1.1  mrg 
   1060      1.1  mrg /* Extract the basename of the filename NAME.  */
   1061      1.1  mrg 
   1062      1.1  mrg static char *
   1063      1.1  mrg extract_file_basename (const char *name)
   1064      1.1  mrg {
   1065      1.1  mrg   char *str;
   1066      1.1  mrg   int len = 0;
   1067      1.1  mrg   char *path = xstrdup (name);
   1068      1.1  mrg   char sep_str[2];
   1069      1.1  mrg 
   1070      1.1  mrg   sep_str[0] = DIR_SEPARATOR;
   1071      1.1  mrg   sep_str[1] = 0;
   1072      1.1  mrg   str = strstr(path, sep_str);
   1073      1.1  mrg   do{
   1074      1.1  mrg       len = strlen(str) + 1;
   1075      1.1  mrg       path = &path[strlen(path) - len + 2];
   1076      1.1  mrg       str = strstr(path, sep_str);
   1077      1.1  mrg   } while(str);
   1078      1.1  mrg 
   1079      1.1  mrg   return path;
   1080      1.1  mrg }
   1081      1.1  mrg 
   1082      1.1  mrg /* Utility function to get the filename.  */
   1083      1.1  mrg 
   1084      1.1  mrg static const char *
   1085      1.1  mrg get_file_basename (const char *name)
   1086      1.1  mrg {
   1087      1.1  mrg   if (overlap_use_fullname)
   1088      1.1  mrg     return name;
   1089      1.1  mrg   return extract_file_basename (name);
   1090      1.1  mrg }
   1091      1.1  mrg 
   1092      1.1  mrg /* A utility function to set the flag for the gcda files.  */
   1093      1.1  mrg 
   1094      1.1  mrg static void
   1095      1.1  mrg set_flag (struct overlap_t *e)
   1096      1.1  mrg {
   1097      1.1  mrg   char flag = 0;
   1098      1.1  mrg 
   1099      1.1  mrg   if (!e->obj1)
   1100      1.1  mrg     {
   1101      1.1  mrg       unique_gcda_files[1]++;
   1102      1.1  mrg       flag = 0x8;
   1103      1.1  mrg     }
   1104      1.1  mrg   else
   1105      1.1  mrg     {
   1106      1.1  mrg       gcda_files[0]++;
   1107      1.1  mrg       if (gcov_info_count_all_zero (e->obj1))
   1108      1.1  mrg         {
   1109      1.1  mrg           zero_gcda_files[0]++;
   1110      1.1  mrg           flag = 0x1;
   1111      1.1  mrg         }
   1112      1.1  mrg       else
   1113      1.1  mrg       if (gcov_info_count_all_cold (e->obj1, overlap_sum_1
   1114      1.1  mrg 			      * overlap_hot_threshold))
   1115      1.1  mrg         {
   1116      1.1  mrg           cold_gcda_files[0]++;
   1117      1.1  mrg           flag = 0x2;
   1118      1.1  mrg         }
   1119      1.1  mrg       else
   1120      1.1  mrg         {
   1121      1.1  mrg           hot_gcda_files[0]++;
   1122      1.1  mrg           flag = 0x4;
   1123      1.1  mrg         }
   1124      1.1  mrg     }
   1125      1.1  mrg 
   1126      1.1  mrg   if (!e->obj2)
   1127      1.1  mrg     {
   1128      1.1  mrg       unique_gcda_files[0]++;
   1129      1.1  mrg       flag |= (0x8 << 4);
   1130      1.1  mrg     }
   1131      1.1  mrg   else
   1132      1.1  mrg     {
   1133      1.1  mrg       gcda_files[1]++;
   1134      1.1  mrg       if (gcov_info_count_all_zero (e->obj2))
   1135      1.1  mrg         {
   1136      1.1  mrg           zero_gcda_files[1]++;
   1137      1.1  mrg           flag |= (0x1 << 4);
   1138      1.1  mrg         }
   1139      1.1  mrg       else
   1140      1.1  mrg       if (gcov_info_count_all_cold (e->obj2, overlap_sum_2
   1141      1.1  mrg 			      * overlap_hot_threshold))
   1142      1.1  mrg         {
   1143      1.1  mrg           cold_gcda_files[1]++;
   1144      1.1  mrg           flag |= (0x2 << 4);
   1145      1.1  mrg         }
   1146      1.1  mrg       else
   1147      1.1  mrg         {
   1148      1.1  mrg           hot_gcda_files[1]++;
   1149      1.1  mrg           flag |= (0x4 << 4);
   1150      1.1  mrg         }
   1151      1.1  mrg     }
   1152      1.1  mrg 
   1153      1.1  mrg   gcc_assert (flag);
   1154      1.1  mrg   e->flag = flag;
   1155      1.1  mrg }
   1156      1.1  mrg 
   1157      1.1  mrg /* Test if INFO1 and INFO2 are from the matched source file.
   1158      1.1  mrg    Return 1 if they match; return 0 otherwise.  */
   1159      1.1  mrg 
   1160      1.1  mrg static int
   1161      1.1  mrg matched_gcov_info (const struct gcov_info *info1, const struct gcov_info *info2)
   1162      1.1  mrg {
   1163      1.1  mrg   /* For FDO, we have to match the name. This can be expensive.
   1164      1.1  mrg      Maybe we should use hash here.  */
   1165      1.1  mrg   if (strcmp (info1->filename, info2->filename))
   1166      1.1  mrg     return 0;
   1167      1.1  mrg 
   1168      1.1  mrg   if (info1->n_functions != info2->n_functions)
   1169      1.1  mrg     {
   1170      1.1  mrg       fnotice (stderr, "mismatched profiles in %s (%d functions"
   1171      1.1  mrg                        " vs %d functions)\n",
   1172      1.1  mrg                        info1->filename,
   1173      1.1  mrg                        info1->n_functions,
   1174      1.1  mrg                        info2->n_functions);
   1175      1.1  mrg       return 0;
   1176      1.1  mrg     }
   1177      1.1  mrg   return 1;
   1178      1.1  mrg }
   1179      1.1  mrg 
   1180      1.1  mrg /* Compute the overlap score of two profiles with the head of GCOV_LIST1 and
   1181      1.1  mrg    GCOV_LIST1. Return a number ranging from [0.0, 1.0], with 0.0 meaning no
   1182      1.1  mrg    match and 1.0 meaning a perfect match.  */
   1183      1.1  mrg 
   1184      1.1  mrg static double
   1185      1.1  mrg calculate_overlap (struct gcov_info *gcov_list1,
   1186      1.1  mrg                    struct gcov_info *gcov_list2)
   1187      1.1  mrg {
   1188      1.1  mrg   unsigned list1_cnt = 0, list2_cnt= 0, all_cnt;
   1189      1.1  mrg   unsigned int i, j;
   1190      1.1  mrg   const struct gcov_info *gi_ptr;
   1191      1.1  mrg   struct overlap_t *all_infos;
   1192      1.1  mrg 
   1193      1.1  mrg   for (gi_ptr = gcov_list1; gi_ptr; gi_ptr = gi_ptr->next)
   1194      1.1  mrg     list1_cnt++;
   1195      1.1  mrg   for (gi_ptr = gcov_list2; gi_ptr; gi_ptr = gi_ptr->next)
   1196      1.1  mrg     list2_cnt++;
   1197      1.1  mrg   all_cnt = list1_cnt + list2_cnt;
   1198      1.1  mrg   all_infos = (struct overlap_t *) xmalloc (sizeof (struct overlap_t)
   1199      1.1  mrg                * all_cnt * 2);
   1200      1.1  mrg   gcc_assert (all_infos);
   1201      1.1  mrg 
   1202      1.1  mrg   i = 0;
   1203      1.1  mrg   for (gi_ptr = gcov_list1; gi_ptr; gi_ptr = gi_ptr->next, i++)
   1204      1.1  mrg     {
   1205      1.1  mrg       all_infos[i].obj1 = gi_ptr;
   1206      1.1  mrg       all_infos[i].obj2 = 0;
   1207      1.1  mrg     }
   1208      1.1  mrg 
   1209      1.1  mrg   for (gi_ptr = gcov_list2; gi_ptr; gi_ptr = gi_ptr->next, i++)
   1210      1.1  mrg     {
   1211      1.1  mrg       all_infos[i].obj1 = 0;
   1212      1.1  mrg       all_infos[i].obj2 = gi_ptr;
   1213      1.1  mrg     }
   1214      1.1  mrg 
   1215      1.1  mrg   for (i = list1_cnt; i < all_cnt; i++)
   1216      1.1  mrg     {
   1217      1.1  mrg       if (all_infos[i].obj2 == 0)
   1218      1.1  mrg         continue;
   1219      1.1  mrg       for (j = 0; j < list1_cnt; j++)
   1220      1.1  mrg         {
   1221      1.1  mrg           if (all_infos[j].obj2 != 0)
   1222      1.1  mrg             continue;
   1223      1.1  mrg           if (matched_gcov_info (all_infos[i].obj2, all_infos[j].obj1))
   1224      1.1  mrg             {
   1225      1.1  mrg               all_infos[j].obj2 = all_infos[i].obj2;
   1226      1.1  mrg               all_infos[i].obj2 = 0;
   1227      1.1  mrg               break;
   1228      1.1  mrg             }
   1229      1.1  mrg         }
   1230      1.1  mrg     }
   1231      1.1  mrg 
   1232      1.1  mrg   for (i = 0; i < all_cnt; i++)
   1233      1.1  mrg     if (all_infos[i].obj1 || all_infos[i].obj2)
   1234      1.1  mrg       {
   1235      1.1  mrg         set_flag (all_infos + i);
   1236      1.1  mrg         if (FLAG_ONE_HOT (all_infos[i].flag))
   1237      1.1  mrg             both_hot_cnt++;
   1238      1.1  mrg         if (FLAG_BOTH_COLD(all_infos[i].flag))
   1239      1.1  mrg             both_cold_cnt++;
   1240      1.1  mrg         if (FLAG_BOTH_ZERO(all_infos[i].flag))
   1241      1.1  mrg             both_zero_cnt++;
   1242      1.1  mrg       }
   1243      1.1  mrg 
   1244      1.1  mrg   double prg_val = 0;
   1245      1.1  mrg   double sum_val = 0;
   1246      1.1  mrg   double sum_cum_1 = 0;
   1247      1.1  mrg   double sum_cum_2 = 0;
   1248      1.1  mrg 
   1249      1.1  mrg   for (i = 0; i < all_cnt; i++)
   1250      1.1  mrg     {
   1251      1.1  mrg       double val;
   1252      1.1  mrg       double cum_1, cum_2;
   1253      1.1  mrg       const char *filename;
   1254      1.1  mrg 
   1255      1.1  mrg       if (all_infos[i].obj1 == 0 && all_infos[i].obj2 == 0)
   1256      1.1  mrg         continue;
   1257      1.1  mrg       if (FLAG_BOTH_ZERO (all_infos[i].flag))
   1258      1.1  mrg           continue;
   1259      1.1  mrg 
   1260      1.1  mrg       if (all_infos[i].obj1)
   1261      1.1  mrg         filename = get_file_basename (all_infos[i].obj1->filename);
   1262      1.1  mrg       else
   1263      1.1  mrg         filename = get_file_basename (all_infos[i].obj2->filename);
   1264      1.1  mrg 
   1265      1.1  mrg       if (overlap_func_level)
   1266      1.1  mrg         printf("\n   processing %36s:\n", filename);
   1267      1.1  mrg 
   1268      1.1  mrg       val = compute_one_gcov (all_infos[i].obj1, all_infos[i].obj2,
   1269      1.1  mrg           overlap_sum_1, overlap_sum_2, &cum_1, &cum_2);
   1270      1.1  mrg 
   1271      1.1  mrg       if (overlap_obj_level && (!overlap_hot_only || FLAG_ONE_HOT (all_infos[i].flag)))
   1272      1.1  mrg         {
   1273      1.1  mrg           printf("   obj=%36s  overlap = %6.2f%% (%5.2f%% %5.2f%%)\n",
   1274      1.1  mrg                   filename, val*100, cum_1*100, cum_2*100);
   1275      1.1  mrg           sum_val += val;
   1276      1.1  mrg           sum_cum_1 += cum_1;
   1277      1.1  mrg           sum_cum_2 += cum_2;
   1278      1.1  mrg         }
   1279      1.1  mrg 
   1280      1.1  mrg       prg_val += val;
   1281      1.1  mrg 
   1282      1.1  mrg     }
   1283      1.1  mrg 
   1284  1.1.1.6  mrg   free (all_infos);
   1285  1.1.1.6  mrg 
   1286      1.1  mrg   if (overlap_obj_level)
   1287      1.1  mrg     printf("   SUM:%36s  overlap = %6.2f%% (%5.2f%% %5.2f%%)\n",
   1288      1.1  mrg            "", sum_val*100, sum_cum_1*100, sum_cum_2*100);
   1289      1.1  mrg 
   1290      1.1  mrg   printf ("  Statistics:\n"
   1291      1.1  mrg           "                    profile1_#     profile2_#       overlap_#\n");
   1292      1.1  mrg   printf ("    gcda files:  %12u\t%12u\t%12u\n", gcda_files[0], gcda_files[1],
   1293  1.1.1.2  mrg 	  gcda_files[0]-unique_gcda_files[0]);
   1294      1.1  mrg   printf ("  unique files:  %12u\t%12u\n", unique_gcda_files[0],
   1295  1.1.1.2  mrg 	  unique_gcda_files[1]);
   1296      1.1  mrg   printf ("     hot files:  %12u\t%12u\t%12u\n", hot_gcda_files[0],
   1297  1.1.1.2  mrg 	  hot_gcda_files[1], both_hot_cnt);
   1298      1.1  mrg   printf ("    cold files:  %12u\t%12u\t%12u\n", cold_gcda_files[0],
   1299  1.1.1.2  mrg 	  cold_gcda_files[1], both_cold_cnt);
   1300      1.1  mrg   printf ("    zero files:  %12u\t%12u\t%12u\n", zero_gcda_files[0],
   1301  1.1.1.2  mrg 	  zero_gcda_files[1], both_zero_cnt);
   1302      1.1  mrg 
   1303      1.1  mrg   return prg_val;
   1304      1.1  mrg }
   1305      1.1  mrg 
   1306  1.1.1.3  mrg /* Compute the overlap score of two lists of gcov_info objects PROFILE1 and
   1307  1.1.1.3  mrg    PROFILE2.
   1308      1.1  mrg    Return 0 on success: without mismatch. Reutrn 1 on error.  */
   1309      1.1  mrg 
   1310      1.1  mrg int
   1311      1.1  mrg gcov_profile_overlap (struct gcov_info *profile1, struct gcov_info *profile2)
   1312      1.1  mrg {
   1313      1.1  mrg   double result;
   1314      1.1  mrg 
   1315      1.1  mrg   result = calculate_overlap (profile1, profile2);
   1316      1.1  mrg 
   1317      1.1  mrg   if (result > 0)
   1318      1.1  mrg     {
   1319      1.1  mrg       printf("\nProgram level overlap result is %3.2f%%\n\n", result*100);
   1320      1.1  mrg       return 0;
   1321      1.1  mrg     }
   1322      1.1  mrg   return 1;
   1323      1.1  mrg }
   1324