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