Hi,
this patch makes us to track quality of the profile. This is useful
to disable some agressive optimizations when counts are known to be
unreliable.
Bootstrapped/regtested x86_64-linux,
Honza
* 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.
Index: profile-count.c
===
--- profile-count.c (revision 249347)
+++ profile-count.c (working copy)
@@ -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_c
{
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_inp
{
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);
}
Index: profile-count.h
===
--- profile-count.h (revision 249347)
+++ profile-count.h (working copy)
@@ -21,6 +21,22 @@ along with GCC; see the file COPYING3.
#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 = 1,
+ /* 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 = 2,
+ /* 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 1
@@ -58,17 +74,21 @@ along with GCC; see the file COPYING3.
*/
-
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;
}
profil