aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJan Hubicka <hubicka@ucw.cz>2017-10-11 19:37:18 +0200
committerJan Hubicka <hubicka@gcc.gnu.org>2017-10-11 17:37:18 +0000
commit9588ea78db1d58ab5eb4fccc93e8ef535ce48c66 (patch)
treee4dda70458567bbf0385750dbbf8f7196369a8d0 /gcc
parent278a84349ae1e964dea6bd3bc456e11eb712c9b4 (diff)
downloadgcc-9588ea78db1d58ab5eb4fccc93e8ef535ce48c66.zip
gcc-9588ea78db1d58ab5eb4fccc93e8ef535ce48c66.tar.gz
gcc-9588ea78db1d58ab5eb4fccc93e8ef535ce48c66.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/profile-count.c19
-rw-r--r--gcc/profile-count.h50
3 files changed, 63 insertions, 14 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index d251832..c596313 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2017-10-11 Jan Hubicka <hubicka@ucw.cz>
+
+ * 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 <nathan@acm.org>
* tree.h (DECL_ASSEMBLER_NAME_SET_P): Don't check
diff --git a/gcc/profile-count.c b/gcc/profile-count.c
index 4d22428..02c9ec2 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 8fd22b8..cb1aa36 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;
}