* Add quality tracking for profile counter
@ 2017-06-19 9:49 Jan Hubicka
2017-06-21 7:40 ` Andreas Schwab
0 siblings, 1 reply; 3+ messages in thread
From: Jan Hubicka @ 2017-06-19 9:49 UTC (permalink / raw)
To: gcc-patches
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 10000
@@ -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;
}
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;
}
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: Add quality tracking for profile counter
2017-06-19 9:49 Add quality tracking for profile counter Jan Hubicka
@ 2017-06-21 7:40 ` Andreas Schwab
2017-06-22 14:51 ` Jan Hubicka
0 siblings, 1 reply; 3+ messages in thread
From: Andreas Schwab @ 2017-06-21 7:40 UTC (permalink / raw)
To: Jan Hubicka; +Cc: gcc-patches
On Jun 19 2017, Jan Hubicka <hubicka@ucw.cz> wrote:
> 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.
This breaks bootstrap on ia64 with a comparison failure in value-prof.o.
The only difference is in gimple_value_profile_transformations:
@@ -8962,14 +8962,14 @@ Disassembly of section .text:
ad06: 10 00 a0 01 42 80 mov r1=r104
ad0c: 0d e0 02 84 mov r108=r92;;
ad10: 09 00 cc 1c 90 11 [MMI] st4 [r14]=r51
- ad16: e0 00 20 30 20 60 ld8 r14=[r8]
+ ad16: 00 00 00 02 00 60 nop.m 0x0
ad1c: 0d 08 01 84 mov r107=r33;;
- ad20: 0b 70 d8 1c 0c 20 [MMI] and r14=r54,r14;;
- ad26: e0 38 39 1c 40 00 or r14=r39,r14
+ ad20: 0b 70 00 10 18 10 [MMI] ld8 r14=[r8];;
+ ad26: e0 b0 39 18 40 00 and r14=r54,r14
ad2c: 00 00 04 00 nop.i 0x0;;
- ad30: 01 00 00 00 01 00 [MII] nop.m 0x0
- ad36: e0 90 39 22 20 00 dep r14=r50,r14,62,2
- ad3c: 00 00 04 00 nop.i 0x0;;
+ ad30: 0b 70 9c 1c 0e 20 [MMI] or r14=r39,r14;;
+ ad36: 00 00 00 02 00 c0 nop.m 0x0
+ ad3c: 21 73 44 40 dep r14=r50,r14,62,2;;
ad40: 09 00 38 10 98 11 [MMI] st8 [r8]=r14
ad46: 00 98 41 20 23 00 st4 [r16]=r51
ad4c: 00 00 04 00 nop.i 0x0;;
Andreas.
--
Andreas Schwab, SUSE Labs, schwab@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE 1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: Add quality tracking for profile counter
2017-06-21 7:40 ` Andreas Schwab
@ 2017-06-22 14:51 ` Jan Hubicka
0 siblings, 0 replies; 3+ messages in thread
From: Jan Hubicka @ 2017-06-22 14:51 UTC (permalink / raw)
To: Andreas Schwab; +Cc: gcc-patches
Hi,
I proofread the code and noticed that in some cases I may trigger division by 0 that may
get different outputs depending on optimization setting on Itanium.
This is what I comitted after profiledbootstrap and regtesting at x86_64.
* profile-count.h (apply_probability,
apply_scale, probability_in): Fix checks for zero.
Index: profile-count.h
===================================================================
--- profile-count.h (revision 249364)
+++ profile-count.h (working copy)
@@ -255,7 +255,7 @@ public:
profile_count apply_probability (int prob) const
{
gcc_checking_assert (prob >= 0 && prob <= REG_BR_PROB_BASE);
- if (*this == profile_count::zero ())
+ if (m_val == 0)
return *this;
if (!initialized_p ())
return profile_count::uninitialized ();
@@ -267,24 +267,25 @@ public:
/* Return *THIS * NUM / DEN. */
profile_count apply_scale (int64_t num, int64_t den) const
{
- if (*this == profile_count::zero ())
+ if (m_val == 0)
return *this;
if (!initialized_p ())
return profile_count::uninitialized ();
profile_count ret;
+ gcc_checking_assert (num >= 0 && den > 0);
/* FIXME: shrink wrapping violates this sanity check. */
- gcc_checking_assert ((num >= 0
- && (num <= REG_BR_PROB_BASE
- || den <= REG_BR_PROB_BASE)
- && den > 0) || 1);
+ gcc_checking_assert ((num <= REG_BR_PROB_BASE
+ || den <= REG_BR_PROB_BASE) || 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
{
- if (*this == profile_count::zero () || num == profile_count::zero ())
- return profile_count::zero ();
+ if (m_val == 0)
+ return *this;
+ if (num.m_val == 0)
+ return num;
if (!initialized_p () || !num.initialized_p () || !den.initialized_p ())
return profile_count::uninitialized ();
gcc_checking_assert (den > 0);
@@ -306,7 +307,7 @@ public:
OVERALL. */
int probability_in (profile_count overall)
{
- if (*this == profile_count::zero ())
+ if (!m_val)
return 0;
if (!initialized_p () || !overall.initialized_p ())
return REG_BR_PROB_BASE / 2;
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2017-06-22 14:51 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-06-19 9:49 Add quality tracking for profile counter Jan Hubicka
2017-06-21 7:40 ` Andreas Schwab
2017-06-22 14:51 ` Jan Hubicka
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).