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