Commit 97c07987 by Jan Hubicka Committed by Jan Hubicka

cfgcleanup.c (try_crossjump_to_edge): Use combine_with_count to merge probabilities.


	* 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
parent 3885527d
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> 2018-01-23 Andrew Waterman <andrew@sifive.com>
Jim Wilson <jimw@sifive.com> Jim Wilson <jimw@sifive.com>
......
...@@ -2130,11 +2130,9 @@ try_crossjump_to_edge (int mode, edge e1, edge e2, ...@@ -2130,11 +2130,9 @@ try_crossjump_to_edge (int mode, edge e1, edge e2,
if (FORWARDER_BLOCK_P (s2->dest)) if (FORWARDER_BLOCK_P (s2->dest))
s2->dest->count -= s->count (); s2->dest->count -= s->count ();
/* FIXME: Is this correct? Should be rewritten to count API. */ s->probability = s->probability.combine_with_count
if (redirect_edges_to->count.nonzero_p () && src1->count.nonzero_p ()) (redirect_edges_to->count,
s->probability = s->probability.combine_with_freq s2->probability, src1->count);
(redirect_edges_to->count.to_frequency (cfun),
s2->probability, src1->count.to_frequency (cfun));
} }
/* Adjust count for the block. An earlier jump /* Adjust count for the block. An earlier jump
......
...@@ -210,7 +210,7 @@ probably_never_executed (struct function *fun, ...@@ -210,7 +210,7 @@ probably_never_executed (struct function *fun,
profile_count count) profile_count count)
{ {
gcc_checking_assert (fun); gcc_checking_assert (fun);
if (count == profile_count::zero ()) if (count.ipa () == profile_count::zero ())
return true; return true;
/* Do not trust adjusted counts. This will make us to drop int cold section /* 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 code with low execution count as a result of inlining. These low counts
......
...@@ -345,3 +345,29 @@ profile_count::from_gcov_type (gcov_type v) ...@@ -345,3 +345,29 @@ profile_count::from_gcov_type (gcov_type v)
return ret; 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 ();
}
...@@ -22,6 +22,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -22,6 +22,7 @@ along with GCC; see the file COPYING3. If not see
#define GCC_PROFILE_COUNT_H #define GCC_PROFILE_COUNT_H
struct function; struct function;
class profile_count;
/* Quality of the profile count. Because gengtype does not support enums /* Quality of the profile count. Because gengtype does not support enums
inside of classes, this is in global namespace. */ inside of classes, this is in global namespace. */
...@@ -350,7 +351,7 @@ public: ...@@ -350,7 +351,7 @@ public:
return profile_probability::uninitialized (); return profile_probability::uninitialized ();
profile_probability ret; profile_probability ret;
ret.m_val = RDIV ((uint64_t)m_val * other.m_val, max_probability); 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; return ret;
} }
profile_probability &operator*= (const profile_probability &other) profile_probability &operator*= (const profile_probability &other)
...@@ -363,7 +364,7 @@ public: ...@@ -363,7 +364,7 @@ public:
else else
{ {
m_val = RDIV ((uint64_t)m_val * other.m_val, max_probability); 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; return *this;
} }
...@@ -374,8 +375,14 @@ public: ...@@ -374,8 +375,14 @@ public:
if (!initialized_p () || !other.initialized_p ()) if (!initialized_p () || !other.initialized_p ())
return profile_probability::uninitialized (); return profile_probability::uninitialized ();
profile_probability ret; profile_probability ret;
/* If we get probability above 1, mark it as unreliable and return 1. */
if (m_val >= other.m_val) 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) else if (!m_val)
ret.m_val = 0; ret.m_val = 0;
else else
...@@ -385,7 +392,7 @@ public: ...@@ -385,7 +392,7 @@ public:
other.m_val), other.m_val),
max_probability); 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; return ret;
} }
profile_probability &operator/= (const profile_probability &other) profile_probability &operator/= (const profile_probability &other)
...@@ -396,8 +403,15 @@ public: ...@@ -396,8 +403,15 @@ public:
return *this = profile_probability::uninitialized (); return *this = profile_probability::uninitialized ();
else else
{ {
/* If we get probability above 1, mark it as unreliable
and return 1. */
if (m_val > other.m_val) 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 if (!m_val)
; ;
else else
...@@ -407,7 +421,7 @@ public: ...@@ -407,7 +421,7 @@ public:
other.m_val), other.m_val),
max_probability); max_probability);
} }
m_quality = MIN (m_quality, other.m_quality); m_quality = MIN (MIN (m_quality, other.m_quality), profile_adjusted);
} }
return *this; return *this;
} }
...@@ -465,27 +479,6 @@ public: ...@@ -465,27 +479,6 @@ public:
return ret; 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. */ /* Return *THIS * NUM / DEN. */
profile_probability apply_scale (int64_t num, int64_t den) const profile_probability apply_scale (int64_t num, int64_t den) const
{ {
...@@ -569,6 +562,12 @@ public: ...@@ -569,6 +562,12 @@ public:
bool differs_from_p (profile_probability other) const; bool differs_from_p (profile_probability other) const;
/* Return if difference is greater than 50%. */ /* Return if difference is greater than 50%. */
bool differs_lot_from_p (profile_probability other) const; 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. */ /* LTO streaming support. */
static profile_probability stream_in (struct lto_input_block *); static profile_probability stream_in (struct lto_input_block *);
...@@ -906,7 +905,10 @@ public: ...@@ -906,7 +905,10 @@ public:
return *this; return *this;
profile_count ret = *this; profile_count ret = *this;
if (ret.m_val == 0) if (ret.m_val == 0)
ret.m_val = 1; {
ret.m_val = 1;
ret.m_quality = MIN (m_quality, profile_adjusted);
}
return ret; return ret;
} }
...@@ -1062,20 +1064,28 @@ public: ...@@ -1062,20 +1064,28 @@ public:
OVERALL. */ OVERALL. */
profile_probability probability_in (const profile_count overall) const 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 (); return profile_probability::never ();
if (!initialized_p () || !overall.initialized_p () if (!initialized_p () || !overall.initialized_p ()
|| !overall.m_val) || !overall.m_val)
return profile_probability::uninitialized (); return profile_probability::uninitialized ();
if (*this == overall && m_quality == profile_precise)
return profile_probability::always ();
profile_probability ret; profile_probability ret;
gcc_checking_assert (compatible_p (overall)); gcc_checking_assert (compatible_p (overall));
if (overall.m_val < m_val) 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 else
ret.m_val = RDIV (m_val * profile_probability::max_probability, ret.m_val = RDIV (m_val * profile_probability::max_probability,
overall.m_val); 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; return ret;
} }
......
...@@ -1570,17 +1570,8 @@ replace_block_by (basic_block bb1, basic_block bb2) ...@@ -1570,17 +1570,8 @@ replace_block_by (basic_block bb1, basic_block bb2)
/* If probabilities are same, we are done. /* If probabilities are same, we are done.
If counts are nonzero we can distribute accordingly. In remaining If counts are nonzero we can distribute accordingly. In remaining
cases just avreage the values and hope for the best. */ cases just avreage the values and hope for the best. */
if (e1->probability == e2->probability) e2->probability = e1->probability.combine_with_count
; (bb1->count, e2->probability, bb2->count);
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 ();
} }
bb2->count += bb1->count; bb2->count += bb1->count;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment