diff options
author | Martin Liska <mliska@suse.cz> | 2014-11-24 11:41:18 +0100 |
---|---|---|
committer | Martin Liska <marxin@gcc.gnu.org> | 2014-11-24 10:41:18 +0000 |
commit | fd27ffab14e3b7c131cc2e454edcd11c9cc53c2e (patch) | |
tree | fc054fc4a4670f251324a07ce04dee2b8dc12fa8 /gcc/sreal.c | |
parent | 6a569cdda92269d42ae8e2cccd8c0f07d39b5d0c (diff) | |
download | gcc-fd27ffab14e3b7c131cc2e454edcd11c9cc53c2e.zip gcc-fd27ffab14e3b7c131cc2e454edcd11c9cc53c2e.tar.gz gcc-fd27ffab14e3b7c131cc2e454edcd11c9cc53c2e.tar.bz2 |
[PATCH 1/2] Negative numbers added for sreal class.
* predict.c (propagate_freq): More elegant sreal API is used.
(estimate_bb_frequencies): Precomputed constants replaced by integer
constants.
* sreal.c (sreal::normalize): New function.
(sreal::to_int): Likewise.
(sreal::operator+): Likewise.
(sreal::operator-): Likewise.
(sreal::signedless_plus): Likewise.
(sreal::signedless_minus): Likewise.
(sreal::operator/): Negative number support is added.
* sreal.h: Definition of new functions added.
(inline sreal operator<<): New function.
(inline sreal operator>>): Likewise.
From-SVN: r218008
Diffstat (limited to 'gcc/sreal.c')
-rw-r--r-- | gcc/sreal.c | 114 |
1 files changed, 87 insertions, 27 deletions
diff --git a/gcc/sreal.c b/gcc/sreal.c index 3f5456a..0337f9e 100644 --- a/gcc/sreal.c +++ b/gcc/sreal.c @@ -1,4 +1,4 @@ -/* Simple data type for positive real numbers for the GNU compiler. +/* Simple data type for real numbers for the GNU compiler. Copyright (C) 2002-2014 Free Software Foundation, Inc. This file is part of GCC. @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with GCC; see the file COPYING3. If not see <http://www.gnu.org/licenses/>. */ -/* This library supports positive real numbers and 0; +/* This library supports real numbers; inf and nan are NOT supported. It is written to be simple and fast. @@ -82,12 +82,12 @@ debug (sreal *ptr) void sreal::shift_right (int s) { - gcc_assert (s > 0); - gcc_assert (s <= SREAL_BITS); + gcc_checking_assert (s > 0); + gcc_checking_assert (s <= SREAL_BITS); /* Exponent should never be so large because shift_right is used only by sreal_add and sreal_sub ant thus the number cannot be shifted out from exponent range. */ - gcc_assert (m_exp + s <= SREAL_MAX_EXP); + gcc_checking_assert (m_exp + s <= SREAL_MAX_EXP); m_exp += s; @@ -102,6 +102,7 @@ sreal::normalize () { if (m_sig == 0) { + m_negative = 0; m_exp = -SREAL_MAX_EXP; } else if (m_sig < SREAL_MIN_SIG) @@ -153,15 +154,17 @@ sreal::normalize () int64_t sreal::to_int () const { + int64_t sign = m_negative ? -1 : 1; + if (m_exp <= -SREAL_BITS) return 0; if (m_exp >= SREAL_PART_BITS) - return INTTYPE_MAXIMUM (int64_t); + return sign * INTTYPE_MAXIMUM (int64_t); if (m_exp > 0) - return m_sig << m_exp; + return sign * (m_sig << m_exp); if (m_exp < 0) - return m_sig >> -m_exp; - return m_sig; + return sign * (m_sig >> -m_exp); + return sign * m_sig; } /* Return *this + other. */ @@ -169,18 +172,40 @@ sreal::to_int () const sreal sreal::operator+ (const sreal &other) const { - int dexp; - sreal tmp, r; -const sreal *a_p = this, *b_p = &other, *bb; + const sreal *a_p = this, *b_p = &other; - if (*a_p < *b_p) + if (a_p->m_negative && !b_p->m_negative) + std::swap (a_p, b_p); + + /* a + -b => a - b. */ + if (!a_p->m_negative && b_p->m_negative) { - const sreal *swap; - swap = a_p; - a_p = b_p; - b_p = swap; + sreal tmp = -(*b_p); + if (*a_p < tmp) + return signedless_minus (tmp, *a_p, false); + else + return signedless_minus (*a_p, tmp, true); } + gcc_checking_assert (a_p->m_negative == b_p->m_negative); + + sreal r = signedless_plus (*a_p, *b_p, a_p->m_negative); + + return r; +} + +sreal +sreal::signedless_plus (const sreal &a, const sreal &b, bool negative) +{ + const sreal *bb; + sreal r, tmp; + int dexp; + const sreal *a_p = &a; + const sreal *b_p = &b; + + if (*a_p < *b_p) + std::swap (a_p, b_p); + dexp = a_p->m_exp - b_p->m_exp; r.m_exp = a_p->m_exp; if (dexp > SREAL_BITS) @@ -200,6 +225,8 @@ const sreal *a_p = this, *b_p = &other, *bb; r.m_sig = a_p->m_sig + bb->m_sig; r.normalize (); + + r.m_negative = negative; return r; } @@ -208,30 +235,60 @@ const sreal *a_p = this, *b_p = &other, *bb; sreal sreal::operator- (const sreal &other) const { + /* -a - b => -a + (-b). */ + if (m_negative && !other.m_negative) + return signedless_plus (*this, -other, true); + + /* a - (-b) => a + b. */ + if (!m_negative && other.m_negative) + return signedless_plus (*this, -other, false); + + gcc_checking_assert (m_negative == other.m_negative); + + /* We want to substract a smaller number from bigger + for nonegative numbers. */ + if (!m_negative && *this < other) + return -signedless_minus (other, *this, true); + + /* Example: -2 - (-3) => 3 - 2 */ + if (m_negative && *this > other) + return signedless_minus (-other, -(*this), true); + + sreal r = signedless_minus (*this, other, m_negative); + + return r; +} + +sreal +sreal::signedless_minus (const sreal &a, const sreal &b, bool negative) +{ int dexp; sreal tmp, r; const sreal *bb; + const sreal *a_p = &a; + const sreal *b_p = &b; - gcc_assert (*this >= other); + dexp = a_p->m_exp - b_p->m_exp; - dexp = m_exp - other.m_exp; - r.m_exp = m_exp; + r.m_exp = a_p->m_exp; if (dexp > SREAL_BITS) { - r.m_sig = m_sig; + r.m_sig = a_p->m_sig; return r; } if (dexp == 0) - bb = &other; + bb = b_p; else { - tmp = other; + tmp = *b_p; tmp.shift_right (dexp); bb = &tmp; } - r.m_sig = m_sig - bb->m_sig; + r.m_sig = a_p->m_sig - bb->m_sig; r.normalize (); + + r.m_negative = negative; return r; } @@ -240,7 +297,7 @@ sreal::operator- (const sreal &other) const sreal sreal::operator* (const sreal &other) const { -sreal r; + sreal r; if (m_sig < SREAL_MIN_SIG || other.m_sig < SREAL_MIN_SIG) { r.m_sig = 0; @@ -252,6 +309,8 @@ sreal r; r.m_exp = m_exp + other.m_exp; r.normalize (); } + + r.m_negative = m_negative ^ other.m_negative; return r; } @@ -260,10 +319,11 @@ sreal r; sreal sreal::operator/ (const sreal &other) const { - gcc_assert (other.m_sig != 0); -sreal r; + gcc_checking_assert (other.m_sig != 0); + sreal r; r.m_sig = (m_sig << SREAL_PART_BITS) / other.m_sig; r.m_exp = m_exp - other.m_exp - SREAL_PART_BITS; + r.m_negative = m_negative ^ other.m_negative; r.normalize (); return r; } |