aboutsummaryrefslogtreecommitdiff
path: root/gcc/sreal.h
diff options
context:
space:
mode:
authorJan Hubicka <hubicka@ucw.cz>2014-12-17 22:11:46 +0100
committerJan Hubicka <hubicka@gcc.gnu.org>2014-12-17 21:11:46 +0000
commit6c0c245e30e159720d62954a978ec2eb4d526d88 (patch)
tree78d1b62334419d5a244d634c647dc1fd0ac08abb /gcc/sreal.h
parent12d9ce19034428072b3779eff017c5e129ee4c0e (diff)
downloadgcc-6c0c245e30e159720d62954a978ec2eb4d526d88.zip
gcc-6c0c245e30e159720d62954a978ec2eb4d526d88.tar.gz
gcc-6c0c245e30e159720d62954a978ec2eb4d526d88.tar.bz2
sreal.h (sreal::normalize): Implement inline.
* sreal.h (sreal::normalize): Implement inline. (sreal::normalize_up): New function. (sreal::normalize_down): New function. * sreal.c (sreal::normalize): Remove. From-SVN: r218833
Diffstat (limited to 'gcc/sreal.h')
-rw-r--r--gcc/sreal.h85
1 files changed, 84 insertions, 1 deletions
diff --git a/gcc/sreal.h b/gcc/sreal.h
index 6314cea..2bee542 100644
--- a/gcc/sreal.h
+++ b/gcc/sreal.h
@@ -116,7 +116,9 @@ public:
}
private:
- void normalize ();
+ inline void normalize ();
+ inline void normalize_up ();
+ inline void normalize_down ();
void shift_right (int amount);
static sreal signedless_plus (const sreal &a, const sreal &b, bool negative);
static sreal signedless_minus (const sreal &a, const sreal &b, bool negative);
@@ -178,4 +180,85 @@ inline sreal operator>> (const sreal &a, int exp)
return a.shift (-exp);
}
+/* Make significant to be >= SREAL_MIN_SIG.
+
+ Make this separate method so inliner can handle hot path better. */
+
+inline void
+sreal::normalize_up ()
+{
+ int64_t s = m_sig < 0 ? -1 : 1;
+ unsigned HOST_WIDE_INT sig = absu_hwi (m_sig);
+ int shift = SREAL_PART_BITS - 2 - floor_log2 (sig);
+
+ gcc_checking_assert (shift > 0);
+ sig <<= shift;
+ m_exp -= shift;
+ gcc_checking_assert (sig <= SREAL_MAX_SIG && sig >= SREAL_MIN_SIG);
+
+ /* Check underflow. */
+ if (m_exp < -SREAL_MAX_EXP)
+ {
+ m_exp = -SREAL_MAX_EXP;
+ sig = 0;
+ }
+ if (s == -1)
+ m_sig = -sig;
+ else
+ m_sig = sig;
+}
+
+/* Make significant to be <= SREAL_MAX_SIG.
+
+ Make this separate method so inliner can handle hot path better. */
+
+inline void
+sreal::normalize_down ()
+{
+ int64_t s = m_sig < 0 ? -1 : 1;
+ int last_bit;
+ unsigned HOST_WIDE_INT sig = absu_hwi (m_sig);
+ int shift = floor_log2 (sig) - SREAL_PART_BITS + 2;
+
+ gcc_checking_assert (shift > 0);
+ last_bit = (sig >> (shift-1)) & 1;
+ sig >>= shift;
+ m_exp += shift;
+ gcc_checking_assert (sig <= SREAL_MAX_SIG && sig >= SREAL_MIN_SIG);
+
+ /* Round the number. */
+ sig += last_bit;
+ if (sig > SREAL_MAX_SIG)
+ {
+ sig >>= 1;
+ m_exp++;
+ }
+
+ /* Check overflow. */
+ if (m_exp > SREAL_MAX_EXP)
+ {
+ m_exp = SREAL_MAX_EXP;
+ sig = SREAL_MAX_SIG;
+ }
+ if (s == -1)
+ m_sig = -sig;
+ else
+ m_sig = sig;
+}
+
+/* Normalize *this; the hot path. */
+
+inline void
+sreal::normalize ()
+{
+ unsigned HOST_WIDE_INT sig = absu_hwi (m_sig);
+
+ if (sig == 0)
+ m_exp = -SREAL_MAX_EXP;
+ else if (sig > SREAL_MAX_SIG)
+ normalize_down ();
+ else if (sig < SREAL_MIN_SIG)
+ normalize_up ();
+}
+
#endif