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
6This file is part of GCC.
7
8GCC is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
10Software Foundation; either version 3, or (at your option) any later
11version.
12
13GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16for more details.
17
18Under Section 7 of GPL version 3, you are granted additional
19permissions described in the GCC Runtime Library Exception, version
203.1, as published by the Free Software Foundation.
21
22You should have received a copy of the GNU General Public License and
23a copy of the GCC Runtime Library Exception along with this program;
24see 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
39extern gcov_position_t gcov_position();
40extern int gcov_is_error();
41
42/* Verbose mode for debug.  */
43static int verbose;
44
45/* Set verbose flag.  */
46void 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
59static void tag_function (unsigned, unsigned);
60static void tag_blocks (unsigned, unsigned);
61static void tag_arcs (unsigned, unsigned);
62static void tag_lines (unsigned, unsigned);
63static void tag_counters (unsigned, unsigned);
64static void tag_summary (unsigned, unsigned);
65
66/* The gcov_info for the first module.  */
67static struct gcov_info *curr_gcov_info;
68/* The gcov_info being processed.  */
69static struct gcov_info *gcov_info_head;
70/* This variable contains all the functions in current module.  */
71static struct obstack fn_info;
72/* The function being processed.  */
73static struct gcov_fn_info *curr_fn_info;
74/* The number of functions seen so far.  */
75static unsigned num_fn_info;
76/* This variable contains all the counters for current module.  */
77static int k_ctrs_mask[GCOV_COUNTERS];
78/* The kind of counters that have been seen.  */
79static struct gcov_ctr_info k_ctrs[GCOV_COUNTERS];
80/* Number of kind of counters that have been seen.  */
81static int k_ctrs_types;
82
83/* Merge functions for counters.  */
84#define DEF_GCOV_COUNTER(COUNTER, NAME, FN_TYPE) __gcov_merge ## FN_TYPE,
85static 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
92static void
93set_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
115typedef 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
124static 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
140static void
141tag_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
173static void
174tag_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
182static void
183tag_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
191static void
192tag_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
200static void
201tag_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
223static void
224tag_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
234static void
235read_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
257static struct gcov_info *
258read_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
389static int
390ftw_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
427static inline void
428read_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
437struct gcov_info *
438gcov_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.  */
473static gcov_type *gcov_value_buf;
474
475/* The number of counter values to be read by current merging.  */
476static gcov_unsigned_t gcov_value_buf_size;
477
478/* The index of counter values being read.  */
479static gcov_unsigned_t gcov_value_buf_pos;
480
481/* The weight of current merging.  */
482static unsigned gcov_merge_weight;
483
484/* Read a counter value from gcov_value_buf array.  */
485
486gcov_type
487gcov_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
498unsigned
499gcov_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
507static void
508merge_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
534static int
535gcov_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
585static struct gcov_info *
586find_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
622int
623gcov_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
683typedef gcov_type (*counter_op_fn) (gcov_type, void*, void*);
684
685/* Performing FN upon arc counters.  */
686
687static 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
700static 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
712static 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
724static 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
741static 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
758static 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
777static gcov_type
778fp_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
786static gcov_type
787int_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.  */
795typedef 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,
801static 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
808int
809gcov_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
850int
851gcov_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.  */
888extern int overlap_func_level;
889extern int overlap_obj_level;
890extern int overlap_hot_only;
891extern int overlap_use_fullname;
892extern 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
897static double
898calculate_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
916static double
917compute_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
1034static bool
1035gcov_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
1069static bool
1070gcov_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 */
1086struct 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.  */
1097static double overlap_sum_1, overlap_sum_2;
1098
1099/* sum_all for profile1 and profile2.  */
1100static gcov_type p1_sum_all, p2_sum_all;
1101
1102/* run_max for profile1 and profile2.  */
1103static gcov_type p1_run_max, p2_run_max;
1104
1105/* The number of gcda files in the profiles.  */
1106static unsigned gcda_files[2];
1107
1108/* The number of unique gcda files in the profiles
1109   (not existing in the other profile).  */
1110static unsigned unique_gcda_files[2];
1111
1112/* The number of gcda files that all counter values are 0.  */
1113static unsigned zero_gcda_files[2];
1114
1115/* The number of gcda files that all counter values are cold (but not 0).  */
1116static unsigned cold_gcda_files[2];
1117
1118/* The number of gcda files that includes hot counter values.  */
1119static unsigned hot_gcda_files[2];
1120
1121/* The number of gcda files with hot count value in either profiles.  */
1122static unsigned both_hot_cnt;
1123
1124/* The number of gcda files with all counts cold (but not 0) in
1125   both profiles. */
1126static unsigned both_cold_cnt;
1127
1128/* The number of gcda files with all counts 0 in both profiles.  */
1129static unsigned both_zero_cnt;
1130
1131/* Extract the basename of the filename NAME.  */
1132
1133static char *
1134extract_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
1155static const char *
1156get_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
1165static void
1166set_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
1231static int
1232matched_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.  */
1252extern 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
1259static double
1260calculate_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
1395int
1396gcov_profile_overlap (struct gcov_info *profile1, struct gcov_info *profile2)
1397{
1398  double result;
1399
1400  result = calculate_overlap (profile1, profile2);
1401
1402  if (result > 0)
1403    {
1404      printf("\nProgram level overlap result is %3.2f%%\n\n", result*100);
1405      return 0;
1406    }
1407  return 1;
1408}
1409