ipa-utils.c (ipa_merge_profiles): Be sure that all type transtions of counters are...
authorJan Hubicka <hubicka@ucw.cz>
Thu, 28 Nov 2019 14:21:08 +0000 (15:21 +0100)
committerJan Hubicka <hubicka@gcc.gnu.org>
Thu, 28 Nov 2019 14:21:08 +0000 (14:21 +0000)
* ipa-utils.c (ipa_merge_profiles): Be sure that all type transtions
of counters are done same way.

From-SVN: r278809

gcc/ChangeLog
gcc/ipa-utils.c

index 9897c0e604e2420e1d9c6e602b5e25248bc1e099..aecc351e0fa9af5fd833caae214ef46677ac886f 100644 (file)
@@ -1,3 +1,8 @@
+2019-11-28  Jan Hubicka  <hubicka@ucw.cz>
+
+       * ipa-utils.c (ipa_merge_profiles): Be sure that all type transtions
+       of counters are done same way.
+
 2019-11-28  Jan Hubicka  <hubicka@ucw.cz>
 
        * ipa-cp.c (update_profiling_info): Fix scaling.
index 2830d41026a5632bac2a60582bda11b70d5b220d..fdbecdb7b35ae8aa2f6ca494d239b315329099eb 100644 (file)
@@ -398,6 +398,7 @@ ipa_merge_profiles (struct cgraph_node *dst,
   tree oldsrcdecl = src->decl;
   struct function *srccfun, *dstcfun;
   bool match = true;
+  bool copy_counts = false;
 
   if (!src->definition
       || !dst->definition)
@@ -429,10 +430,26 @@ ipa_merge_profiles (struct cgraph_node *dst,
     }
   profile_count orig_count = dst->count;
 
-  if (dst->count.initialized_p () && dst->count.ipa () == dst->count)
-    dst->count += src->count.ipa ();
-  else 
-    dst->count = src->count.ipa ();
+  /* Either sum the profiles if both are IPA and not global0, or
+     pick more informative one (that is nonzero IPA if other is
+     uninitialized, guessed or global0).   */
+
+  if ((dst->count.ipa ().nonzero_p ()
+       || src->count.ipa ().nonzero_p ())
+      && dst->count.ipa ().initialized_p ()
+      && src->count.ipa ().initialized_p ())
+    dst->count = dst->count.ipa () + src->count.ipa ();
+  else if (dst->count.ipa ().initialized_p ())
+    ;
+  else if (src->count.ipa ().initialized_p ())
+    {
+      copy_counts = true;
+      dst->count = src->count.ipa ();
+    }
+
+  /* If no updating needed return early.  */
+  if (dst->count == orig_count)
+    return;
 
   /* First handle functions with no gimple body.  */
   if (dst->thunk.thunk_p || dst->alias
@@ -544,6 +561,16 @@ ipa_merge_profiles (struct cgraph_node *dst,
       struct cgraph_edge *e, *e2;
       basic_block srcbb, dstbb;
 
+      /* Function and global profile may be out of sync.  First scale it same
+        way as fixup_cfg would.  */
+      profile_count srcnum = src->count;
+      profile_count srcden = ENTRY_BLOCK_PTR_FOR_FN (srccfun)->count;
+      bool srcscale = srcnum.initialized_p () && !(srcnum == srcden);
+      profile_count dstnum = orig_count;
+      profile_count dstden = ENTRY_BLOCK_PTR_FOR_FN (dstcfun)->count;
+      bool dstscale = !copy_counts
+                     && dstnum.initialized_p () && !(dstnum == dstden);
+
       /* TODO: merge also statement histograms.  */
       FOR_ALL_BB_FN (srcbb, srccfun)
        {
@@ -551,15 +578,15 @@ ipa_merge_profiles (struct cgraph_node *dst,
 
          dstbb = BASIC_BLOCK_FOR_FN (dstcfun, srcbb->index);
 
-         /* Either sum the profiles if both are IPA and not global0, or
-            pick more informative one (that is nonzero IPA if other is
-            uninitialized, guessed or global0).   */
-         if (!dstbb->count.ipa ().initialized_p ()
-             || (dstbb->count.ipa () == profile_count::zero ()
-                 && (srcbb->count.ipa ().initialized_p ()
-                     && !(srcbb->count.ipa () == profile_count::zero ()))))
+         profile_count srccount = srcbb->count;
+         if (srcscale)
+           srccount = srccount.apply_scale (srcnum, srcden);
+         if (dstscale)
+           dstbb->count = dstbb->count.apply_scale (dstnum, dstden);
+
+         if (copy_counts)
            {
-             dstbb->count = srcbb->count;
+             dstbb->count = srccount;
              for (i = 0; i < EDGE_COUNT (srcbb->succs); i++)
                {
                  edge srce = EDGE_SUCC (srcbb, i);
@@ -568,18 +595,21 @@ ipa_merge_profiles (struct cgraph_node *dst,
                    dste->probability = srce->probability;
                }
            }   
-         else if (srcbb->count.ipa ().initialized_p ()
-                  && !(srcbb->count.ipa () == profile_count::zero ()))
+         else 
            {
              for (i = 0; i < EDGE_COUNT (srcbb->succs); i++)
                {
                  edge srce = EDGE_SUCC (srcbb, i);
                  edge dste = EDGE_SUCC (dstbb, i);
                  dste->probability = 
-                   dste->probability * dstbb->count.probability_in (dstbb->count + srcbb->count)
-                   + srce->probability * srcbb->count.probability_in (dstbb->count + srcbb->count);
+                   dste->probability * dstbb->count.ipa ().probability_in
+                                                (dstbb->count.ipa ()
+                                                 + srccount.ipa ())
+                   + srce->probability * srcbb->count.ipa ().probability_in
+                                                (dstbb->count.ipa ()
+                                                 + srccount.ipa ());
                }
-             dstbb->count += srcbb->count;
+             dstbb->count = dstbb->count.ipa () + srccount.ipa ();
            }
        }
       push_cfun (dstcfun);