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