diff options
Diffstat (limited to 'gcc/profile-count.cc')
-rw-r--r-- | gcc/profile-count.cc | 82 |
1 files changed, 55 insertions, 27 deletions
diff --git a/gcc/profile-count.cc b/gcc/profile-count.cc index 374f06f..190bbeb 100644 --- a/gcc/profile-count.cc +++ b/gcc/profile-count.cc @@ -39,8 +39,9 @@ const char *profile_quality_names[] = { "uninitialized", "guessed_local", - "guessed_global0", + "guessed_global0afdo", "guessed_global0adjusted", + "guessed_global0", "guessed", "afdo", "adjusted", @@ -76,8 +77,9 @@ const char *profile_quality_display_names[] = { NULL, "estimated locally", - "estimated locally, globally 0", + "estimated locally, globally 0 auto FDO", "estimated locally, globally 0 adjusted", + "estimated locally, globally 0", "guessed", "auto FDO", "adjusted", @@ -94,9 +96,16 @@ profile_count::dump (FILE *f, struct function *fun) const else if (fun && initialized_p () && fun->cfg && ENTRY_BLOCK_PTR_FOR_FN (fun)->count.initialized_p ()) - fprintf (f, "%" PRId64 " (%s, freq %.4f)", m_val, - profile_quality_display_names[m_quality], - to_sreal_scale (ENTRY_BLOCK_PTR_FOR_FN (fun)->count).to_double ()); + { + if (compatible_p (ENTRY_BLOCK_PTR_FOR_FN (fun)->count)) + fprintf (f, "%" PRId64 " (%s, freq %.4f)", m_val, + profile_quality_display_names[m_quality], + to_sreal_scale + (ENTRY_BLOCK_PTR_FOR_FN (fun)->count).to_double ()); + else + fprintf (f, "%" PRId64 " (%s, incompatible with entry block count)", + m_val, profile_quality_display_names[m_quality]); + } else fprintf (f, "%" PRId64 " (%s)", m_val, profile_quality_display_names[m_quality]); @@ -177,11 +186,11 @@ profile_probability::dump (char *buffer) const else buffer += sprintf (buffer, "%3.1f%%", (double)m_val * 100 / max_probability); - if (m_quality == ADJUSTED) + if (quality () == ADJUSTED) sprintf (buffer, " (adjusted)"); - else if (m_quality == AFDO) + else if (quality () == AFDO) sprintf (buffer, " (auto FDO)"); - else if (m_quality == GUESSED) + else if (quality () == GUESSED) sprintf (buffer, " (guessed)"); } } @@ -239,7 +248,7 @@ profile_probability::stream_in (class lto_input_block *ib) { profile_probability ret; ret.m_val = streamer_read_uhwi (ib); - ret.m_quality = (profile_quality) streamer_read_uhwi (ib); + ret.m_adjusted_quality = streamer_read_uhwi (ib); return ret; } @@ -249,7 +258,7 @@ void profile_probability::stream_out (struct output_block *ob) { streamer_write_uhwi (ob, m_val); - streamer_write_uhwi (ob, m_quality); + streamer_write_uhwi (ob, m_adjusted_quality); } /* Stream THIS to OB. */ @@ -258,7 +267,7 @@ void profile_probability::stream_out (struct lto_output_stream *ob) { streamer_write_uhwi_stream (ob, m_val); - streamer_write_uhwi_stream (ob, m_quality); + streamer_write_uhwi_stream (ob, m_adjusted_quality); } /* Compute RES=(a*b + c/2)/c capping and return false if overflow happened. */ @@ -344,6 +353,10 @@ profile_count::to_sreal_scale (profile_count in, bool *known) const return 1; if (!in.m_val) return m_val * 4; + /* Auto-FDO 0 really just means that we have no samples. + Treat it as small non-zero frequency. */ + if (!m_val && quality () == AFDO) + return (sreal)1 / (sreal)in.m_val; return (sreal)m_val / (sreal)in.m_val; } @@ -364,8 +377,12 @@ profile_count::adjust_for_ipa_scaling (profile_count *num, /* Scaling to zero is always zero. */ if (*num == zero ()) return; - /* If den is non-zero we are safe. */ - if (den->force_nonzero () == *den) + /* If den is non-zero we are safe. + However take care of zeros in AFDO profiles since + they simply means that no useful samples were collected. + Called function still may contain important loop. */ + if (den->force_nonzero () == *den + && num->quality () != AFDO) return; /* Force both to non-zero so we do not push profiles to 0 when both num == 0 and den == 0. */ @@ -391,10 +408,12 @@ profile_count::combine_with_ipa_count (profile_count ipa) return *this; if (ipa == zero ()) return this->global0 (); + if (ipa == afdo_zero ()) + return this->global0afdo (); return this->global0adjusted (); } -/* Sae as profile_count::combine_with_ipa_count but within function with count +/* Same as profile_count::combine_with_ipa_count but within function with count IPA2. */ profile_count profile_count::combine_with_ipa_count_within (profile_count ipa, @@ -406,7 +425,16 @@ profile_count::combine_with_ipa_count_within (profile_count ipa, if (ipa2.ipa () == ipa2 && ipa.initialized_p ()) ret = ipa; else - ret = combine_with_ipa_count (ipa); + { + /* For inconsistent profiles we may end up having ipa2 of GLOBAL0 + while ipa is non-zero (i.e. non-zero IPA counters within function + executed 0 times). Be sure we produce GLOBAL0 as well + so counters remain compatible. */ + if (ipa.nonzero_p () + && ipa2.ipa ().initialized_p ()) + ipa = ipa2.ipa (); + ret = combine_with_ipa_count (ipa); + } gcc_checking_assert (ret.compatible_p (ipa2)); return ret; } @@ -417,17 +445,17 @@ profile_count::combine_with_ipa_count_within (profile_count ipa, profile_count profile_count::from_gcov_type (gcov_type v, profile_quality quality) - { - profile_count ret; - gcc_checking_assert (v >= 0); - if (dump_file && v >= (gcov_type)max_count) - fprintf (dump_file, - "Capping gcov count %" PRId64 " to max_count %" PRId64 "\n", - (int64_t) v, (int64_t) max_count); - ret.m_val = MIN (v, (gcov_type)max_count); - ret.m_quality = quality; - return ret; - } +{ + profile_count ret; + gcc_checking_assert (v >= 0); + if (dump_file && v >= (gcov_type)max_count) + fprintf (dump_file, + "Capping gcov count %" PRId64 " to max_count %" PRId64 "\n", + (int64_t) v, (int64_t) max_count); + ret.m_val = MIN (v, (gcov_type)max_count); + ret.m_quality = quality; + return ret; +} /* COUNT1 times event happens with *THIS probability, COUNT2 times OTHER happens with COUNT2 probability. Return probability that either *THIS or @@ -471,7 +499,7 @@ profile_probability::sqrt () const if (!initialized_p () || *this == never () || *this == always ()) return *this; profile_probability ret = *this; - ret.m_quality = MIN (ret.m_quality, ADJUSTED); + ret.set_quality (MIN (ret.quality (), ADJUSTED)); uint32_t min_range = m_val; uint32_t max_range = max_probability; if (!m_val) |