diff mbox

[8/9] Negative numbers added for sreal class.

Message ID 546F4EB7.8060006@suse.cz
State New
Headers show

Commit Message

Martin Liška Nov. 21, 2014, 2:39 p.m. UTC
On 11/21/2014 01:03 PM, Richard Biener wrote:
> On Fri, Nov 21, 2014 at 12:21 PM, Martin Liška <mliska@suse.cz> wrote:
>> On 11/14/2014 11:48 AM, Richard Biener wrote:
>>>
>>> On Thu, Nov 13, 2014 at 1:35 PM, mliska <mliska@suse.cz> wrote:
>>>>
>>>> gcc/ChangeLog:
>>>>
>>>> 2014-11-13  Martin Liska  <mliska@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.
>>>
>>>
>>> Please use gcc_checking_assert()s everywhere.  sreal is supposed
>>> to be fast... (I see it has current uses of gcc_assert - you may want
>>> to mass-convert them as a followup).
>>>
>>>> ---
>>>>    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;
>>>
>>>
>>> also undefined behavior for sig == int64_min ...
>>>
>>>> +
>>>> +    m_sig = (uint64_t) sig;
>>>
>>>
>>> any reason for not making m_sig signed and using the sign of m_sig
>>> as sign of the sreal?
>>>
>>>> +
>>>> +    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.  */
>>>
>>>
>>> As this gets padded to 2 * 64bits I wonder if it is necessary to
>>> get the slowdowns for using bitfields here.  I'd have just used
>>>
>>>     uint64_t m_sig;               /* Significant.  */
>>>     signed int m_exp;                     /* Exponent.  */
>>>     bool m_negative;
>>>
>>> or making m_sig signed...
>>>
>>> Thanks,
>>> Richard.
>>
>>
>> Hello.
>>
>> I tries to fix all notes I was given in this thread. There's list of
>> updates:
>> 1) signedless_{plus}|{minus} was introduced and there's no more recursion
>> coming from operator+|-.
>> 2) Bitfields are not used.
>> 3) New function to_double is added.
>> 4) gcc_assert is converted to gcc_checking_assert.
>>
>> With having this patch applied I was able to reach the same time (difference
>> is in noise level) for Inkscape WPA phase.
>>
>> What do you think about it?
>
> What's the point of sreal::zero and sreal::one when sreal (0) and
> sreal (1) work and when you could add
>
>    sreal& operator=(int64_t sig) { new sreal (this) (sig); }
>
> ?
>
> +  /* Global minimum sreal can hold.  */
> +  inline static sreal min ()
> +  {
> +    return sreal (LONG_MIN, 0);
>     }

Hello.

Ok, this is simplified, one can use sreal a = 12345 and it works ;)

> that's a  new API, right?  There is no max () and I think that using
> LONG_MIN here is asking for trouble (host dependence).  The
> comment in the file says the max should be
> sreal (SREAL_MAX_SIG, SREAL_MAX_EXP) and the min
> sreal (-SREAL_MAX_SIG, SREAL_MAX_EXP)?
>

Sure, sreal can store much bigger(smaller) numbers :)

> Where do you need sreal::to_double?  The host shouldn't perform
> double calculations so it can be only for dumping?  In which case
> the user should have used sreal::dump (), maybe with extra
> arguments.
>

That new function was request from Honza, only for debugging purpose.
I agree that dump should this kind of job.

If no other problem, I will run tests once more and commit it.
Thanks,
Martin

> Otherwise looks good to me and sorry for not noticing the above
> earlier.
>
> Thanks,
> Richard.
>
>> Thanks,
>> Martin
>>
>>
>>>>    };
>>>>
>>>>    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
>>>>
>>>>
>>

Comments

Richard Biener Nov. 21, 2014, 3:02 p.m. UTC | #1
On Fri, Nov 21, 2014 at 3:39 PM, Martin Liška <mliska@suse.cz> wrote:

> Hello.
>
> Ok, this is simplified, one can use sreal a = 12345 and it works ;)
>
>> that's a  new API, right?  There is no max () and I think that using
>> LONG_MIN here is asking for trouble (host dependence).  The
>> comment in the file says the max should be
>> sreal (SREAL_MAX_SIG, SREAL_MAX_EXP) and the min
>> sreal (-SREAL_MAX_SIG, SREAL_MAX_EXP)?
>>
>
> Sure, sreal can store much bigger(smaller) numbers :)
>
>> Where do you need sreal::to_double?  The host shouldn't perform
>> double calculations so it can be only for dumping?  In which case
>> the user should have used sreal::dump (), maybe with extra
>> arguments.
>>
>
> That new function was request from Honza, only for debugging purpose.
> I agree that dump should this kind of job.
>
> If no other problem, I will run tests once more and commit it.
> Thanks,
> Martin

-#define SREAL_MAX_EXP (INT_MAX / 4)
+#define SREAL_MAX_EXP (INT_MAX / 8)

this change doesn't look necessary anymore?

Btw, it's also odd that...

 #define SREAL_PART_BITS 32
...
 #define SREAL_MIN_SIG ((uint64_t) 1 << (SREAL_PART_BITS - 1))
 #define SREAL_MAX_SIG (((uint64_t) 1 << SREAL_PART_BITS) - 1)

thus all m_sig values fit in 32bits but we still use a uint64_t m_sig ...
(the implementation uses 64bit for internal computations, but still
the storage is wasteful?)

Of course the way normalize() works requires that storage to be
64bits to store unnormalized values.

I'd say ok with the SREAL_MAX_EXP change reverted.

Thanks,
Richard.


>
>> Otherwise looks good to me and sorry for not noticing the above
>> earlier.
>>
>> Thanks,
>> Richard.
>>
>>> Thanks,
>>> Martin
>>>
>>>
>>>>>    };
>>>>>
>>>>>    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
>>>>>
>>>>>
>>>
>
diff mbox

Patch

From 56e485026db94a8b226fc6af3d2bd4adbd26f9c4 Mon Sep 17 00:00:00 2001
From: mliska <mliska@suse.cz>
Date: Fri, 21 Nov 2014 12:07:40 +0100
Subject: [PATCH 1/2] Negative numbers added for sreal class.

gcc/ChangeLog:

2014-11-13  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.h: Definition of new functions added.
---
 gcc/predict.c |  30 ++++++++--------
 gcc/sreal.c   | 114 ++++++++++++++++++++++++++++++++++++++++++++--------------
 gcc/sreal.h   |  84 +++++++++++++++++++++++++++++++++++++------
 3 files changed, 175 insertions(+), 53 deletions(-)

diff --git a/gcc/predict.c b/gcc/predict.c
index 779af11..0cfe4a9 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);
@@ -2541,13 +2541,13 @@  propagate_freq (basic_block head, bitmap tovisit)
 	bb->count = bb->frequency = 0;
     }
 
-  BLOCK_INFO (head)->frequency = real_one;
+  BLOCK_INFO (head)->frequency = 1;
   last = head;
   for (bb = head; bb; bb = nextbb)
     {
       edge_iterator ei;
-      sreal cyclic_probability = real_zero;
-      sreal frequency = real_zero;
+      sreal cyclic_probability = 0;
+      sreal frequency = 0;
 
       nextbb = BLOCK_INFO (bb)->next;
       BLOCK_INFO (bb)->next = NULL;
@@ -2572,13 +2572,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 == 0)
 	    {
 	      BLOCK_INFO (bb)->frequency = frequency;
 	    }
@@ -2590,7 +2590,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 (1) - cyclic_probability;
 	      BLOCK_INFO (bb)->frequency = frequency / cyclic_probability;
 	    }
 	}
@@ -2604,7 +2604,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;
 	}
@@ -2886,13 +2886,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 (1) / real_br_prob_base;
+	  real_almost_one = sreal (1) - real_inv_br_prob_base;
 	}
 
       mark_dfs_back_edges ();
@@ -2910,7 +2908,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;
 	    }
 	}
@@ -2919,7 +2917,7 @@  estimate_bb_frequencies (bool force)
          to outermost to examine frequencies for back edges.  */
       estimate_loops ();
 
-      freq_max = real_zero;
+      freq_max = 0;
       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..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;
 }
diff --git a/gcc/sreal.h b/gcc/sreal.h
index 461e28b..e647c4c 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.
@@ -23,9 +23,11 @@  along with GCC; see the file COPYING3.  If not see
 /* SREAL_PART_BITS has to be an even number.  */
 #define SREAL_PART_BITS 32
 
+#define UINT64_BITS	64
+
 #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,14 +36,23 @@  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;
+
+    if (sig < 0)
+      sig = -sig;
+
+    m_sig = (uint64_t) sig;
+
+    normalize ();
+  }
 
   void dump (FILE *) const;
   int64_t to_int () const;
-
   sreal operator+ (const sreal &other) const;
   sreal operator- (const sreal &other) const;
   sreal operator* (const sreal &other) const;
@@ -49,21 +60,64 @@  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;
+  }
+
+  /* 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:
   void normalize ();
   void shift_right (int amount);
 
-  uint64_t m_sig;		/* Significant.  */
+  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.  */
   signed int m_exp;			/* Exponent.  */
+  bool m_negative;			/* Negative sign.  */
 };
 
 extern void debug (sreal &ref);
@@ -76,12 +130,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)
@@ -109,4 +163,14 @@  inline bool operator>= (const sreal &a, const sreal &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
-- 
2.1.2