Update gcc-50 to SVN version 221261
[dragonfly.git] / contrib / gcc-5.0 / libgcc / libgcov-util.c
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 }