aboutsummaryrefslogtreecommitdiff
path: root/gcc/profile-count.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/profile-count.cc')
-rw-r--r--gcc/profile-count.cc27
1 files changed, 26 insertions, 1 deletions
diff --git a/gcc/profile-count.cc b/gcc/profile-count.cc
index 190bbeb..8f05a79 100644
--- a/gcc/profile-count.cc
+++ b/gcc/profile-count.cc
@@ -32,6 +32,7 @@ along with GCC; see the file COPYING3. If not see
#include "cgraph.h"
#include "wide-int.h"
#include "sreal.h"
+#include "profile.h"
/* Names from profile_quality enum values. */
@@ -557,7 +558,7 @@ profile_count::operator* (const sreal &num) const
sreal scaled = num * m_val;
gcc_checking_assert (scaled >= 0);
profile_count ret;
- if (m_val > max_count)
+ if (scaled > max_count)
ret.m_val = max_count;
else
ret.m_val = scaled.to_nearest_int ();
@@ -570,3 +571,27 @@ profile_count::operator*= (const sreal &num)
{
return *this * num;
}
+
+/* Make counter forcibly nonzero. */
+profile_count
+profile_count::force_nonzero () const
+{
+ if (!initialized_p ())
+ return *this;
+ profile_count ret = *this;
+ /* Generally values are forced non-zero to handle inconsistent profile
+ where count 0 needs to be scaled up to non-zero.
+
+ Use cutoff value here to avoid situation where profile has large
+ cutoff and we perform count = count * num / den where num is non-zero
+ and den is 0. If profile was scaled by large factor, forcing value
+ to 1 would lead to large scale factor. */
+ gcov_unsigned_t small = profile_info ? profile_info->cutoff / 2 + 1
+ : 1;
+ if (ret.m_val < small)
+ {
+ ret.m_val = small;
+ ret.m_quality = MIN (m_quality, ADJUSTED);
+ }
+ return ret;
+}