Commit 4e9a497f by Jan Hubicka Committed by Jan Hubicka

profile-count.c (profile_count::dump): Dump quality.

	* profile-count.c (profile_count::dump): Dump quality.
	(profile_count::differs_from_p): Update for unsigned val.
	* profile-count.h (profile_count_quality): New enum.
	(profile_count): Turn m_val to 62bit unsigned, add quality tracking.

From-SVN: r249360
parent fe1ae165
2017-06-19 Jan Hubicka <hubicka@ucw.cz>
* profile-count.c (profile_count::dump): Dump quality.
(profile_count::differs_from_p): Update for unsigned val.
* profile-count.h (profile_count_quality): New enum.
(profile_count): Turn m_val to 62bit unsigned, add quality tracking.
2017-06-19 Richard Biener <rguenther@suse.de>
* tree-ssa-loop-niter.h (estimate_numbers_of_iterations): Take
......
......@@ -37,7 +37,15 @@ profile_count::dump (FILE *f) const
if (!initialized_p ())
fprintf (f, "uninitialized");
else
fprintf (f, "%" PRId64, m_val);
{
fprintf (f, "%" PRId64, m_val);
if (m_quality == count_adjusted)
fprintf (f, "(adjusted)");
else if (m_quality == count_afdo)
fprintf (f, "(auto FDO)");
else if (m_quality == count_guessed)
fprintf (f, "(guessed)");
}
}
void
......@@ -51,7 +59,7 @@ profile_count::differs_from_p (profile_count other) const
{
if (!initialized_p () || !other.initialized_p ())
return false;
if (m_val - other.m_val < 100 && other.m_val - m_val < 100)
if (m_val - other.m_val < 100 || other.m_val - m_val < 100)
return false;
if (!other.m_val)
return true;
......@@ -64,6 +72,7 @@ profile_count::stream_in (struct lto_input_block *ib)
{
profile_count ret;
ret.m_val = streamer_read_gcov_count (ib);
ret.m_quality = (profile_count_quality) streamer_read_uhwi (ib);
return ret;
}
......@@ -71,10 +80,12 @@ void
profile_count::stream_out (struct output_block *ob)
{
streamer_write_gcov_count (ob, m_val);
streamer_write_uhwi (ob, m_quality);
}
void
profile_count::stream_out (struct lto_output_stream *ob)
{
streamer_write_gcov_count_stream (ob, m_val);
streamer_write_uhwi_stream (ob, m_quality);
}
......@@ -21,6 +21,22 @@ along with GCC; see the file COPYING3. If not see
#ifndef GCC_PROFILE_COUNT_H
#define GCC_PROFILE_COUNT_H
/* Quality of the proflie count. Because gengtype does not support enums
inside of clases, this is in global namespace. */
enum profile_count_quality {
/* Profile is based on static branch prediction heuristics. It may or may
not reflect the reality. */
count_guessed = 0,
/* Profile was determined by autofdo. */
count_afdo = 2,
/* Profile was originally based on feedback but it was adjusted
by code duplicating optimization. It may not precisely reflect the
particular code path. */
count_adjusted = 1,
/* Profile was read from profile feedback or determined by accurate static
method. */
count_read = 3
};
/* The base value for branch probability notes and edge probabilities. */
#define REG_BR_PROB_BASE 10000
......@@ -58,17 +74,21 @@ along with GCC; see the file COPYING3. If not see
*/
class GTY(()) profile_count
{
/* Use int64_t to hold basic block counters. Should be at least
/* Use 62bit to hold basic block counters. Should be at least
64bit. Although a counter cannot be negative, we use a signed
type to hold various extra stages. */
int64_t m_val;
static const int n_bits = 62;
static const uint64_t max_count = ((uint64_t) 1 << n_bits) - 2;
static const uint64_t uninitialized_count = ((uint64_t) 1 << n_bits) - 1;
uint64_t m_val : n_bits;
enum profile_count_quality m_quality : 2;
/* Assume numbers smaller than this to multiply. This is set to make
testsuite pass, in future we may implement precise multiples in higer
testsuite pass, in future we may implement precise multiplication in higer
rangers. */
static const int64_t max_safe_multiplier = 131072;
public:
......@@ -87,7 +107,8 @@ public:
static profile_count uninitialized ()
{
profile_count c;
c.m_val = -1;
c.m_val = uninitialized_count;
c.m_quality = count_guessed;
return c;
}
......@@ -97,8 +118,9 @@ public:
static profile_count from_gcov_type (gcov_type v)
{
profile_count ret;
gcc_checking_assert (v>=0);
gcc_checking_assert (v >= 0 && (uint64_t) v <= max_count);
ret.m_val = v;
ret.m_quality = count_read;
return ret;
}
......@@ -112,7 +134,7 @@ public:
/* Return true if value has been initialized. */
bool initialized_p () const
{
return m_val != -1;
return m_val != uninitialized_count;
}
/* Return true if value can be trusted. */
bool reliable_p () const
......@@ -123,7 +145,7 @@ public:
/* Basic operations. */
bool operator== (const profile_count &other) const
{
return m_val == other.m_val;
return m_val == other.m_val && m_quality == other.m_quality;
}
profile_count operator+ (const profile_count &other) const
{
......@@ -136,6 +158,7 @@ public:
profile_count ret;
ret.m_val = m_val + other.m_val;
ret.m_quality = MIN (m_quality, other.m_quality);
return ret;
}
profile_count &operator+= (const profile_count &other)
......@@ -150,7 +173,10 @@ public:
if (!initialized_p () || !other.initialized_p ())
return *this = profile_count::uninitialized ();
else
m_val += other.m_val;
{
m_val += other.m_val;
m_quality = MIN (m_quality, other.m_quality);
}
return *this;
}
profile_count operator- (const profile_count &other) const
......@@ -160,7 +186,8 @@ public:
if (!initialized_p () || !other.initialized_p ())
return profile_count::uninitialized ();
profile_count ret;
ret.m_val = MAX (m_val - other.m_val, 0);
ret.m_val = m_val >= other.m_val ? m_val - other.m_val : 0;
ret.m_quality = MIN (m_quality, other.m_quality);
return ret;
}
profile_count &operator-= (const profile_count &other)
......@@ -170,14 +197,17 @@ public:
if (!initialized_p () || !other.initialized_p ())
return *this = profile_count::uninitialized ();
else
m_val = MAX (m_val - other.m_val, 0);
{
m_val = m_val >= other.m_val ? m_val - other.m_val: 0;
m_quality = MIN (m_quality, other.m_quality);
}
return *this;
}
/* Return false if profile_count is bogus. */
bool verify () const
{
return m_val >= -1;
return m_val != uninitialized_count || m_quality == count_guessed;
}
/* Comparsions are three-state and conservative. False is returned if
......@@ -192,11 +222,13 @@ public:
}
bool operator< (const gcov_type other) const
{
return initialized_p () && m_val < other;
gcc_checking_assert (other >= 0);
return initialized_p () && m_val < (uint64_t) other;
}
bool operator> (const gcov_type other) const
{
return initialized_p () && m_val > other;
gcc_checking_assert (other >= 0);
return initialized_p () && m_val > (uint64_t) other;
}
bool operator<= (const profile_count &other) const
......@@ -209,11 +241,13 @@ public:
}
bool operator<= (const gcov_type other) const
{
return initialized_p () && m_val <= other;
gcc_checking_assert (other >= 0);
return initialized_p () && m_val <= (uint64_t) other;
}
bool operator>= (const gcov_type other) const
{
return initialized_p () && m_val >= other;
gcc_checking_assert (other >= 0);
return initialized_p () && m_val >= (uint64_t) other;
}
/* PROB is a probability in scale 0...REG_BR_PROB_BASE. Scale counter
......@@ -227,6 +261,7 @@ public:
return profile_count::uninitialized ();
profile_count ret;
ret.m_val = RDIV (m_val * prob, REG_BR_PROB_BASE);
ret.m_quality = MIN (m_quality, count_adjusted);
return ret;
}
/* Return *THIS * NUM / DEN. */
......@@ -243,6 +278,7 @@ public:
|| den <= REG_BR_PROB_BASE)
&& den > 0) || 1);
ret.m_val = RDIV (m_val * num, den);
ret.m_quality = MIN (m_quality, count_adjusted);
return ret;
}
profile_count apply_scale (profile_count num, profile_count den) const
......@@ -251,14 +287,18 @@ public:
return profile_count::zero ();
if (!initialized_p () || !num.initialized_p () || !den.initialized_p ())
return profile_count::uninitialized ();
profile_count ret;
gcc_checking_assert (den > 0);
if (num == den)
return *this;
profile_count ret;
/* Take care for overflows! */
if (num.m_val < max_safe_multiplier || m_val < max_safe_multiplier)
ret.m_val = RDIV (m_val * num.m_val, den.m_val);
else
ret.m_val = RDIV (m_val * RDIV (num.m_val * max_safe_multiplier,
den.m_val), max_safe_multiplier);
ret.m_quality = MIN (m_quality, count_adjusted);
return ret;
}
......
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