From 9588ea78db1d58ab5eb4fccc93e8ef535ce48c66 Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Wed, 11 Oct 2017 19:37:18 +0200 Subject: [PATCH] profile-count.h (slow_safe_scale_64bit): New function. * profile-count.h (slow_safe_scale_64bit): New function. (safe_scale_64bit): New inline. (profile_count::max_safe_multiplier): Remove; use safe_scale_64bit. * profile-count.c: Include wide-int.h (slow_safe_scale_64bit): New. From-SVN: r253652 --- gcc/ChangeLog | 8 ++++++++ gcc/profile-count.c | 19 +++++++++++++++++ gcc/profile-count.h | 50 ++++++++++++++++++++++++++++++++------------- 3 files changed, 63 insertions(+), 14 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d2518321cda..c596313bb11 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2017-10-11 Jan Hubicka + + * profile-count.h (slow_safe_scale_64bit): New function. + (safe_scale_64bit): New inline. + (profile_count::max_safe_multiplier): Remove; use safe_scale_64bit. + * profile-count.c: Include wide-int.h + (slow_safe_scale_64bit): New. + 2017-10-11 Nathan Sidwell * tree.h (DECL_ASSEMBLER_NAME_SET_P): Don't check diff --git a/gcc/profile-count.c b/gcc/profile-count.c index 4d22428a195..02c9ec241d4 100644 --- a/gcc/profile-count.c +++ b/gcc/profile-count.c @@ -30,6 +30,7 @@ along with GCC; see the file COPYING3. If not see #include "gimple.h" #include "data-streamer.h" #include "cgraph.h" +#include "wide-int.h" /* Dump THIS to F. */ @@ -194,3 +195,21 @@ profile_probability::stream_out (struct lto_output_stream *ob) streamer_write_uhwi_stream (ob, m_val); streamer_write_uhwi_stream (ob, m_quality); } + +/* Compute RES=(a*b + c/2)/c capping and return false if overflow happened. */ + +bool +slow_safe_scale_64bit (uint64_t a, uint64_t b, uint64_t c, uint64_t *res) +{ + FIXED_WIDE_INT (128) tmp = a; + bool overflow; + tmp = wi::udiv_floor (wi::umul (tmp, b, &overflow) + (c / 2), c); + gcc_checking_assert (!overflow); + if (wi::fits_uhwi_p (tmp)) + { + *res = tmp.to_uhwi (); + return true; + } + *res = (uint64_t) -1; + return false; +} diff --git a/gcc/profile-count.h b/gcc/profile-count.h index 8fd22b8b68a..cb1aa365c95 100644 --- a/gcc/profile-count.h +++ b/gcc/profile-count.h @@ -43,6 +43,35 @@ enum profile_quality { #define RDIV(X,Y) (((X) + (Y) / 2) / (Y)) +bool slow_safe_scale_64bit (uint64_t a, uint64_t b, uint64_t c, uint64_t *res); + +/* Compute RES=(a*b + c/2)/c capping and return false if overflow happened. */ + +inline bool +safe_scale_64bit (uint64_t a, uint64_t b, uint64_t c, uint64_t *res) +{ +#if (GCC_VERSION >= 5000) + uint64_t tmp; + if (!__builtin_mul_overflow (a, b, &tmp) + && !__builtin_add_overflow (tmp, c/2, &tmp)) + { + *res = tmp / c; + return true; + } + if (c == 1) + { + *res = (uint64_t) -1; + return false; + } +#else + if (a < ((uint64_t)1 << 31) + && b < ((uint64_t)1 << 31) + && c < ((uint64_t)1 << 31)) + return (a * b + (c / 2)) / c; +#endif + return slow_safe_scale_64bit (a, b, c, res); +} + /* Data type to hold probabilities. It implements fixed point arithmetics with capping so probability is always in range [0,1] and scaling requiring values greater than 1 needs to be represented otherwise. @@ -87,7 +116,8 @@ class GTY((user)) profile_probability static const int n_bits = 30; static const uint32_t max_probability = REG_BR_PROB_BASE; - static const uint32_t uninitialized_probability = ((uint32_t) 1 << n_bits) - 1; + static const uint32_t uninitialized_probability + = ((uint32_t) 1 << (n_bits - 1)) - 1; uint32_t m_val : 30; enum profile_quality m_quality : 2; @@ -171,7 +201,7 @@ public: /* Return true if value can be trusted. */ bool reliable_p () const { - return initialized_p (); + return m_quality >= profile_adjusted; } /* Conversion from and to REG_BR_PROB_BASE integer fixpoint arithmetics. @@ -535,11 +565,6 @@ class GTY(()) profile_count uint64_t m_val : n_bits; enum profile_quality m_quality : 2; - - /* Assume numbers smaller than this to multiply. This is set to make - testsuite pass, in future we may implement precise multiplication in higer - rangers. */ - static const uint64_t max_safe_multiplier = 131072; public: /* Used for counters which are expected to be never executed. */ @@ -595,7 +620,7 @@ public: /* Return true if value can be trusted. */ bool reliable_p () const { - return initialized_p (); + return m_quality >= profile_adjusted; } /* When merging basic blocks, the two different profile counts are unified. @@ -790,12 +815,9 @@ public: 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); + uint64_t val; + safe_scale_64bit (m_val, num.m_val, den.m_val, &val); + ret.m_val = MIN (val, max_count); ret.m_quality = MIN (m_quality, profile_adjusted); return ret; } -- 2.30.2