gcc/ChangeLog: 2014-11-13 Martin Liska <mli...@suse.cz>
* predict.c (propagate_freq): More elegant sreal API is used. (estimate_bb_frequencies): New static constants defined by sreal replace precomputed ones. * sreal.c (sreal::normalize): New function. (sreal::to_int): Likewise. (sreal::operator+): Likewise. (sreal::operator-): Likewise. * sreal.h: Definition of new functions added. --- gcc/predict.c | 30 +++++++++++------------- gcc/sreal.c | 56 ++++++++++++++++++++++++++++++++++++-------- gcc/sreal.h | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 126 insertions(+), 35 deletions(-) diff --git a/gcc/predict.c b/gcc/predict.c index 0215e91..0f640f5 100644 --- a/gcc/predict.c +++ b/gcc/predict.c @@ -82,7 +82,7 @@ along with GCC; see the file COPYING3. If not see /* real constants: 0, 1, 1-1/REG_BR_PROB_BASE, REG_BR_PROB_BASE, 1/REG_BR_PROB_BASE, 0.5, BB_FREQ_MAX. */ -static sreal real_zero, real_one, real_almost_one, real_br_prob_base, +static sreal real_almost_one, real_br_prob_base, real_inv_br_prob_base, real_one_half, real_bb_freq_max; static void combine_predictions_for_insn (rtx_insn *, basic_block); @@ -2528,13 +2528,13 @@ propagate_freq (basic_block head, bitmap tovisit) bb->count = bb->frequency = 0; } - BLOCK_INFO (head)->frequency = real_one; + BLOCK_INFO (head)->frequency = sreal::one (); last = head; for (bb = head; bb; bb = nextbb) { edge_iterator ei; - sreal cyclic_probability = real_zero; - sreal frequency = real_zero; + sreal cyclic_probability = sreal::zero (); + sreal frequency = sreal::zero (); nextbb = BLOCK_INFO (bb)->next; BLOCK_INFO (bb)->next = NULL; @@ -2559,13 +2559,13 @@ propagate_freq (basic_block head, bitmap tovisit) * BLOCK_INFO (e->src)->frequency / REG_BR_PROB_BASE); */ - sreal tmp (e->probability, 0); + sreal tmp = e->probability; tmp *= BLOCK_INFO (e->src)->frequency; tmp *= real_inv_br_prob_base; frequency += tmp; } - if (cyclic_probability == real_zero) + if (cyclic_probability == sreal::zero ()) { BLOCK_INFO (bb)->frequency = frequency; } @@ -2577,7 +2577,7 @@ propagate_freq (basic_block head, bitmap tovisit) /* BLOCK_INFO (bb)->frequency = frequency / (1 - cyclic_probability) */ - cyclic_probability = real_one - cyclic_probability; + cyclic_probability = sreal::one () - cyclic_probability; BLOCK_INFO (bb)->frequency = frequency / cyclic_probability; } } @@ -2591,7 +2591,7 @@ propagate_freq (basic_block head, bitmap tovisit) = ((e->probability * BLOCK_INFO (bb)->frequency) / REG_BR_PROB_BASE); */ - sreal tmp (e->probability, 0); + sreal tmp = e->probability; tmp *= BLOCK_INFO (bb)->frequency; EDGE_INFO (e)->back_edge_prob = tmp * real_inv_br_prob_base; } @@ -2873,13 +2873,11 @@ estimate_bb_frequencies (bool force) if (!real_values_initialized) { real_values_initialized = 1; - real_zero = sreal (0, 0); - real_one = sreal (1, 0); - real_br_prob_base = sreal (REG_BR_PROB_BASE, 0); - real_bb_freq_max = sreal (BB_FREQ_MAX, 0); + real_br_prob_base = REG_BR_PROB_BASE; + real_bb_freq_max = BB_FREQ_MAX; real_one_half = sreal (1, -1); - real_inv_br_prob_base = real_one / real_br_prob_base; - real_almost_one = real_one - real_inv_br_prob_base; + real_inv_br_prob_base = sreal::one () / real_br_prob_base; + real_almost_one = sreal::one () - real_inv_br_prob_base; } mark_dfs_back_edges (); @@ -2897,7 +2895,7 @@ estimate_bb_frequencies (bool force) FOR_EACH_EDGE (e, ei, bb->succs) { - EDGE_INFO (e)->back_edge_prob = sreal (e->probability, 0); + EDGE_INFO (e)->back_edge_prob = e->probability; EDGE_INFO (e)->back_edge_prob *= real_inv_br_prob_base; } } @@ -2906,7 +2904,7 @@ estimate_bb_frequencies (bool force) to outermost to examine frequencies for back edges. */ estimate_loops (); - freq_max = real_zero; + freq_max = sreal::zero (); FOR_EACH_BB_FN (bb, cfun) if (freq_max < BLOCK_INFO (bb)->frequency) freq_max = BLOCK_INFO (bb)->frequency; diff --git a/gcc/sreal.c b/gcc/sreal.c index 3f5456a..89b9c4d 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. @@ -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,9 +172,19 @@ sreal::to_int () const sreal sreal::operator+ (const sreal &other) const { + const sreal *a_p = this, *b_p = &other, *bb; + + if (m_negative && !other.m_negative) + return other + *a_p; + + if (!m_negative && other.m_negative) + return *a_p - -other; + + gcc_assert (m_negative == other.m_negative); + int dexp; sreal tmp, r; -const sreal *a_p = this, *b_p = &other, *bb; + r.m_negative = a_p->m_negative; if (*a_p < *b_p) { @@ -211,10 +224,30 @@ sreal::operator- (const sreal &other) const int dexp; sreal tmp, r; const sreal *bb; + const sreal *a_p = this; + + /* -a - b => -a + (-b). */ + if (m_negative && !other.m_negative) + return *a_p + -other; - gcc_assert (*this >= other); + /* a - (-b) => a + b. */ + if (!m_negative && other.m_negative) + return *a_p + -other; + + gcc_assert (m_negative == other.m_negative); + + /* We want to substract a smaller number from bigger + for nonegative numbers. */ + if (!m_negative && *this < other) + return -(other - *this); + + /* Example: -2 - (-3) => 3 - 2 */ + if (m_negative && *this > other) + return -other - -(*this); dexp = m_exp - other.m_exp; + + r.m_negative = m_negative; r.m_exp = m_exp; if (dexp > SREAL_BITS) { @@ -240,7 +273,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 +285,8 @@ sreal r; r.m_exp = m_exp + other.m_exp; r.normalize (); } + + r.m_negative = m_negative ^ other.m_negative; return r; } @@ -261,9 +296,10 @@ sreal sreal::operator/ (const sreal &other) const { gcc_assert (other.m_sig != 0); -sreal r; + 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; } diff --git a/gcc/sreal.h b/gcc/sreal.h index 461e28b..bfed3c7 100644 --- a/gcc/sreal.h +++ b/gcc/sreal.h @@ -1,4 +1,4 @@ -/* Definitions for simple data type for positive real numbers. +/* Definitions for simple data type for real numbers. Copyright (C) 2002-2014 Free Software Foundation, Inc. This file is part of GCC. @@ -25,7 +25,7 @@ along with GCC; see the file COPYING3. If not see #define SREAL_MIN_SIG ((uint64_t) 1 << (SREAL_PART_BITS - 1)) #define SREAL_MAX_SIG (((uint64_t) 1 << SREAL_PART_BITS) - 1) -#define SREAL_MAX_EXP (INT_MAX / 4) +#define SREAL_MAX_EXP (INT_MAX / 8) #define SREAL_BITS SREAL_PART_BITS @@ -34,10 +34,21 @@ class sreal { public: /* Construct an uninitialized sreal. */ - sreal () : m_sig (-1), m_exp (-1) {} + sreal () : m_sig (-1), m_exp (-1), m_negative (0) {} /* Construct a sreal. */ - sreal (uint64_t sig, int exp) : m_sig (sig), m_exp (exp) { normalize (); } + sreal (int64_t sig, int exp = 0) : m_exp (exp) + { + m_negative = sig < 0; + + // TODO: speed up + if (sig < 0) + sig = -sig; + + m_sig = (uint64_t) sig; + + normalize (); + } void dump (FILE *) const; int64_t to_int () const; @@ -49,13 +60,58 @@ public: bool operator< (const sreal &other) const { - return m_exp < other.m_exp + if (m_negative != other.m_negative) + return m_negative > other.m_negative; + + bool r = m_exp < other.m_exp || (m_exp == other.m_exp && m_sig < other.m_sig); + + return m_negative ? !r : r; } bool operator== (const sreal &other) const { - return m_exp == other.m_exp && m_sig == other.m_sig; + return m_exp == other.m_exp && m_sig == other.m_sig + && m_negative == other.m_negative; + } + + sreal operator- () const + { + if (m_sig == 0) + return *this; + + sreal tmp = *this; + tmp.m_negative = !tmp.m_negative; + + return tmp; + } + + sreal shift (int sig) const + { + sreal tmp = *this; + tmp.m_sig += sig; + + return tmp; + } + + /* Return zero constant. */ + inline static sreal zero () + { + static const sreal zero = sreal (0); + return zero; + } + + /* Return one constant. */ + inline static sreal one () + { + static const sreal one = sreal (1); + return one; + } + + /* Global minimum sreal can hold. */ + inline static sreal min () + { + return sreal (LONG_MIN, 0); } private: @@ -63,7 +119,8 @@ private: void shift_right (int amount); uint64_t m_sig; /* Significant. */ - signed int m_exp; /* Exponent. */ + signed int m_exp: 31; /* Exponent. */ + unsigned int m_negative: 1; /* Negative sign. */ }; extern void debug (sreal &ref); @@ -76,12 +133,12 @@ inline sreal &operator+= (sreal &a, const sreal &b) inline sreal &operator-= (sreal &a, const sreal &b) { -return a = a - b; + return a = a - b; } inline sreal &operator/= (sreal &a, const sreal &b) { -return a = a / b; + return a = a / b; } inline sreal &operator*= (sreal &a, const sreal &b) -- 2.1.2