FDO insane profile
authorXinliang David Li <davidxl@google.com>
Fri, 8 Apr 2011 21:03:12 +0000 (21:03 +0000)
committerXinliang David Li <davidxl@gcc.gnu.org>
Fri, 8 Apr 2011 21:03:12 +0000 (21:03 +0000)
From-SVN: r172213

gcc/ChangeLog
gcc/ipa-cp.c

index 3abeed0c0fdaf26e5d7e7cd680202ce1be2f732e..6d7b907317690e82b50752fc9d23f015ac7abb32 100644 (file)
@@ -1,3 +1,8 @@
+2011-04-08  Xinliang David Li  <davidxl@google.com>
+
+       * ipa-cp.c (ipcp_update_profiling): Correct
+        negative scale factor due to insane profile data.
+
 2011-04-08  Xinliang David Li  <davidxl@google.com>
 
        * final.c (dump_basic_block_info): New function.
index db0941c36a3c275adc76ab128f79071c904ba53a..2b1e50dcb615d3314e8e121a6ccaa6670328e1bb 100644 (file)
@@ -1113,6 +1113,29 @@ ipcp_update_profiling (void)
          scale = ipcp_get_node_scale (orig_node);
          node->count = orig_node->count * scale / REG_BR_PROB_BASE;
          scale_complement = REG_BR_PROB_BASE - scale;
+
+          /* Negative scale complement can result from insane profile data
+             in which the total incoming edge counts in this module is
+             larger than the callee's entry count. The insane profile data
+             usually gets generated due to the following reasons:
+
+             1) in multithreaded programs, when profile data is dumped
+             to gcda files in gcov_exit, some other threads are still running.
+             The profile counters are dumped in bottom up order (call graph).
+             The caller's BB counters may still be updated while the callee's
+             counter data is already saved to disk.
+
+             2) Comdat functions: comdat functions' profile data are not
+             allocated in comdat. When a comdat callee function gets inlined
+             at some callsites after instrumentation, and the remaining calls
+             to this function resolves to a comdat copy in another module,
+             the profile counters for this function are split. This can
+             result in sum of incoming edge counts from this module being
+             larger than callee instance's entry count.  */
+
+          if (scale_complement < 0 && flag_profile_correction)
+            scale_complement = 0;
+
          orig_node->count =
            orig_node->count * scale_complement / REG_BR_PROB_BASE;
          for (cs = node->callees; cs; cs = cs->next_callee)