Fix the long lasting issue of `gcov-tool overlap  xxx yyy`,
divide to 0 caused the output shows a lot of nans, another problem
is the counts in file are never acculated leads to incorrect results.

Signed-off-by: Xionghu Luo <xionghu...@tencent.com>

libgcc/ChangeLog:

        * libgcov-util.c (compute_one_gcov): Avoid divide to 0.
        (accumulate_sum_counts): New.
        (calculate_overlap): Call accumulate_sum_countes.
---
 libgcc/libgcov-util.c | 58 ++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 54 insertions(+), 4 deletions(-)

diff --git a/libgcc/libgcov-util.c b/libgcc/libgcov-util.c
index d547c103cab..26a02e66567 100644
--- a/libgcc/libgcov-util.c
+++ b/libgcc/libgcov-util.c
@@ -1072,6 +1072,8 @@ compute_one_gcov (const struct gcov_info *gcov_info1,
 
   for (f_ix = 0; f_ix < gcov_info1->n_functions; f_ix++)
     {
+      double func_1 = 0.0;
+      double func_2 = 0.0;
       double func_cum_1 = 0.0;
       double func_cum_2 = 0.0;
       double func_val = 0.0;
@@ -1096,11 +1098,15 @@ compute_one_gcov (const struct gcov_info *gcov_info1,
                                               ci_ptr2->values[c_num],
                                               sum_1, sum_2);
 
-             func_cum_1 += ci_ptr1->values[c_num] / sum_1;
-             func_cum_2 += ci_ptr2->values[c_num] / sum_2;
+             if (sum_1)
+               func_1 = ci_ptr1->values[c_num] / sum_1;
+             func_cum_1 += func_1;
+             if (sum_2)
+               func_2 = ci_ptr2->values[c_num] / sum_2;
+             func_cum_2 += func_2;
              nonzero = 1;
-             if (ci_ptr1->values[c_num] / sum_1 >= overlap_hot_threshold
-                 || ci_ptr2->values[c_num] / sum_2 >= overlap_hot_threshold)
+             if (func_1 >= overlap_hot_threshold
+                 || func_2 >= overlap_hot_threshold)
                hot = 1;
            }
        }
@@ -1322,6 +1328,47 @@ matched_gcov_info (const struct gcov_info *info1, const 
struct gcov_info *info2)
   return 1;
 }
 
+static int
+accumuate_sum_counts (const struct gcov_info *gcov_info1,
+                     const struct gcov_info *gcov_info2)
+{
+  gcc_assert (gcov_info1 || gcov_info2);
+  unsigned f_ix;
+
+  if (gcov_info1)
+    {
+      gcov_type cum_1 = 0;
+      for (f_ix = 0; f_ix < gcov_info1->n_functions; f_ix++)
+       {
+         const struct gcov_fn_info *gfi_ptr = gcov_info1->functions[f_ix];
+         if (!gfi_ptr || gfi_ptr->key != gcov_info1)
+           continue;
+         const struct gcov_ctr_info *ci_ptr = gfi_ptr->ctrs;
+         unsigned c_num;
+         for (c_num = 0; c_num < ci_ptr->num; c_num++)
+           cum_1 += ci_ptr->values[c_num];
+       }
+      overlap_sum_1 = cum_1;
+    }
+
+  if (gcov_info2)
+    {
+      gcov_type cum_2 = 0;
+      for (f_ix = 0; f_ix < gcov_info2->n_functions; f_ix++)
+       {
+         const struct gcov_fn_info *gfi_ptr = gcov_info2->functions[f_ix];
+         if (!gfi_ptr || gfi_ptr->key != gcov_info2)
+           continue;
+         const struct gcov_ctr_info *ci_ptr = gfi_ptr->ctrs;
+         unsigned c_num;
+         for (c_num = 0; c_num < ci_ptr->num; c_num++)
+           cum_2 += ci_ptr->values[c_num];
+       }
+      overlap_sum_2 = cum_2;
+    }
+  return 0;
+}
+
 /* Compute the overlap score of two profiles with the head of GCOV_LIST1 and
    GCOV_LIST1. Return a number ranging from [0.0, 1.0], with 0.0 meaning no
    match and 1.0 meaning a perfect match.  */
@@ -1410,6 +1457,9 @@ calculate_overlap (struct gcov_info *gcov_list1,
       if (overlap_func_level)
         printf("\n   processing %36s:\n", filename);
 
+      overlap_sum_1 = overlap_sum_2 = 0.0;
+      accumuate_sum_counts (all_infos[i].obj1, all_infos[i].obj2);
+
       val = compute_one_gcov (all_infos[i].obj1, all_infos[i].obj2,
           overlap_sum_1, overlap_sum_2, &cum_1, &cum_2);
 
-- 
2.39.3

Reply via email to