Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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@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.