enum profile_quality {
/* Uninitialized value. */
UNINITIALIZED_PROFILE,
+
/* Profile is based on static branch prediction heuristics and may
or may not match reality. It is local to function and cannot be compared
inter-procedurally. Never used by probabilities (they are always local).
*/
GUESSED_LOCAL,
+
/* Profile was read by feedback and was 0, we used local heuristics to guess
better. This is the case of functions not run in profile fedback.
Never used by probabilities. */
with feedback and propagated from that).
Never used by probablities. */
GUESSED,
+
/* Profile was determined by autofdo. */
AFDO,
+
/* Profile was originally based on feedback but it was adjusted
by code duplicating optimization. It may not precisely reflect the
particular code path. */
ADJUSTED,
+
/* Profile was read from profile feedback or determined by accurate static
method. */
PRECISE
ret.m_quality = PRECISE;
return ret;
}
+
static profile_probability guessed_never ()
{
profile_probability ret;
ret.m_quality = GUESSED;
return ret;
}
+
static profile_probability very_unlikely ()
{
/* Be consistent with PROB_VERY_UNLIKELY in predict.h. */
r.m_val--;
return r;
}
+
static profile_probability unlikely ()
{
/* Be consistent with PROB_VERY_LIKELY in predict.h. */
r.m_val--;
return r;
}
+
static profile_probability even ()
{
return guessed_always ().apply_scale (1, 2);
}
+
static profile_probability very_likely ()
{
return always () - very_unlikely ();
}
+
static profile_probability likely ()
{
return always () - unlikely ();
}
+
static profile_probability guessed_always ()
{
profile_probability ret;
ret.m_quality = GUESSED;
return ret;
}
+
static profile_probability always ()
{
profile_probability ret;
ret.m_quality = PRECISE;
return ret;
}
+
/* Probabilities which has not been initialized. Either because
initialization did not happen yet or because profile is unknown. */
static profile_probability uninitialized ()
return c;
}
-
/* Return true if value has been initialized. */
bool initialized_p () const
{
return m_val != uninitialized_probability;
}
+
/* Return true if value can be trusted. */
bool reliable_p () const
{
ret.m_quality = GUESSED;
return ret;
}
+
int to_reg_br_prob_base () const
{
gcc_checking_assert (initialized_p ());
ret.m_quality = (enum profile_quality)(v & 7);
return ret;
}
+
int to_reg_br_prob_note () const
{
gcc_checking_assert (initialized_p ());
{
return m_val == other.m_val && m_quality == other.m_quality;
}
+
profile_probability operator+ (const profile_probability &other) const
{
if (other == never ())
ret.m_quality = MIN (m_quality, other.m_quality);
return ret;
}
+
profile_probability &operator+= (const profile_probability &other)
{
if (other == never ())
}
return *this;
}
+
profile_probability operator- (const profile_probability &other) const
{
if (*this == never ()
ret.m_quality = MIN (m_quality, other.m_quality);
return ret;
}
+
profile_probability &operator-= (const profile_probability &other)
{
if (*this == never ()
}
return *this;
}
+
profile_probability operator* (const profile_probability &other) const
{
if (*this == never ()
ret.m_quality = MIN (MIN (m_quality, other.m_quality), ADJUSTED);
return ret;
}
+
profile_probability &operator*= (const profile_probability &other)
{
if (*this == never ()
}
return *this;
}
+
profile_probability operator/ (const profile_probability &other) const
{
if (*this == never ())
ret.m_quality = MIN (MIN (m_quality, other.m_quality), ADJUSTED);
return ret;
}
+
profile_probability &operator/= (const profile_probability &other)
{
if (*this == never ())
noreturn heuristic that is only one giving probability over 99% or bellow
1%. In future we might want to propagate reliability information across the
CFG if we find this information useful on multiple places. */
-
bool probably_reliable_p () const
{
if (m_quality >= ADJUSTED)
{
return initialized_p () && other.initialized_p () && m_val < other.m_val;
}
+
bool operator> (const profile_probability &other) const
{
return initialized_p () && other.initialized_p () && m_val > other.m_val;
{
return initialized_p () && other.initialized_p () && m_val <= other.m_val;
}
+
bool operator>= (const profile_probability &other) const
{
return initialized_p () && other.initialized_p () && m_val >= other.m_val;
/* Return true if THIS is known to differ significantly from OTHER. */
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. */
{
return from_gcov_type (0);
}
+
static profile_count adjusted_zero ()
{
profile_count c;
c.m_quality = ADJUSTED;
return c;
}
+
static profile_count guessed_zero ()
{
profile_count c;
c.m_quality = GUESSED;
return c;
}
+
static profile_count one ()
{
return from_gcov_type (1);
}
+
/* Value of counters which has not been initialized. Either because
initialization did not happen yet or because profile is unknown. */
static profile_count uninitialized ()
{
return m_val != uninitialized_count;
}
+
/* Return true if value can be trusted. */
bool reliable_p () const
{
return m_quality >= ADJUSTED;
}
+
/* Return true if vlaue can be operated inter-procedurally. */
bool ipa_p () const
{
return !initialized_p () || m_quality >= GUESSED_GLOBAL0;
}
+
/* Return true if quality of profile is precise. */
bool precise_p () const
{
{
return m_val == other.m_val && m_quality == other.m_quality;
}
+
profile_count operator+ (const profile_count &other) const
{
if (other == zero ())
ret.m_quality = MIN (m_quality, other.m_quality);
return ret;
}
+
profile_count &operator+= (const profile_count &other)
{
if (other == zero ())
}
return *this;
}
+
profile_count operator- (const profile_count &other) const
{
if (*this == zero () || other == zero ())
ret.m_quality = MIN (m_quality, other.m_quality);
return ret;
}
+
profile_count &operator-= (const profile_count &other)
{
if (*this == zero () || other == zero ())
gcc_checking_assert (compatible_p (other));
return m_val < other.m_val;
}
+
bool operator> (const profile_count &other) const
{
if (!initialized_p () || !other.initialized_p ())
gcc_checking_assert (compatible_p (other));
return initialized_p () && other.initialized_p () && m_val > other.m_val;
}
+
bool operator< (const gcov_type other) const
{
gcc_checking_assert (ipa_p ());
gcc_checking_assert (other >= 0);
return initialized_p () && m_val < (uint64_t) other;
}
+
bool operator> (const gcov_type other) const
{
gcc_checking_assert (ipa_p ());
gcc_checking_assert (compatible_p (other));
return m_val <= other.m_val;
}
+
bool operator>= (const profile_count &other) const
{
if (!initialized_p () || !other.initialized_p ())
gcc_checking_assert (compatible_p (other));
return m_val >= other.m_val;
}
+
bool operator<= (const gcov_type other) const
{
gcc_checking_assert (ipa_p ());
gcc_checking_assert (other >= 0);
return initialized_p () && m_val <= (uint64_t) other;
}
+
bool operator>= (const gcov_type other) const
{
gcc_checking_assert (ipa_p ());
gcc_checking_assert (other >= 0);
return initialized_p () && m_val >= (uint64_t) other;
}
+
/* Return true when value is not zero and can be used for scaling.
This is different from *this > 0 because that requires counter to
be IPA. */
ret.m_quality = MIN (m_quality, prob.m_quality);
return ret;
}
+
/* Return *THIS * NUM / DEN. */
profile_count apply_scale (int64_t num, int64_t den) const
{
ret.m_quality = MIN (m_quality, ADJUSTED);
return ret;
}
+
profile_count apply_scale (profile_count num, profile_count den) const
{
if (*this == zero ())