Update soft-fp from glibc (PR libgcc/77265).
[platform/upstream/gcc.git] / 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-2016 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       gi_ptr->next = NULL;
677       tgt_tail->next = gi_ptr;
678       tgt_tail = gi_ptr;
679     }
680
681   return 0;
682 }
683
684 typedef gcov_type (*counter_op_fn) (gcov_type, void*, void*);
685
686 /* Performing FN upon arc counters.  */
687
688 static void
689 __gcov_add_counter_op (gcov_type *counters, unsigned n_counters,
690                        counter_op_fn fn, void *data1, void *data2)
691 {
692   for (; n_counters; counters++, n_counters--)
693     {
694       gcov_type val = *counters;
695       *counters = fn(val, data1, data2);
696     }
697 }
698
699 /* Performing FN upon ior counters.  */
700
701 static void
702 __gcov_ior_counter_op (gcov_type *counters ATTRIBUTE_UNUSED,
703                        unsigned n_counters ATTRIBUTE_UNUSED,
704                        counter_op_fn fn ATTRIBUTE_UNUSED,
705                        void *data1 ATTRIBUTE_UNUSED,
706                        void *data2 ATTRIBUTE_UNUSED)
707 {
708   /* Do nothing.  */
709 }
710
711 /* Performing FN upon time-profile counters.  */
712
713 static void
714 __gcov_time_profile_counter_op (gcov_type *counters ATTRIBUTE_UNUSED,
715                                 unsigned n_counters ATTRIBUTE_UNUSED,
716                                 counter_op_fn fn ATTRIBUTE_UNUSED,
717                                 void *data1 ATTRIBUTE_UNUSED,
718                                 void *data2 ATTRIBUTE_UNUSED)
719 {
720   /* Do nothing.  */
721 }
722
723 /* Performaing FN upon delta counters.  */
724
725 static void
726 __gcov_delta_counter_op (gcov_type *counters, unsigned n_counters,
727                          counter_op_fn fn, void *data1, void *data2)
728 {
729   unsigned i, n_measures;
730
731   gcc_assert (!(n_counters % 4));
732   n_measures = n_counters / 4;
733   for (i = 0; i < n_measures; i++, counters += 4)
734     {
735       counters[2] = fn (counters[2], data1, data2);
736       counters[3] = fn (counters[3], data1, data2);
737     }
738 }
739
740 /* Performing FN upon single counters.  */
741
742 static void
743 __gcov_single_counter_op (gcov_type *counters, unsigned n_counters,
744                           counter_op_fn fn, void *data1, void *data2)
745 {
746   unsigned i, n_measures;
747
748   gcc_assert (!(n_counters % 3));
749   n_measures = n_counters / 3;
750   for (i = 0; i < n_measures; i++, counters += 3)
751     {
752       counters[1] = fn (counters[1], data1, data2);
753       counters[2] = fn (counters[2], data1, data2);
754     }
755 }
756
757 /* Performing FN upon indirect-call profile counters.  */
758
759 static void
760 __gcov_icall_topn_counter_op (gcov_type *counters, unsigned n_counters,
761                               counter_op_fn fn, void *data1, void *data2)
762 {
763   unsigned i;
764
765   gcc_assert (!(n_counters % GCOV_ICALL_TOPN_NCOUNTS));
766   for (i = 0; i < n_counters; i += GCOV_ICALL_TOPN_NCOUNTS)
767     {
768       unsigned j;
769       gcov_type *value_array = &counters[i + 1];
770
771       for (j = 0; j < GCOV_ICALL_TOPN_NCOUNTS - 1; j += 2)
772         value_array[j + 1] = fn (value_array[j + 1], data1, data2);
773     }
774 }
775
776 /* Scaling the counter value V by multiplying *(float*) DATA1.  */
777
778 static gcov_type
779 fp_scale (gcov_type v, void *data1, void *data2 ATTRIBUTE_UNUSED)
780 {
781   float f = *(float *) data1;
782   return (gcov_type) (v * f);
783 }
784
785 /* Scaling the counter value V by multiplying DATA2/DATA1.  */
786
787 static gcov_type
788 int_scale (gcov_type v, void *data1, void *data2)
789 {
790   int n = *(int *) data1;
791   int d = *(int *) data2;
792   return (gcov_type) ( RDIV (v,d) * n);
793 }
794
795 /* Type of function used to process counters.  */
796 typedef void (*gcov_counter_fn) (gcov_type *, gcov_unsigned_t,
797                           counter_op_fn, void *, void *);
798
799 /* Function array to process profile counters.  */
800 #define DEF_GCOV_COUNTER(COUNTER, NAME, FN_TYPE) \
801   __gcov ## FN_TYPE ## _counter_op,
802 static gcov_counter_fn ctr_functions[GCOV_COUNTERS] = {
803 #include "gcov-counter.def"
804 };
805 #undef DEF_GCOV_COUNTER
806
807 /* Driver for scaling profile counters.  */
808
809 int
810 gcov_profile_scale (struct gcov_info *profile, float scale_factor, int n, int d)
811 {
812   struct gcov_info *gi_ptr;
813   unsigned f_ix;
814
815   if (verbose)
816     fnotice (stdout, "scale_factor is %f or %d/%d\n", scale_factor, n, d);
817
818   /* Scaling the counters.  */
819   for (gi_ptr = profile; gi_ptr; gi_ptr = gi_ptr->next)
820     for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++)
821       {
822         unsigned t_ix;
823         const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix];
824         const struct gcov_ctr_info *ci_ptr;
825
826         if (!gfi_ptr || gfi_ptr->key != gi_ptr)
827           continue;
828
829         ci_ptr = gfi_ptr->ctrs;
830         for (t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++)
831           {
832             gcov_merge_fn merge = gi_ptr->merge[t_ix];
833
834             if (!merge)
835               continue;
836             if (d == 0)
837               (*ctr_functions[t_ix]) (ci_ptr->values, ci_ptr->num,
838                                       fp_scale, &scale_factor, NULL);
839             else
840               (*ctr_functions[t_ix]) (ci_ptr->values, ci_ptr->num,
841                                       int_scale, &n, &d);
842             ci_ptr++;
843           }
844       }
845
846   return 0;
847 }
848
849 /* Driver to normalize profile counters.  */
850
851 int
852 gcov_profile_normalize (struct gcov_info *profile, gcov_type max_val)
853 {
854   struct gcov_info *gi_ptr;
855   gcov_type curr_max_val = 0;
856   unsigned f_ix;
857   unsigned int i;
858   float scale_factor;
859
860   /* Find the largest count value.  */
861   for (gi_ptr = profile; gi_ptr; gi_ptr = gi_ptr->next)
862     for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++)
863       {
864         unsigned t_ix;
865         const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix];
866         const struct gcov_ctr_info *ci_ptr;
867
868         if (!gfi_ptr || gfi_ptr->key != gi_ptr)
869           continue;
870
871         ci_ptr = gfi_ptr->ctrs;
872         for (t_ix = 0; t_ix < 1; t_ix++)
873           {
874             for (i = 0; i < ci_ptr->num; i++)
875               if (ci_ptr->values[i] > curr_max_val)
876                 curr_max_val = ci_ptr->values[i];
877             ci_ptr++;
878           }
879       }
880
881   scale_factor = (float)max_val / curr_max_val;
882   if (verbose)
883     fnotice (stdout, "max_val is %" PRId64 "\n", curr_max_val);
884
885   return gcov_profile_scale (profile, scale_factor, 0, 0);
886 }
887
888 /* The following variables are defined in gcc/gcov-tool.c.  */
889 extern int overlap_func_level;
890 extern int overlap_obj_level;
891 extern int overlap_hot_only;
892 extern int overlap_use_fullname;
893 extern double overlap_hot_threshold;
894
895 /* Compute the overlap score of two values. The score is defined as:
896     min (V1/SUM_1, V2/SUM_2)  */
897
898 static double
899 calculate_2_entries (const unsigned long v1, const unsigned long v2,
900                      const double sum_1, const double sum_2)
901 {
902   double val1 = (sum_1 == 0.0 ? 0.0 : v1/sum_1);
903   double val2 = (sum_2 == 0.0 ? 0.0 : v2/sum_2);
904
905   if (val2 < val1)
906     val1 = val2;
907
908   return val1;
909 }
910
911 /*  Compute the overlap score between GCOV_INFO1 and GCOV_INFO2.
912     SUM_1 is the sum_all for profile1 where GCOV_INFO1 belongs.
913     SUM_2 is the sum_all for profile2 where GCOV_INFO2 belongs.
914     This function also updates cumulative score CUM_1_RESULT and
915     CUM_2_RESULT.  */
916
917 static double
918 compute_one_gcov (const struct gcov_info *gcov_info1,
919                   const struct gcov_info *gcov_info2,
920                   const double sum_1, const double sum_2,
921                   double *cum_1_result, double *cum_2_result)
922 {
923   unsigned f_ix;
924   double ret = 0;
925   double cum_1 = 0, cum_2 = 0;
926   const struct gcov_info *gcov_info = 0;
927   double *cum_p;
928   double sum;
929
930   gcc_assert (gcov_info1 || gcov_info2);
931   if (!gcov_info1)
932     {
933       gcov_info = gcov_info2;
934       cum_p = cum_2_result;
935       sum = sum_2;
936       *cum_1_result = 0;
937     } else
938   if (!gcov_info2)
939     {
940       gcov_info = gcov_info1;
941       cum_p = cum_1_result;
942       sum = sum_1;
943       *cum_2_result = 0;
944     }
945
946   if (gcov_info)
947   {
948     for (f_ix = 0; f_ix < gcov_info->n_functions; f_ix++)
949       {
950         unsigned t_ix;
951         const struct gcov_fn_info *gfi_ptr = gcov_info->functions[f_ix];
952         if (!gfi_ptr || gfi_ptr->key != gcov_info)
953           continue;
954         const struct gcov_ctr_info *ci_ptr = gfi_ptr->ctrs;
955         for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++)
956           {
957             unsigned c_num;
958
959             if (!gcov_info->merge[t_ix])
960               continue;
961
962             for (c_num = 0; c_num < ci_ptr->num; c_num++)
963               {
964                 cum_1 += ci_ptr->values[c_num] / sum;
965               }
966             ci_ptr++;
967           }
968       }
969     *cum_p = cum_1;
970     return 0.0;
971   }
972
973   for (f_ix = 0; f_ix < gcov_info1->n_functions; f_ix++)
974     {
975       unsigned t_ix;
976       double func_cum_1 = 0.0;
977       double func_cum_2 = 0.0;
978       double func_val = 0.0;
979       int nonzero = 0;
980       int hot = 0;
981       const struct gcov_fn_info *gfi_ptr1 = gcov_info1->functions[f_ix];
982       const struct gcov_fn_info *gfi_ptr2 = gcov_info2->functions[f_ix];
983
984       if (!gfi_ptr1 || gfi_ptr1->key != gcov_info1)
985         continue;
986       if (!gfi_ptr2 || gfi_ptr2->key != gcov_info2)
987         continue;
988
989       const struct gcov_ctr_info *ci_ptr1 = gfi_ptr1->ctrs;
990       const struct gcov_ctr_info *ci_ptr2 = gfi_ptr2->ctrs;
991       for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++)
992         {
993           unsigned c_num;
994
995           if (!gcov_info1->merge[t_ix])
996             continue;
997
998           for (c_num = 0; c_num < ci_ptr1->num; c_num++)
999             {
1000               if (ci_ptr1->values[c_num] | ci_ptr2->values[c_num])
1001                 {
1002                   func_val += calculate_2_entries (ci_ptr1->values[c_num],
1003                                           ci_ptr2->values[c_num],
1004                                           sum_1, sum_2);
1005
1006                   func_cum_1 += ci_ptr1->values[c_num] / sum_1;
1007                   func_cum_2 += ci_ptr2->values[c_num] / sum_2;
1008                   nonzero = 1;
1009                   if (ci_ptr1->values[c_num] / sum_1 >= overlap_hot_threshold ||
1010                       ci_ptr2->values[c_num] / sum_2 >= overlap_hot_threshold)
1011                     hot = 1;
1012                 }
1013             }
1014           ci_ptr1++;
1015           ci_ptr2++;
1016         }
1017       ret += func_val;
1018       cum_1 += func_cum_1;
1019       cum_2 += func_cum_2;
1020       if (overlap_func_level && nonzero && (!overlap_hot_only || hot))
1021         {
1022           printf("   \tfunc_id=%10d \toverlap =%6.5f%% (%5.5f%% %5.5f%%)\n",
1023                  gfi_ptr1->ident, func_val*100, func_cum_1*100, func_cum_2*100);
1024         }
1025     }
1026   *cum_1_result = cum_1;
1027   *cum_2_result = cum_2;
1028   return ret;
1029 }
1030
1031 /* Test if all counter values in this GCOV_INFO are cold.
1032    "Cold" is defined as the counter value being less than
1033    or equal to THRESHOLD.  */
1034
1035 static bool
1036 gcov_info_count_all_cold (const struct gcov_info *gcov_info,
1037                           gcov_type threshold)
1038 {
1039   unsigned f_ix;
1040
1041   for (f_ix = 0; f_ix < gcov_info->n_functions; f_ix++)
1042     {
1043       unsigned t_ix;
1044       const struct gcov_fn_info *gfi_ptr = gcov_info->functions[f_ix];
1045
1046       if (!gfi_ptr || gfi_ptr->key != gcov_info)
1047         continue;
1048       const struct gcov_ctr_info *ci_ptr = gfi_ptr->ctrs;
1049       for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++)
1050         {
1051           unsigned c_num;
1052
1053           if (!gcov_info->merge[t_ix])
1054             continue;
1055
1056           for (c_num = 0; c_num < ci_ptr->num; c_num++)
1057             {
1058               if (ci_ptr->values[c_num] > threshold)
1059                 return false;
1060             }
1061           ci_ptr++;
1062         }
1063     }
1064
1065   return true;
1066 }
1067
1068 /* Test if all counter values in this GCOV_INFO are 0.  */
1069
1070 static bool
1071 gcov_info_count_all_zero (const struct gcov_info *gcov_info)
1072 {
1073   return gcov_info_count_all_cold (gcov_info, 0);
1074 }
1075
1076 /* A pair of matched GCOV_INFO.
1077    The flag is a bitvector:
1078      b0: obj1's all counts are 0;
1079      b1: obj1's all counts are cold (but no 0);
1080      b2: obj1 is hot;
1081      b3: no obj1 to match obj2;
1082      b4: obj2's all counts are 0;
1083      b5: obj2's all counts are cold (but no 0);
1084      b6: obj2 is hot;
1085      b7: no obj2 to match obj1;
1086  */
1087 struct overlap_t {
1088    const struct gcov_info *obj1;
1089    const struct gcov_info *obj2;
1090    char flag;
1091 };
1092
1093 #define FLAG_BOTH_ZERO(flag) ((flag & 0x1) && (flag & 0x10))
1094 #define FLAG_BOTH_COLD(flag) ((flag & 0x2) && (flag & 0x20))
1095 #define FLAG_ONE_HOT(flag) ((flag & 0x4) || (flag & 0x40))
1096
1097 /* Cumlative overlap dscore for profile1 and profile2.  */
1098 static double overlap_sum_1, overlap_sum_2;
1099
1100 /* sum_all for profile1 and profile2.  */
1101 static gcov_type p1_sum_all, p2_sum_all;
1102
1103 /* run_max for profile1 and profile2.  */
1104 static gcov_type p1_run_max, p2_run_max;
1105
1106 /* The number of gcda files in the profiles.  */
1107 static unsigned gcda_files[2];
1108
1109 /* The number of unique gcda files in the profiles
1110    (not existing in the other profile).  */
1111 static unsigned unique_gcda_files[2];
1112
1113 /* The number of gcda files that all counter values are 0.  */
1114 static unsigned zero_gcda_files[2];
1115
1116 /* The number of gcda files that all counter values are cold (but not 0).  */
1117 static unsigned cold_gcda_files[2];
1118
1119 /* The number of gcda files that includes hot counter values.  */
1120 static unsigned hot_gcda_files[2];
1121
1122 /* The number of gcda files with hot count value in either profiles.  */
1123 static unsigned both_hot_cnt;
1124
1125 /* The number of gcda files with all counts cold (but not 0) in
1126    both profiles. */
1127 static unsigned both_cold_cnt;
1128
1129 /* The number of gcda files with all counts 0 in both profiles.  */
1130 static unsigned both_zero_cnt;
1131
1132 /* Extract the basename of the filename NAME.  */
1133
1134 static char *
1135 extract_file_basename (const char *name)
1136 {
1137   char *str;
1138   int len = 0;
1139   char *path = xstrdup (name);
1140   char sep_str[2];
1141
1142   sep_str[0] = DIR_SEPARATOR;
1143   sep_str[1] = 0;
1144   str = strstr(path, sep_str);
1145   do{
1146       len = strlen(str) + 1;
1147       path = &path[strlen(path) - len + 2];
1148       str = strstr(path, sep_str);
1149   } while(str);
1150
1151   return path;
1152 }
1153
1154 /* Utility function to get the filename.  */
1155
1156 static const char *
1157 get_file_basename (const char *name)
1158 {
1159   if (overlap_use_fullname)
1160     return name;
1161   return extract_file_basename (name);
1162 }
1163
1164 /* A utility function to set the flag for the gcda files.  */
1165
1166 static void
1167 set_flag (struct overlap_t *e)
1168 {
1169   char flag = 0;
1170
1171   if (!e->obj1)
1172     {
1173       unique_gcda_files[1]++;
1174       flag = 0x8;
1175     }
1176   else
1177     {
1178       gcda_files[0]++;
1179       if (gcov_info_count_all_zero (e->obj1))
1180         {
1181           zero_gcda_files[0]++;
1182           flag = 0x1;
1183         }
1184       else
1185       if (gcov_info_count_all_cold (e->obj1, overlap_sum_1
1186                               * overlap_hot_threshold))
1187         {
1188           cold_gcda_files[0]++;
1189           flag = 0x2;
1190         }
1191       else
1192         {
1193           hot_gcda_files[0]++;
1194           flag = 0x4;
1195         }
1196     }
1197
1198   if (!e->obj2)
1199     {
1200       unique_gcda_files[0]++;
1201       flag |= (0x8 << 4);
1202     }
1203   else
1204     {
1205       gcda_files[1]++;
1206       if (gcov_info_count_all_zero (e->obj2))
1207         {
1208           zero_gcda_files[1]++;
1209           flag |= (0x1 << 4);
1210         }
1211       else
1212       if (gcov_info_count_all_cold (e->obj2, overlap_sum_2
1213                               * overlap_hot_threshold))
1214         {
1215           cold_gcda_files[1]++;
1216           flag |= (0x2 << 4);
1217         }
1218       else
1219         {
1220           hot_gcda_files[1]++;
1221           flag |= (0x4 << 4);
1222         }
1223     }
1224
1225   gcc_assert (flag);
1226   e->flag = flag;
1227 }
1228
1229 /* Test if INFO1 and INFO2 are from the matched source file.
1230    Return 1 if they match; return 0 otherwise.  */
1231
1232 static int
1233 matched_gcov_info (const struct gcov_info *info1, const struct gcov_info *info2)
1234 {
1235   /* For FDO, we have to match the name. This can be expensive.
1236      Maybe we should use hash here.  */
1237   if (strcmp (info1->filename, info2->filename))
1238     return 0;
1239
1240   if (info1->n_functions != info2->n_functions)
1241     {
1242       fnotice (stderr, "mismatched profiles in %s (%d functions"
1243                        " vs %d functions)\n",
1244                        info1->filename,
1245                        info1->n_functions,
1246                        info2->n_functions);
1247       return 0;
1248     }
1249   return 1;
1250 }
1251
1252 /* Defined in libgcov-driver.c.  */
1253 extern gcov_unsigned_t compute_summary (struct gcov_info *,
1254                  struct gcov_summary *, size_t *);
1255
1256 /* Compute the overlap score of two profiles with the head of GCOV_LIST1 and
1257    GCOV_LIST1. Return a number ranging from [0.0, 1.0], with 0.0 meaning no
1258    match and 1.0 meaning a perfect match.  */
1259
1260 static double
1261 calculate_overlap (struct gcov_info *gcov_list1,
1262                    struct gcov_info *gcov_list2)
1263 {
1264   struct gcov_summary this_prg;
1265   unsigned list1_cnt = 0, list2_cnt= 0, all_cnt;
1266   unsigned int i, j;
1267   size_t max_length;
1268   const struct gcov_info *gi_ptr;
1269   struct overlap_t *all_infos;
1270
1271   compute_summary (gcov_list1, &this_prg, &max_length);
1272   overlap_sum_1 = (double) (this_prg.ctrs[0].sum_all);
1273   p1_sum_all = this_prg.ctrs[0].sum_all;
1274   p1_run_max = this_prg.ctrs[0].run_max;
1275   compute_summary (gcov_list2, &this_prg, &max_length);
1276   overlap_sum_2 = (double) (this_prg.ctrs[0].sum_all);
1277   p2_sum_all = this_prg.ctrs[0].sum_all;
1278   p2_run_max = this_prg.ctrs[0].run_max;
1279
1280   for (gi_ptr = gcov_list1; gi_ptr; gi_ptr = gi_ptr->next)
1281     list1_cnt++;
1282   for (gi_ptr = gcov_list2; gi_ptr; gi_ptr = gi_ptr->next)
1283     list2_cnt++;
1284   all_cnt = list1_cnt + list2_cnt;
1285   all_infos = (struct overlap_t *) xmalloc (sizeof (struct overlap_t)
1286                * all_cnt * 2);
1287   gcc_assert (all_infos);
1288
1289   i = 0;
1290   for (gi_ptr = gcov_list1; gi_ptr; gi_ptr = gi_ptr->next, i++)
1291     {
1292       all_infos[i].obj1 = gi_ptr;
1293       all_infos[i].obj2 = 0;
1294     }
1295
1296   for (gi_ptr = gcov_list2; gi_ptr; gi_ptr = gi_ptr->next, i++)
1297     {
1298       all_infos[i].obj1 = 0;
1299       all_infos[i].obj2 = gi_ptr;
1300     }
1301
1302   for (i = list1_cnt; i < all_cnt; i++)
1303     {
1304       if (all_infos[i].obj2 == 0)
1305         continue;
1306       for (j = 0; j < list1_cnt; j++)
1307         {
1308           if (all_infos[j].obj2 != 0)
1309             continue;
1310           if (matched_gcov_info (all_infos[i].obj2, all_infos[j].obj1))
1311             {
1312               all_infos[j].obj2 = all_infos[i].obj2;
1313               all_infos[i].obj2 = 0;
1314               break;
1315             }
1316         }
1317     }
1318
1319   for (i = 0; i < all_cnt; i++)
1320     if (all_infos[i].obj1 || all_infos[i].obj2)
1321       {
1322         set_flag (all_infos + i);
1323         if (FLAG_ONE_HOT (all_infos[i].flag))
1324             both_hot_cnt++;
1325         if (FLAG_BOTH_COLD(all_infos[i].flag))
1326             both_cold_cnt++;
1327         if (FLAG_BOTH_ZERO(all_infos[i].flag))
1328             both_zero_cnt++;
1329       }
1330
1331   double prg_val = 0;
1332   double sum_val = 0;
1333   double sum_cum_1 = 0;
1334   double sum_cum_2 = 0;
1335
1336   for (i = 0; i < all_cnt; i++)
1337     {
1338       double val;
1339       double cum_1, cum_2;
1340       const char *filename;
1341
1342       if (all_infos[i].obj1 == 0 && all_infos[i].obj2 == 0)
1343         continue;
1344       if (FLAG_BOTH_ZERO (all_infos[i].flag))
1345           continue;
1346
1347       if (all_infos[i].obj1)
1348         filename = get_file_basename (all_infos[i].obj1->filename);
1349       else
1350         filename = get_file_basename (all_infos[i].obj2->filename);
1351
1352       if (overlap_func_level)
1353         printf("\n   processing %36s:\n", filename);
1354
1355       val = compute_one_gcov (all_infos[i].obj1, all_infos[i].obj2,
1356           overlap_sum_1, overlap_sum_2, &cum_1, &cum_2);
1357
1358       if (overlap_obj_level && (!overlap_hot_only || FLAG_ONE_HOT (all_infos[i].flag)))
1359         {
1360           printf("   obj=%36s  overlap = %6.2f%% (%5.2f%% %5.2f%%)\n",
1361                   filename, val*100, cum_1*100, cum_2*100);
1362           sum_val += val;
1363           sum_cum_1 += cum_1;
1364           sum_cum_2 += cum_2;
1365         }
1366
1367       prg_val += val;
1368
1369     }
1370
1371   if (overlap_obj_level)
1372     printf("   SUM:%36s  overlap = %6.2f%% (%5.2f%% %5.2f%%)\n",
1373            "", sum_val*100, sum_cum_1*100, sum_cum_2*100);
1374
1375   printf ("  Statistics:\n"
1376           "                    profile1_#     profile2_#       overlap_#\n");
1377   printf ("    gcda files:  %12u\t%12u\t%12u\n", gcda_files[0], gcda_files[1],
1378           gcda_files[0]-unique_gcda_files[0]);
1379   printf ("  unique files:  %12u\t%12u\n", unique_gcda_files[0],
1380           unique_gcda_files[1]);
1381   printf ("     hot files:  %12u\t%12u\t%12u\n", hot_gcda_files[0],
1382           hot_gcda_files[1], both_hot_cnt);
1383   printf ("    cold files:  %12u\t%12u\t%12u\n", cold_gcda_files[0],
1384           cold_gcda_files[1], both_cold_cnt);
1385   printf ("    zero files:  %12u\t%12u\t%12u\n", zero_gcda_files[0],
1386           zero_gcda_files[1], both_zero_cnt);
1387   printf ("       sum_all:  %12" PRId64 "\t%12" PRId64 "\n",
1388           p1_sum_all, p2_sum_all);
1389   printf ("       run_max:  %12" PRId64 "\t%12" PRId64 "\n",
1390           p1_run_max, p2_run_max);
1391
1392   return prg_val;
1393 }
1394
1395 /* Compute the overlap score of two lists of gcov_info objects PROFILE1 and
1396    PROFILE2.
1397    Return 0 on success: without mismatch. Reutrn 1 on error.  */
1398
1399 int
1400 gcov_profile_overlap (struct gcov_info *profile1, struct gcov_info *profile2)
1401 {
1402   double result;
1403
1404   result = calculate_overlap (profile1, profile2);
1405
1406   if (result > 0)
1407     {
1408       printf("\nProgram level overlap result is %3.2f%%\n\n", result*100);
1409       return 0;
1410     }
1411   return 1;
1412 }