cfgcleanup.c (try_crossjump_to_edge): Use combine_with_count to merge probabilities.
authorJan Hubicka <hubicka@ucw.cz>
Wed, 24 Jan 2018 08:12:40 +0000 (09:12 +0100)
committerJan Hubicka <hubicka@gcc.gnu.org>
Wed, 24 Jan 2018 08:12:40 +0000 (08:12 +0000)
* cfgcleanup.c (try_crossjump_to_edge): Use combine_with_count
to merge probabilities.
* predict.c (probably_never_executed): Also mark as cold functions
with global 0 profile and guessed local profile.
* profile-count.c (profile_probability::combine_with_count): New
member function.
* profile-count.h (profile_probability::operator*,
profile_probability::operator*=, profile_probability::operator/,
profile_probability::operator/=): Reduce precision to adjusted
and set value to guessed on contradictory divisions.
(profile_probability::combine_with_freq): Remove.
(profile_probability::combine_wiht_count): Declare.
(profile_count::force_nonzero):: Set to adjusted.
(profile_count::probability_in):: Set quality to adjusted.
* tree-ssa-tail-merge.c (replace_block_by): Use
combine_with_count.

From-SVN: r257010

gcc/ChangeLog
gcc/cfgcleanup.c
gcc/predict.c
gcc/profile-count.c
gcc/profile-count.h
gcc/tree-ssa-tail-merge.c

index 899b13e32f82aa992ddb216eae4349185dde20a3..b3ebc9d5eec28094100b02e4ee270433348a44c7 100644 (file)
@@ -1,3 +1,22 @@
+2018-01-23  Jan Hubicka  <hubicka@ucw.cz>
+
+       * cfgcleanup.c (try_crossjump_to_edge): Use combine_with_count
+       to merge probabilities.
+       * predict.c (probably_never_executed): Also mark as cold functions
+       with global 0 profile and guessed local profile.
+       * profile-count.c (profile_probability::combine_with_count): New
+       member function.
+       * profile-count.h (profile_probability::operator*,
+       profile_probability::operator*=, profile_probability::operator/,
+       profile_probability::operator/=): Reduce precision to adjusted
+       and set value to guessed on contradictory divisions.
+       (profile_probability::combine_with_freq): Remove.
+       (profile_probability::combine_wiht_count): Declare.
+       (profile_count::force_nonzero):: Set to adjusted.
+       (profile_count::probability_in):: Set quality to adjusted.
+       * tree-ssa-tail-merge.c (replace_block_by): Use
+       combine_with_count.
+
 2018-01-23  Andrew Waterman  <andrew@sifive.com>
            Jim Wilson  <jimw@sifive.com>
 
index c33022c1bb5c6d75736d80af75f0b1469e654e1e..6892d806e53272dc76b5adcb8accedc44cb5451f 100644 (file)
@@ -2130,11 +2130,9 @@ try_crossjump_to_edge (int mode, edge e1, edge e2,
       if (FORWARDER_BLOCK_P (s2->dest))
        s2->dest->count -= s->count ();
 
-      /* FIXME: Is this correct? Should be rewritten to count API.  */
-      if (redirect_edges_to->count.nonzero_p () && src1->count.nonzero_p ())
-       s->probability = s->probability.combine_with_freq
-                          (redirect_edges_to->count.to_frequency (cfun),
-                           s2->probability, src1->count.to_frequency (cfun));
+      s->probability = s->probability.combine_with_count
+                         (redirect_edges_to->count,
+                          s2->probability, src1->count);
     }
 
   /* Adjust count for the block.  An earlier jump
index 2d932e9fd11645d3ebeee9b2cdeb2742a10f0e7f..25629db89f8b731b5ca79f96345508c28efad801 100644 (file)
@@ -210,7 +210,7 @@ probably_never_executed (struct function *fun,
                          profile_count count)
 {
   gcc_checking_assert (fun);
-  if (count == profile_count::zero ())
+  if (count.ipa () == profile_count::zero ())
     return true;
   /* Do not trust adjusted counts.  This will make us to drop int cold section
      code with low execution count as a result of inlining. These low counts
index 5f1a5fbe03ee3eb7c18705bd5a575f8e9159efb1..c3b115f0b81c96b4456af77ff24cb1043a95dcbb 100644 (file)
@@ -345,3 +345,29 @@ profile_count::from_gcov_type (gcov_type v)
     return ret;
   }
 
+
+/* COUNT1 times event happens with *THIS probability, COUNT2 times OTHER
+   happens with COUNT2 probablity. Return probablity that either *THIS or
+   OTHER happens.  */
+
+profile_probability
+profile_probability::combine_with_count (profile_count count1,
+                                        profile_probability other,
+                                        profile_count count2) const
+{
+  /* If probabilities are same, we are done.
+     If counts are nonzero we can distribute accordingly. In remaining
+     cases just avreage the values and hope for the best.  */
+  if (*this == other || count1 == count2
+      || (count2 == profile_count::zero ()
+         && !(count1 == profile_count::zero ())))
+    return *this;
+  if (count1 == profile_count::zero () && !(count2 == profile_count::zero ()))
+    return other;
+  else if (count1.nonzero_p () || count2.nonzero_p ())
+    return *this * count1.probability_in (count1 + count2)
+          + other * count2.probability_in (count1 + count2);
+  else
+    return *this * profile_probability::even ()
+          + other * profile_probability::even ();
+}
index 234e3886cb2bd32854a6736efc79ebdf1873b24e..c83fa3beb8feb6dd3f6238c611c4fa0508cf83c6 100644 (file)
@@ -22,6 +22,7 @@ along with GCC; see the file COPYING3.  If not see
 #define GCC_PROFILE_COUNT_H
 
 struct function;
+class profile_count;
 
 /* Quality of the profile count.  Because gengtype does not support enums
    inside of classes, this is in global namespace.  */
@@ -350,7 +351,7 @@ public:
        return profile_probability::uninitialized ();
       profile_probability ret;
       ret.m_val = RDIV ((uint64_t)m_val * other.m_val, max_probability);
-      ret.m_quality = MIN (m_quality, other.m_quality);
+      ret.m_quality = MIN (MIN (m_quality, other.m_quality), profile_adjusted);
       return ret;
     }
   profile_probability &operator*= (const profile_probability &other)
@@ -363,7 +364,7 @@ public:
       else
        {
          m_val = RDIV ((uint64_t)m_val * other.m_val, max_probability);
-         m_quality = MIN (m_quality, other.m_quality);
+         m_quality = MIN (MIN (m_quality, other.m_quality), profile_adjusted);
        }
       return *this;
     }
@@ -374,8 +375,14 @@ public:
       if (!initialized_p () || !other.initialized_p ())
        return profile_probability::uninitialized ();
       profile_probability ret;
+      /* If we get probability above 1, mark it as unreliable and return 1. */
       if (m_val >= other.m_val)
-       ret.m_val = max_probability;
+       {
+         ret.m_val = max_probability;
+          ret.m_quality = MIN (MIN (m_quality, other.m_quality),
+                              profile_guessed);
+         return ret;
+       }
       else if (!m_val)
        ret.m_val = 0;
       else
@@ -385,7 +392,7 @@ public:
                                 other.m_val),
                           max_probability);
        }
-      ret.m_quality = MIN (m_quality, other.m_quality);
+      ret.m_quality = MIN (MIN (m_quality, other.m_quality), profile_adjusted);
       return ret;
     }
   profile_probability &operator/= (const profile_probability &other)
@@ -396,8 +403,15 @@ public:
        return *this = profile_probability::uninitialized ();
       else
        {
+          /* If we get probability above 1, mark it as unreliable
+            and return 1. */
          if (m_val > other.m_val)
-           m_val = max_probability;
+           {
+             m_val = max_probability;
+              m_quality = MIN (MIN (m_quality, other.m_quality),
+                              profile_guessed);
+             return *this;
+           }
          else if (!m_val)
            ;
          else
@@ -407,7 +421,7 @@ public:
                                 other.m_val),
                           max_probability);
            }
-         m_quality = MIN (m_quality, other.m_quality);
+         m_quality = MIN (MIN (m_quality, other.m_quality), profile_adjusted);
        }
       return *this;
     }
@@ -465,27 +479,6 @@ public:
       return ret;
     }
 
-  profile_probability combine_with_freq (int freq1, profile_probability other,
-                                        int freq2) const
-    {
-      profile_probability ret;
-
-      if (*this == profile_probability::uninitialized ()
-         || other == profile_probability::uninitialized ())
-       return profile_probability::uninitialized ();
-
-      gcc_checking_assert (freq1 >= 0 && freq2 >= 0);
-      if (!freq1 && !freq2)
-       {
-         ret.m_val = (m_val + other.m_val) / 2;
-       }
-      else
-       ret.m_val = RDIV (m_val * (uint64_t) freq1
-                         + other.m_val * (uint64_t) freq2, freq1 + freq2);
-      ret.m_quality = MIN (m_quality, other.m_quality);
-      return ret;
-    }
-
   /* Return *THIS * NUM / DEN.  */
   profile_probability apply_scale (int64_t num, int64_t den) const
     {
@@ -569,6 +562,12 @@ public:
   bool differs_from_p (profile_probability other) const;
   /* Return if difference is greater than 50%.  */
   bool differs_lot_from_p (profile_probability other) const;
+  /* COUNT1 times event happens with *THIS probability, COUNT2 times OTHER
+     happens with COUNT2 probablity. Return probablity that either *THIS or
+     OTHER happens.  */
+  profile_probability combine_with_count (profile_count count1,
+                                         profile_probability other,
+                                         profile_count count2) const;
 
   /* LTO streaming support.  */
   static profile_probability stream_in (struct lto_input_block *);
@@ -906,7 +905,10 @@ public:
        return *this;
       profile_count ret = *this;
       if (ret.m_val == 0)
-       ret.m_val = 1;
+       {
+         ret.m_val = 1;
+          ret.m_quality = MIN (m_quality, profile_adjusted);
+       }
       return ret;
     }
 
@@ -1062,20 +1064,28 @@ public:
      OVERALL.  */
   profile_probability probability_in (const profile_count overall) const
     {
-      if (*this == profile_count::zero ())
+      if (*this == profile_count::zero ()
+         && !(overall == profile_count::zero ()))
        return profile_probability::never ();
       if (!initialized_p () || !overall.initialized_p ()
          || !overall.m_val)
        return profile_probability::uninitialized ();
+      if (*this == overall && m_quality == profile_precise)
+       return profile_probability::always ();
       profile_probability ret;
       gcc_checking_assert (compatible_p (overall));
 
       if (overall.m_val < m_val)
-       ret.m_val = profile_probability::max_probability;
+       {
+         ret.m_val = profile_probability::max_probability;
+         ret.m_quality = profile_guessed;
+         return ret;
+       }
       else
        ret.m_val = RDIV (m_val * profile_probability::max_probability,
                          overall.m_val);
-      ret.m_quality = MAX (MIN (m_quality, overall.m_quality), profile_guessed);
+      ret.m_quality = MIN (MAX (MIN (m_quality, overall.m_quality),
+                               profile_guessed), profile_adjusted);
       return ret;
     }
 
index d43f3fbf55685f98c6186e702fad2083900031e6..a687c3f28df9ea2212221029259b8f6e2b82ad69 100644 (file)
@@ -1570,17 +1570,8 @@ replace_block_by (basic_block bb1, basic_block bb2)
        /* If probabilities are same, we are done.
           If counts are nonzero we can distribute accordingly. In remaining
           cases just avreage the values and hope for the best.  */
-       if (e1->probability == e2->probability)
-         ;
-       else if (bb1->count.nonzero_p () || bb2->count.nonzero_p ())
-         e2->probability
-            = e2->probability
-                * bb2->count.probability_in (bb1->count + bb2->count)
-              + e1->probability
-                * bb1->count.probability_in (bb1->count + bb2->count);
-       else
-         e2->probability = e2->probability * profile_probability::even ()
-                           + e1->probability * profile_probability::even ();
+       e2->probability = e1->probability.combine_with_count
+                            (bb1->count, e2->probability, bb2->count);
       }
   bb2->count += bb1->count;