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