Commit fd27ffab by Martin Liska Committed by Martin Liska

[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
parent 6a569cdd
2014-11-24 Martin Liska <mliska@suse.cz>
* 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.
2014-11-24 Kyrylo Tkachov <kyrylo.tkachov@arm.com> 2014-11-24 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
* config/aarch64/aarch64-protos.h (struct tune_params): Add * config/aarch64/aarch64-protos.h (struct tune_params): Add
...@@ -82,7 +82,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -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, /* real constants: 0, 1, 1-1/REG_BR_PROB_BASE, REG_BR_PROB_BASE,
1/REG_BR_PROB_BASE, 0.5, BB_FREQ_MAX. */ 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; real_inv_br_prob_base, real_one_half, real_bb_freq_max;
static void combine_predictions_for_insn (rtx_insn *, basic_block); static void combine_predictions_for_insn (rtx_insn *, basic_block);
...@@ -2541,13 +2541,13 @@ propagate_freq (basic_block head, bitmap tovisit) ...@@ -2541,13 +2541,13 @@ propagate_freq (basic_block head, bitmap tovisit)
bb->count = bb->frequency = 0; bb->count = bb->frequency = 0;
} }
BLOCK_INFO (head)->frequency = real_one; BLOCK_INFO (head)->frequency = 1;
last = head; last = head;
for (bb = head; bb; bb = nextbb) for (bb = head; bb; bb = nextbb)
{ {
edge_iterator ei; edge_iterator ei;
sreal cyclic_probability = real_zero; sreal cyclic_probability = 0;
sreal frequency = real_zero; sreal frequency = 0;
nextbb = BLOCK_INFO (bb)->next; nextbb = BLOCK_INFO (bb)->next;
BLOCK_INFO (bb)->next = NULL; BLOCK_INFO (bb)->next = NULL;
...@@ -2572,13 +2572,13 @@ propagate_freq (basic_block head, bitmap tovisit) ...@@ -2572,13 +2572,13 @@ propagate_freq (basic_block head, bitmap tovisit)
* BLOCK_INFO (e->src)->frequency / * BLOCK_INFO (e->src)->frequency /
REG_BR_PROB_BASE); */ REG_BR_PROB_BASE); */
sreal tmp (e->probability, 0); sreal tmp = e->probability;
tmp *= BLOCK_INFO (e->src)->frequency; tmp *= BLOCK_INFO (e->src)->frequency;
tmp *= real_inv_br_prob_base; tmp *= real_inv_br_prob_base;
frequency += tmp; frequency += tmp;
} }
if (cyclic_probability == real_zero) if (cyclic_probability == 0)
{ {
BLOCK_INFO (bb)->frequency = frequency; BLOCK_INFO (bb)->frequency = frequency;
} }
...@@ -2590,7 +2590,7 @@ propagate_freq (basic_block head, bitmap tovisit) ...@@ -2590,7 +2590,7 @@ propagate_freq (basic_block head, bitmap tovisit)
/* BLOCK_INFO (bb)->frequency = frequency /* BLOCK_INFO (bb)->frequency = frequency
/ (1 - cyclic_probability) */ / (1 - cyclic_probability) */
cyclic_probability = real_one - cyclic_probability; cyclic_probability = sreal (1) - cyclic_probability;
BLOCK_INFO (bb)->frequency = frequency / cyclic_probability; BLOCK_INFO (bb)->frequency = frequency / cyclic_probability;
} }
} }
...@@ -2604,7 +2604,7 @@ propagate_freq (basic_block head, bitmap tovisit) ...@@ -2604,7 +2604,7 @@ propagate_freq (basic_block head, bitmap tovisit)
= ((e->probability * BLOCK_INFO (bb)->frequency) = ((e->probability * BLOCK_INFO (bb)->frequency)
/ REG_BR_PROB_BASE); */ / REG_BR_PROB_BASE); */
sreal tmp (e->probability, 0); sreal tmp = e->probability;
tmp *= BLOCK_INFO (bb)->frequency; tmp *= BLOCK_INFO (bb)->frequency;
EDGE_INFO (e)->back_edge_prob = tmp * real_inv_br_prob_base; EDGE_INFO (e)->back_edge_prob = tmp * real_inv_br_prob_base;
} }
...@@ -2886,13 +2886,11 @@ estimate_bb_frequencies (bool force) ...@@ -2886,13 +2886,11 @@ estimate_bb_frequencies (bool force)
if (!real_values_initialized) if (!real_values_initialized)
{ {
real_values_initialized = 1; real_values_initialized = 1;
real_zero = sreal (0, 0); real_br_prob_base = REG_BR_PROB_BASE;
real_one = sreal (1, 0); real_bb_freq_max = BB_FREQ_MAX;
real_br_prob_base = sreal (REG_BR_PROB_BASE, 0);
real_bb_freq_max = sreal (BB_FREQ_MAX, 0);
real_one_half = sreal (1, -1); real_one_half = sreal (1, -1);
real_inv_br_prob_base = real_one / real_br_prob_base; real_inv_br_prob_base = sreal (1) / real_br_prob_base;
real_almost_one = real_one - real_inv_br_prob_base; real_almost_one = sreal (1) - real_inv_br_prob_base;
} }
mark_dfs_back_edges (); mark_dfs_back_edges ();
...@@ -2910,7 +2908,7 @@ estimate_bb_frequencies (bool force) ...@@ -2910,7 +2908,7 @@ estimate_bb_frequencies (bool force)
FOR_EACH_EDGE (e, ei, bb->succs) 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; EDGE_INFO (e)->back_edge_prob *= real_inv_br_prob_base;
} }
} }
...@@ -2919,7 +2917,7 @@ estimate_bb_frequencies (bool force) ...@@ -2919,7 +2917,7 @@ estimate_bb_frequencies (bool force)
to outermost to examine frequencies for back edges. */ to outermost to examine frequencies for back edges. */
estimate_loops (); estimate_loops ();
freq_max = real_zero; freq_max = 0;
FOR_EACH_BB_FN (bb, cfun) FOR_EACH_BB_FN (bb, cfun)
if (freq_max < BLOCK_INFO (bb)->frequency) if (freq_max < BLOCK_INFO (bb)->frequency)
freq_max = BLOCK_INFO (bb)->frequency; freq_max = BLOCK_INFO (bb)->frequency;
......
/* 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. Copyright (C) 2002-2014 Free Software Foundation, Inc.
This file is part of GCC. This file is part of GCC.
...@@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License ...@@ -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 along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */ <http://www.gnu.org/licenses/>. */
/* This library supports positive real numbers and 0; /* This library supports real numbers;
inf and nan are NOT supported. inf and nan are NOT supported.
It is written to be simple and fast. It is written to be simple and fast.
...@@ -82,12 +82,12 @@ debug (sreal *ptr) ...@@ -82,12 +82,12 @@ debug (sreal *ptr)
void void
sreal::shift_right (int s) sreal::shift_right (int s)
{ {
gcc_assert (s > 0); gcc_checking_assert (s > 0);
gcc_assert (s <= SREAL_BITS); gcc_checking_assert (s <= SREAL_BITS);
/* Exponent should never be so large because shift_right is used only by /* 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 sreal_add and sreal_sub ant thus the number cannot be shifted out from
exponent range. */ exponent range. */
gcc_assert (m_exp + s <= SREAL_MAX_EXP); gcc_checking_assert (m_exp + s <= SREAL_MAX_EXP);
m_exp += s; m_exp += s;
...@@ -102,6 +102,7 @@ sreal::normalize () ...@@ -102,6 +102,7 @@ sreal::normalize ()
{ {
if (m_sig == 0) if (m_sig == 0)
{ {
m_negative = 0;
m_exp = -SREAL_MAX_EXP; m_exp = -SREAL_MAX_EXP;
} }
else if (m_sig < SREAL_MIN_SIG) else if (m_sig < SREAL_MIN_SIG)
...@@ -153,15 +154,17 @@ sreal::normalize () ...@@ -153,15 +154,17 @@ sreal::normalize ()
int64_t int64_t
sreal::to_int () const sreal::to_int () const
{ {
int64_t sign = m_negative ? -1 : 1;
if (m_exp <= -SREAL_BITS) if (m_exp <= -SREAL_BITS)
return 0; return 0;
if (m_exp >= SREAL_PART_BITS) if (m_exp >= SREAL_PART_BITS)
return INTTYPE_MAXIMUM (int64_t); return sign * INTTYPE_MAXIMUM (int64_t);
if (m_exp > 0) if (m_exp > 0)
return m_sig << m_exp; return sign * (m_sig << m_exp);
if (m_exp < 0) if (m_exp < 0)
return m_sig >> -m_exp; return sign * (m_sig >> -m_exp);
return m_sig; return sign * m_sig;
} }
/* Return *this + other. */ /* Return *this + other. */
...@@ -169,18 +172,40 @@ sreal::to_int () const ...@@ -169,18 +172,40 @@ sreal::to_int () const
sreal sreal
sreal::operator+ (const sreal &other) const sreal::operator+ (const sreal &other) const
{ {
int dexp; const sreal *a_p = this, *b_p = &other;
sreal tmp, r;
const sreal *a_p = this, *b_p = &other, *bb;
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; sreal tmp = -(*b_p);
swap = a_p; if (*a_p < tmp)
a_p = b_p; return signedless_minus (tmp, *a_p, false);
b_p = swap; 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; dexp = a_p->m_exp - b_p->m_exp;
r.m_exp = a_p->m_exp; r.m_exp = a_p->m_exp;
if (dexp > SREAL_BITS) if (dexp > SREAL_BITS)
...@@ -200,6 +225,8 @@ const sreal *a_p = this, *b_p = &other, *bb; ...@@ -200,6 +225,8 @@ const sreal *a_p = this, *b_p = &other, *bb;
r.m_sig = a_p->m_sig + bb->m_sig; r.m_sig = a_p->m_sig + bb->m_sig;
r.normalize (); r.normalize ();
r.m_negative = negative;
return r; return r;
} }
...@@ -208,30 +235,60 @@ const sreal *a_p = this, *b_p = &other, *bb; ...@@ -208,30 +235,60 @@ const sreal *a_p = this, *b_p = &other, *bb;
sreal sreal
sreal::operator- (const sreal &other) const 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; int dexp;
sreal tmp, r; sreal tmp, r;
const sreal *bb; 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 = a_p->m_exp;
r.m_exp = m_exp;
if (dexp > SREAL_BITS) if (dexp > SREAL_BITS)
{ {
r.m_sig = m_sig; r.m_sig = a_p->m_sig;
return r; return r;
} }
if (dexp == 0) if (dexp == 0)
bb = &other; bb = b_p;
else else
{ {
tmp = other; tmp = *b_p;
tmp.shift_right (dexp); tmp.shift_right (dexp);
bb = &tmp; bb = &tmp;
} }
r.m_sig = m_sig - bb->m_sig; r.m_sig = a_p->m_sig - bb->m_sig;
r.normalize (); r.normalize ();
r.m_negative = negative;
return r; return r;
} }
...@@ -240,7 +297,7 @@ sreal::operator- (const sreal &other) const ...@@ -240,7 +297,7 @@ sreal::operator- (const sreal &other) const
sreal sreal
sreal::operator* (const sreal &other) const sreal::operator* (const sreal &other) const
{ {
sreal r; sreal r;
if (m_sig < SREAL_MIN_SIG || other.m_sig < SREAL_MIN_SIG) if (m_sig < SREAL_MIN_SIG || other.m_sig < SREAL_MIN_SIG)
{ {
r.m_sig = 0; r.m_sig = 0;
...@@ -252,6 +309,8 @@ sreal r; ...@@ -252,6 +309,8 @@ sreal r;
r.m_exp = m_exp + other.m_exp; r.m_exp = m_exp + other.m_exp;
r.normalize (); r.normalize ();
} }
r.m_negative = m_negative ^ other.m_negative;
return r; return r;
} }
...@@ -260,10 +319,11 @@ sreal r; ...@@ -260,10 +319,11 @@ sreal r;
sreal sreal
sreal::operator/ (const sreal &other) const sreal::operator/ (const sreal &other) const
{ {
gcc_assert (other.m_sig != 0); gcc_checking_assert (other.m_sig != 0);
sreal r; sreal r;
r.m_sig = (m_sig << SREAL_PART_BITS) / other.m_sig; r.m_sig = (m_sig << SREAL_PART_BITS) / other.m_sig;
r.m_exp = m_exp - other.m_exp - SREAL_PART_BITS; r.m_exp = m_exp - other.m_exp - SREAL_PART_BITS;
r.m_negative = m_negative ^ other.m_negative;
r.normalize (); r.normalize ();
return r; return r;
} }
/* 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. Copyright (C) 2002-2014 Free Software Foundation, Inc.
This file is part of GCC. This file is part of GCC.
...@@ -23,6 +23,8 @@ along with GCC; see the file COPYING3. If not see ...@@ -23,6 +23,8 @@ along with GCC; see the file COPYING3. If not see
/* SREAL_PART_BITS has to be an even number. */ /* SREAL_PART_BITS has to be an even number. */
#define SREAL_PART_BITS 32 #define SREAL_PART_BITS 32
#define UINT64_BITS 64
#define SREAL_MIN_SIG ((uint64_t) 1 << (SREAL_PART_BITS - 1)) #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_SIG (((uint64_t) 1 << SREAL_PART_BITS) - 1)
#define SREAL_MAX_EXP (INT_MAX / 4) #define SREAL_MAX_EXP (INT_MAX / 4)
...@@ -34,14 +36,23 @@ class sreal ...@@ -34,14 +36,23 @@ class sreal
{ {
public: public:
/* Construct an uninitialized sreal. */ /* Construct an uninitialized sreal. */
sreal () : m_sig (-1), m_exp (-1) {} sreal () : m_sig (-1), m_exp (-1), m_negative (0) {}
/* Construct a sreal. */ /* 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;
if (sig < 0)
sig = -sig;
m_sig = (uint64_t) sig;
normalize ();
}
void dump (FILE *) const; void dump (FILE *) const;
int64_t to_int () const; int64_t to_int () const;
sreal operator+ (const sreal &other) const; sreal operator+ (const sreal &other) const;
sreal operator- (const sreal &other) const; sreal operator- (const sreal &other) const;
sreal operator* (const sreal &other) const; sreal operator* (const sreal &other) const;
...@@ -49,21 +60,64 @@ public: ...@@ -49,21 +60,64 @@ public:
bool operator< (const sreal &other) const 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); || (m_exp == other.m_exp && m_sig < other.m_sig);
return m_negative ? !r : r;
} }
bool operator== (const sreal &other) const 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;
}
/* Global minimum sreal can hold. */
inline static sreal min ()
{
static sreal min = sreal (-SREAL_MAX_SIG, SREAL_MAX_EXP);
return min;
}
/* Global minimum sreal can hold. */
inline static sreal max ()
{
static sreal max = sreal (SREAL_MAX_SIG, SREAL_MAX_EXP);
return max;
} }
private: private:
void normalize (); void normalize ();
void shift_right (int amount); 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);
uint64_t m_sig; /* Significant. */ uint64_t m_sig; /* Significant. */
signed int m_exp; /* Exponent. */ signed int m_exp; /* Exponent. */
bool m_negative; /* Negative sign. */
}; };
extern void debug (sreal &ref); extern void debug (sreal &ref);
...@@ -76,12 +130,12 @@ inline sreal &operator+= (sreal &a, const sreal &b) ...@@ -76,12 +130,12 @@ inline sreal &operator+= (sreal &a, const sreal &b)
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) inline sreal &operator/= (sreal &a, const sreal &b)
{ {
return a = a / b; return a = a / b;
} }
inline sreal &operator*= (sreal &a, const sreal &b) inline sreal &operator*= (sreal &a, const sreal &b)
...@@ -109,4 +163,14 @@ inline bool operator>= (const sreal &a, const sreal &b) ...@@ -109,4 +163,14 @@ inline bool operator>= (const sreal &a, const sreal &b)
return a == b || a > b; return a == b || a > b;
} }
inline sreal operator<< (const sreal &a, int exp)
{
return a.shift (exp);
}
inline sreal operator>> (const sreal &a, int exp)
{
return a.shift (-exp);
}
#endif #endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment