]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/real.c
c++: Handle multiple aggregate overloads [PR95319].
[thirdparty/gcc.git] / gcc / real.c
index 0cc5aec7363079397f6428d081ee6132ca4efa6b..09ec5c08c3863e18f498009e9a3d36522f6c2a9d 100644 (file)
@@ -1,5 +1,5 @@
 /* real.c - software floating point emulation.
-   Copyright (C) 1993-2015 Free Software Foundation, Inc.
+   Copyright (C) 1993-2020 Free Software Foundation, Inc.
    Contributed by Stephen L. Moshier (moshier@world.std.com).
    Re-written by Richard Henderson <rth@redhat.com>
 
@@ -420,7 +420,10 @@ clear_significand_below (REAL_VALUE_TYPE *r, unsigned int n)
   for (i = 0; i < w; ++i)
     r->sig[i] = 0;
 
-  r->sig[w] &= ~(((unsigned long)1 << (n % HOST_BITS_PER_LONG)) - 1);
+  /* We are actually passing N == SIGNIFICAND_BITS which would result
+     in an out-of-bound access below.  */
+  if (n % HOST_BITS_PER_LONG != 0)
+    r->sig[w] &= ~(((unsigned long)1 << (n % HOST_BITS_PER_LONG)) - 1);
 }
 
 /* Divide the significands of A and B, placing the result in R.  Return
@@ -541,6 +544,10 @@ do_add (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a,
     case CLASS2 (rvc_normal, rvc_inf):
       /* R + Inf = Inf.  */
       *r = *b;
+      /* Make resulting NaN value to be qNaN. The caller has the
+         responsibility to avoid the operation if flag_signaling_nans
+         is on.  */
+      r->signalling = 0;
       r->sign = sign ^ subtract_p;
       return false;
 
@@ -554,6 +561,10 @@ do_add (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a,
     case CLASS2 (rvc_inf, rvc_normal):
       /* Inf + R = Inf.  */
       *r = *a;
+      /* Make resulting NaN value to be qNaN. The caller has the
+         responsibility to avoid the operation if flag_signaling_nans
+         is on.  */
+      r->signalling = 0;
       return false;
 
     case CLASS2 (rvc_inf, rvc_inf):
@@ -676,6 +687,10 @@ do_multiply (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a,
     case CLASS2 (rvc_nan, rvc_nan):
       /* ANY * NaN = NaN.  */
       *r = *b;
+      /* Make resulting NaN value to be qNaN. The caller has the
+         responsibility to avoid the operation if flag_signaling_nans
+         is on.  */
+      r->signalling = 0;
       r->sign = sign;
       return false;
 
@@ -684,6 +699,10 @@ do_multiply (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a,
     case CLASS2 (rvc_nan, rvc_inf):
       /* NaN * ANY = NaN.  */
       *r = *a;
+      /* Make resulting NaN value to be qNaN. The caller has the
+         responsibility to avoid the operation if flag_signaling_nans
+         is on.  */
+      r->signalling = 0;
       r->sign = sign;
       return false;
 
@@ -826,6 +845,10 @@ do_divide (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a,
     case CLASS2 (rvc_nan, rvc_nan):
       /* ANY / NaN = NaN.  */
       *r = *b;
+      /* Make resulting NaN value to be qNaN. The caller has the
+         responsibility to avoid the operation if flag_signaling_nans
+         is on.  */
+      r->signalling = 0;
       r->sign = sign;
       return false;
 
@@ -834,6 +857,10 @@ do_divide (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a,
     case CLASS2 (rvc_nan, rvc_inf):
       /* NaN / ANY = NaN.  */
       *r = *a;
+      /* Make resulting NaN value to be qNaN. The caller has the
+         responsibility to avoid the operation if flag_signaling_nans
+         is on.  */
+      r->signalling = 0;
       r->sign = sign;
       return false;
 
@@ -936,12 +963,12 @@ do_compare (const REAL_VALUE_TYPE *a, const REAL_VALUE_TYPE *b,
       gcc_unreachable ();
     }
 
-  if (a->sign != b->sign)
-    return -a->sign - -b->sign;
-
   if (a->decimal || b->decimal)
     return decimal_do_compare (a, b, nan_result);
 
+  if (a->sign != b->sign)
+    return -a->sign - -b->sign;
+
   if (REAL_EXP (a) > REAL_EXP (b))
     ret = 1;
   else if (REAL_EXP (a) < REAL_EXP (b))
@@ -964,6 +991,10 @@ do_fix_trunc (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a)
     case rvc_zero:
     case rvc_inf:
     case rvc_nan:
+      /* Make resulting NaN value to be qNaN. The caller has the
+         responsibility to avoid the operation if flag_signaling_nans
+         is on.  */
+      r->signalling = 0;
       break;
 
     case rvc_normal:
@@ -1022,7 +1053,13 @@ real_arithmetic (REAL_VALUE_TYPE *r, int icode, const REAL_VALUE_TYPE *op0,
 
     case MIN_EXPR:
       if (op1->cl == rvc_nan)
+      {
        *r = *op1;
+       /* Make resulting NaN value to be qNaN. The caller has the
+          responsibility to avoid the operation if flag_signaling_nans
+           is on.  */
+       r->signalling = 0;
+      }
       else if (do_compare (op0, op1, -1) < 0)
        *r = *op0;
       else
@@ -1031,7 +1068,13 @@ real_arithmetic (REAL_VALUE_TYPE *r, int icode, const REAL_VALUE_TYPE *op0,
 
     case MAX_EXPR:
       if (op1->cl == rvc_nan)
+      {
        *r = *op1;
+       /* Make resulting NaN value to be qNaN. The caller has the
+          responsibility to avoid the operation if flag_signaling_nans
+           is on.  */
+       r->signalling = 0;
+      }
       else if (do_compare (op0, op1, 1) < 0)
        *r = *op1;
       else
@@ -1162,6 +1205,10 @@ real_ldexp (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *op0, int exp)
     case rvc_zero:
     case rvc_inf:
     case rvc_nan:
+      /* Make resulting NaN value to be qNaN. The caller has the
+         responsibility to avoid the operation if flag_signaling_nans
+         is on.  */
+      r->signalling = 0;
       break;
 
     case rvc_normal:
@@ -1195,6 +1242,12 @@ real_isnan (const REAL_VALUE_TYPE *r)
   return (r->cl == rvc_nan);
 }
 
+/* Determine whether a floating-point value X is a signaling NaN.  */ 
+bool real_issignaling_nan (const REAL_VALUE_TYPE *r)
+{
+  return real_isnan (r) && r->signalling;
+}
+
 /* Determine whether a floating-point value X is finite.  */
 
 bool
@@ -1345,7 +1398,7 @@ real_to_integer (const REAL_VALUE_TYPE *r)
     case rvc_inf:
     case rvc_nan:
     overflow:
-      i = (unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1);
+      i = HOST_WIDE_INT_1U << (HOST_BITS_PER_WIDE_INT - 1);
       if (!r->sign)
        i--;
       return i;
@@ -1661,8 +1714,8 @@ real_to_decimal_for_mode (char *str, const REAL_VALUE_TYPE *r_orig,
 
          do_multiply (&u, &v, ten);
 
-         /* Stop if we're now >= 1.  */
-         if (REAL_EXP (&u) > 0)
+         /* Stop if we're now >= 1 or zero.  */
+         if (REAL_EXP (&u) > 0 || u.cl == rvc_zero)
            break;
 
          v = u;
@@ -2054,7 +2107,7 @@ real_from_string (REAL_VALUE_TYPE *r, const char *str)
 
       /* Nonzero value, possibly overflowing or underflowing.  */
       mpfr_init2 (m, SIGNIFICAND_BITS);
-      inexact = mpfr_strtofr (m, str, NULL, 10, GMP_RNDZ);
+      inexact = mpfr_strtofr (m, str, NULL, 10, MPFR_RNDZ);
       /* The result should never be a NaN, and because the rounding is
         toward zero should never be an infinity.  */
       gcc_assert (!mpfr_nan_p (m) && !mpfr_inf_p (m));
@@ -2070,7 +2123,7 @@ real_from_string (REAL_VALUE_TYPE *r, const char *str)
        }
       else
        {
-         real_from_mpfr (r, m, NULL_TREE, GMP_RNDZ);
+         real_from_mpfr (r, m, NULL_TREE, MPFR_RNDZ);
          /* 1 to 3 bits may have been shifted off (with a sticky bit)
             because the hex digits used in real_from_mpfr did not
             start with a digit 8 to f, but the exponent bounds above
@@ -2216,7 +2269,7 @@ real_from_integer (REAL_VALUE_TYPE *r, format_helper fmt,
 
   if (fmt.decimal_p ())
     decimal_from_integer (r);
-  else if (fmt)
+  if (fmt)
     real_convert (r, fmt, r);
 }
 
@@ -2381,9 +2434,9 @@ dconst_e_ptr (void)
     {
       mpfr_t m;
       mpfr_init2 (m, SIGNIFICAND_BITS);
-      mpfr_set_ui (m, 1, GMP_RNDN);
-      mpfr_exp (m, m, GMP_RNDN);
-      real_from_mpfr (&value, m, NULL_TREE, GMP_RNDN);
+      mpfr_set_ui (m, 1, MPFR_RNDN);
+      mpfr_exp (m, m, MPFR_RNDN);
+      real_from_mpfr (&value, m, NULL_TREE, MPFR_RNDN);
       mpfr_clear (m);
 
     }
@@ -2424,8 +2477,8 @@ dconst_sqrt2_ptr (void)
     {
       mpfr_t m;
       mpfr_init2 (m, SIGNIFICAND_BITS);
-      mpfr_sqrt_ui (m, 2, GMP_RNDN);
-      real_from_mpfr (&value, m, NULL_TREE, GMP_RNDN);
+      mpfr_sqrt_ui (m, 2, MPFR_RNDN);
+      real_from_mpfr (&value, m, NULL_TREE, MPFR_RNDN);
       mpfr_clear (m);
     }
   return &value;
@@ -2521,7 +2574,7 @@ real_nan (REAL_VALUE_TYPE *r, const char *str, int quiet,
       /* Our MSB is always unset for NaNs.  */
       r->sig[SIGSZ-1] &= ~SIG_MSB;
 
-      /* Force quiet or signalling NaN.  */
+      /* Force quiet or signaling NaN.  */
       r->signalling = !quiet;
     }
 
@@ -2617,6 +2670,7 @@ round_for_format (const struct real_format *fmt, REAL_VALUE_TYPE *r)
     {
     underflow:
       get_zero (r, r->sign);
+      /* FALLTHRU */
     case rvc_zero:
       if (!fmt->has_signed_zero)
        r->sign = 0;
@@ -2724,6 +2778,12 @@ real_convert (REAL_VALUE_TYPE *r, format_helper fmt,
 
   round_for_format (fmt, r);
 
+  /* Make resulting NaN value to be qNaN. The caller has the
+     responsibility to avoid the operation if flag_signaling_nans
+     is on.  */
+  if (r->cl == rvc_nan)
+    r->signalling = 0;
+
   /* round_for_format de-normalizes denormals.  Undo just that part.  */
   if (r->cl == rvc_normal)
     normalize (r);
@@ -2830,7 +2890,7 @@ real_hash (const REAL_VALUE_TYPE *r)
       return h;
 
     case rvc_normal:
-      h |= REAL_EXP (r) << 3;
+      h |= (unsigned int)REAL_EXP (r) << 3;
       break;
 
     case rvc_nan:
@@ -2986,6 +3046,7 @@ const struct real_format ieee_single_format =
     128,
     31,
     31,
+    32,
     false,
     true,
     true,
@@ -3008,6 +3069,7 @@ const struct real_format mips_single_format =
     128,
     31,
     31,
+    32,
     false,
     true,
     true,
@@ -3030,6 +3092,7 @@ const struct real_format motorola_single_format =
     128,
     31,
     31,
+    32,
     false,
     true,
     true,
@@ -3063,6 +3126,7 @@ const struct real_format spu_single_format =
     129,
     31,
     31,
+    0,
     true,
     false,
     false,
@@ -3273,6 +3337,7 @@ const struct real_format ieee_double_format =
     1024,
     63,
     63,
+    64,
     false,
     true,
     true,
@@ -3295,6 +3360,7 @@ const struct real_format mips_double_format =
     1024,
     63,
     63,
+    64,
     false,
     true,
     true,
@@ -3317,6 +3383,7 @@ const struct real_format motorola_double_format =
     1024,
     63,
     63,
+    64,
     false,
     true,
     true,
@@ -3662,6 +3729,7 @@ const struct real_format ieee_extended_motorola_format =
     16384,
     95,
     95,
+    0,
     false,
     true,
     true,
@@ -3684,6 +3752,7 @@ const struct real_format ieee_extended_intel_96_format =
     16384,
     79,
     79,
+    65,
     false,
     true,
     true,
@@ -3706,6 +3775,7 @@ const struct real_format ieee_extended_intel_128_format =
     16384,
     79,
     79,
+    65,
     false,
     true,
     true,
@@ -3730,6 +3800,7 @@ const struct real_format ieee_extended_intel_96_round_53_format =
     16384,
     79,
     79,
+    33,
     false,
     true,
     true,
@@ -3819,6 +3890,7 @@ const struct real_format ibm_extended_format =
     1024,
     127,
     -1,
+    0,
     false,
     true,
     true,
@@ -3841,6 +3913,7 @@ const struct real_format mips_extended_format =
     1024,
     127,
     -1,
+    0,
     false,
     true,
     true,
@@ -4105,6 +4178,7 @@ const struct real_format ieee_quad_format =
     16384,
     127,
     127,
+    128,
     false,
     true,
     true,
@@ -4127,6 +4201,7 @@ const struct real_format mips_quad_format =
     16384,
     127,
     127,
+    128,
     false,
     true,
     true,
@@ -4428,6 +4503,7 @@ const struct real_format vax_f_format =
     127,
     15,
     15,
+    0,
     false,
     false,
     false,
@@ -4450,6 +4526,7 @@ const struct real_format vax_d_format =
     127,
     15,
     15,
+    0,
     false,
     false,
     false,
@@ -4472,6 +4549,7 @@ const struct real_format vax_g_format =
     1023,
     15,
     15,
+    0,
     false,
     false,
     false,
@@ -4549,6 +4627,7 @@ const struct real_format decimal_single_format =
     97,
     31,
     31,
+    32,
     false,
     true,
     true,
@@ -4572,6 +4651,7 @@ const struct real_format decimal_double_format =
     385,
     63,
     63,
+    64,
     false,
     true,
     true,
@@ -4595,6 +4675,7 @@ const struct real_format decimal_quad_format =
     6145,
     127,
     127,
+    128,
     false,
     true,
     true,
@@ -4721,6 +4802,116 @@ decode_ieee_half (const struct real_format *fmt, REAL_VALUE_TYPE *r,
     }
 }
 
+/* Encode arm_bfloat types.  */
+static void
+encode_arm_bfloat_half (const struct real_format *fmt, long *buf,
+                   const REAL_VALUE_TYPE *r)
+{
+  unsigned long image, sig, exp;
+  unsigned long sign = r->sign;
+  bool denormal = (r->sig[SIGSZ-1] & SIG_MSB) == 0;
+
+  image = sign << 15;
+  sig = (r->sig[SIGSZ-1] >> (HOST_BITS_PER_LONG - 8)) & 0x7f;
+
+  switch (r->cl)
+    {
+    case rvc_zero:
+      break;
+
+    case rvc_inf:
+      if (fmt->has_inf)
+       image |= 255 << 7;
+      else
+       image |= 0x7fff;
+      break;
+
+    case rvc_nan:
+      if (fmt->has_nans)
+       {
+         if (r->canonical)
+           sig = (fmt->canonical_nan_lsbs_set ? (1 << 6) - 1 : 0);
+         if (r->signalling == fmt->qnan_msb_set)
+           sig &= ~(1 << 6);
+         else
+           sig |= 1 << 6;
+         if (sig == 0)
+           sig = 1 << 5;
+
+         image |= 255 << 7;
+         image |= sig;
+       }
+      else
+       image |= 0x7fff;
+      break;
+
+    case rvc_normal:
+      if (denormal)
+       exp = 0;
+      else
+      exp = REAL_EXP (r) + 127 - 1;
+      image |= exp << 7;
+      image |= sig;
+      break;
+
+    default:
+      gcc_unreachable ();
+    }
+
+  buf[0] = image;
+}
+
+/* Decode arm_bfloat types.  */
+static void
+decode_arm_bfloat_half (const struct real_format *fmt, REAL_VALUE_TYPE *r,
+                   const long *buf)
+{
+  unsigned long image = buf[0] & 0xffff;
+  bool sign = (image >> 15) & 1;
+  int exp = (image >> 7) & 0xff;
+
+  memset (r, 0, sizeof (*r));
+  image <<= HOST_BITS_PER_LONG - 8;
+  image &= ~SIG_MSB;
+
+  if (exp == 0)
+    {
+      if (image && fmt->has_denorm)
+       {
+         r->cl = rvc_normal;
+         r->sign = sign;
+         SET_REAL_EXP (r, -126);
+         r->sig[SIGSZ-1] = image << 1;
+         normalize (r);
+       }
+      else if (fmt->has_signed_zero)
+       r->sign = sign;
+    }
+  else if (exp == 255 && (fmt->has_nans || fmt->has_inf))
+    {
+      if (image)
+       {
+         r->cl = rvc_nan;
+         r->sign = sign;
+         r->signalling = (((image >> (HOST_BITS_PER_LONG - 2)) & 1)
+                          ^ fmt->qnan_msb_set);
+         r->sig[SIGSZ-1] = image;
+       }
+      else
+       {
+         r->cl = rvc_inf;
+         r->sign = sign;
+       }
+    }
+  else
+    {
+      r->cl = rvc_normal;
+      r->sign = sign;
+      SET_REAL_EXP (r, exp - 127 + 1);
+      r->sig[SIGSZ-1] = image | SIG_MSB;
+    }
+}
+
 /* Half-precision format, as specified in IEEE 754R.  */
 const struct real_format ieee_half_format =
   {
@@ -4733,6 +4924,7 @@ const struct real_format ieee_half_format =
     16,
     15,
     15,
+    16,
     false,
     true,
     true,
@@ -4758,6 +4950,7 @@ const struct real_format arm_half_format =
     17,
     15,
     15,
+    0,
     false,
     true,
     false,
@@ -4768,6 +4961,33 @@ const struct real_format arm_half_format =
     false,
     "arm_half"
   };
+
+/* ARM Bfloat half-precision format.  This format resembles a truncated
+   (16-bit) version of the 32-bit IEEE 754 single-precision floating-point
+   format.  */
+const struct real_format arm_bfloat_half_format =
+  {
+    encode_arm_bfloat_half,
+    decode_arm_bfloat_half,
+    2,
+    8,
+    8,
+    -125,
+    128,
+    15,
+    15,
+    0,
+    false,
+    true,
+    true,
+    true,
+    true,
+    true,
+    true,
+    false,
+    "arm_bfloat_half"
+  };
+
 \f
 /* A synthetic "format" for internal arithmetic.  It's the size of the
    internal significand minus the two bits needed for proper rounding.
@@ -4804,6 +5024,7 @@ const struct real_format real_internal_format =
     MAX_EXP,
     -1,
     -1,
+    0,
     false,
     false,
     true,
@@ -4847,7 +5068,7 @@ real_powi (REAL_VALUE_TYPE *r, format_helper fmt,
     neg = false;
 
   t = *x;
-  bit = (unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1);
+  bit = HOST_WIDE_INT_1U << (HOST_BITS_PER_WIDE_INT - 1);
   for (i = 0; i < HOST_BITS_PER_WIDE_INT; i++)
     {
       if (init)
@@ -4929,6 +5150,97 @@ real_round (REAL_VALUE_TYPE *r, format_helper fmt,
     real_convert (r, fmt, r);
 }
 
+/* Return true (including 0) if integer part of R is even, else return
+   false.  The function is not valid for rvc_inf and rvc_nan classes.  */
+
+static bool
+is_even (REAL_VALUE_TYPE *r)
+{
+  gcc_assert (r->cl != rvc_inf);
+  gcc_assert (r->cl != rvc_nan);
+
+  if (r->cl == rvc_zero)
+    return true;
+
+  /* For (-1,1), number is even.  */
+  if (REAL_EXP (r) <= 0)
+    return true;
+
+  /* Check lowest bit, if not set, return true.  */
+  else if (REAL_EXP (r) <= SIGNIFICAND_BITS)
+    {
+      unsigned int n = SIGNIFICAND_BITS - REAL_EXP (r);
+      int w = n / HOST_BITS_PER_LONG;
+
+      unsigned long num = ((unsigned long)1 << (n % HOST_BITS_PER_LONG));
+
+      if ((r->sig[w] & num) == 0)
+       return true;
+    }
+  else
+    return true;
+
+  return false;
+}
+
+/* Return true if R is halfway between two integers, else return
+   false.  */
+
+static bool
+is_halfway_below (const REAL_VALUE_TYPE *r)
+{
+  if (r->cl != rvc_normal)
+    return false;
+
+  /* For numbers (-0.5,0) and (0,0.5).  */
+  if (REAL_EXP (r) < 0)
+    return false;
+
+  else if (REAL_EXP (r) < SIGNIFICAND_BITS)
+    {
+      unsigned int n = SIGNIFICAND_BITS - REAL_EXP (r) - 1;
+      int w = n / HOST_BITS_PER_LONG;
+
+      for (int i = 0; i < w; ++i)
+       if (r->sig[i] != 0)
+         return false;
+
+      unsigned long num = 1UL << (n % HOST_BITS_PER_LONG);
+
+      if ((r->sig[w] & num) != 0 && (r->sig[w] & (num - 1)) == 0)
+       return true;
+    }
+  return false;
+}
+
+/* Round X to nearest integer, rounding halfway cases towards even.  */
+
+void
+real_roundeven (REAL_VALUE_TYPE *r, format_helper fmt,
+               const REAL_VALUE_TYPE *x)
+{
+  if (is_halfway_below (x))
+    {
+      /* Special case as -0.5 rounds to -0.0 and
+        similarly +0.5 rounds to +0.0.  */
+      if (REAL_EXP (x) == 0)
+       {
+         *r = *x;
+         clear_significand_below (r, SIGNIFICAND_BITS);
+       }
+      else
+       {
+         do_add (r, x, &dconsthalf, x->sign);
+         if (!is_even (r))
+           do_add (r, r, &dconstm1, x->sign);
+       }
+      if (fmt)
+       real_convert (r, fmt, r);
+    }
+  else
+    real_round (r, fmt, x);
+}
+
 /* Set the sign of R to the sign of X.  */
 
 void
@@ -4937,7 +5249,8 @@ real_copysign (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *x)
   r->sign = x->sign;
 }
 
-/* Check whether the real constant value given is an integer.  */
+/* Check whether the real constant value given is an integer.
+   Returns false for signaling NaN.  */
 
 bool
 real_isinteger (const REAL_VALUE_TYPE *c, format_helper fmt)
@@ -4966,16 +5279,118 @@ real_isinteger (const REAL_VALUE_TYPE *c, HOST_WIDE_INT *int_out)
   return false;
 }
 
+/* Calculate nextafter (X, Y) or nexttoward (X, Y).  Return true if
+   underflow or overflow needs to be raised.  */
+
+bool
+real_nextafter (REAL_VALUE_TYPE *r, format_helper fmt,
+               const REAL_VALUE_TYPE *x, const REAL_VALUE_TYPE *y)
+{
+  int cmp = do_compare (x, y, 2);
+  /* If either operand is NaN, return qNaN.  */
+  if (cmp == 2)
+    {
+      get_canonical_qnan (r, 0);
+      return false;
+    }
+  /* If x == y, return y cast to target type.  */
+  if (cmp == 0)
+    {
+      real_convert (r, fmt, y);
+      return false;
+    }
+
+  if (x->cl == rvc_zero)
+    {
+      get_zero (r, y->sign);
+      r->cl = rvc_normal;
+      SET_REAL_EXP (r, fmt->emin - fmt->p + 1);
+      r->sig[SIGSZ - 1] = SIG_MSB;
+      return false;
+    }
+
+  int np2 = SIGNIFICAND_BITS - fmt->p;
+  /* For denormals adjust np2 correspondingly.  */
+  if (x->cl == rvc_normal && REAL_EXP (x) < fmt->emin)
+    np2 += fmt->emin - REAL_EXP (x);
+
+  REAL_VALUE_TYPE u;
+  get_zero (r, x->sign);
+  get_zero (&u, 0);
+  set_significand_bit (&u, np2);
+  r->cl = rvc_normal;
+  SET_REAL_EXP (r, REAL_EXP (x));
+
+  if (x->cl == rvc_inf)
+    {
+      bool borrow = sub_significands (r, r, &u, 0);
+      gcc_assert (borrow);
+      SET_REAL_EXP (r, fmt->emax);
+    }
+  else if (cmp == (x->sign ? 1 : -1))
+    {
+      if (add_significands (r, x, &u))
+       {
+         /* Overflow.  Means the significand had been all ones, and
+            is now all zeros.  Need to increase the exponent, and
+            possibly re-normalize it.  */
+         SET_REAL_EXP (r, REAL_EXP (r) + 1);
+         if (REAL_EXP (r) > fmt->emax)
+           {
+             get_inf (r, x->sign);
+             return true;
+           }
+         r->sig[SIGSZ - 1] = SIG_MSB;
+       }
+    }
+  else
+    {
+      if (REAL_EXP (x) > fmt->emin && x->sig[SIGSZ - 1] == SIG_MSB)
+       {
+         int i;
+         for (i = SIGSZ - 2; i >= 0; i--)
+           if (x->sig[i])
+             break;
+         if (i < 0)
+           {
+             /* When mantissa is 1.0, we need to subtract only
+                half of u: nextafter (1.0, 0.0) is 1.0 - __DBL_EPSILON__ / 2
+                rather than 1.0 - __DBL_EPSILON__.  */
+             clear_significand_bit (&u, np2);
+             np2--;
+             set_significand_bit (&u, np2);
+           }
+       }
+      sub_significands (r, x, &u, 0);
+    }
+
+  /* Clear out trailing garbage.  */
+  clear_significand_below (r, np2);
+  normalize (r);
+  if (REAL_EXP (r) <= fmt->emin - fmt->p)
+    {
+      get_zero (r, x->sign);
+      return true;
+    }
+  return r->cl == rvc_zero || REAL_EXP (r) < fmt->emin;
+}
+
 /* Write into BUF the maximum representable finite floating-point
    number, (1 - b**-p) * b**emax for a given FP format FMT as a hex
    float string.  LEN is the size of BUF, and the buffer must be large
-   enough to contain the resulting string.  */
+   enough to contain the resulting string.  If NORM_MAX, instead write
+   the maximum representable finite normalized floating-point number,
+   defined to be such that all choices of digits for that exponent are
+   representable in the format (this only makes a difference for IBM
+   long double).  */
 
 void
-get_max_float (const struct real_format *fmt, char *buf, size_t len)
+get_max_float (const struct real_format *fmt, char *buf, size_t len,
+              bool norm_max)
 {
   int i, n;
   char *p;
+  bool is_ibm_extended = fmt->pnan < fmt->p;
 
   strcpy (buf, "0x0.");
   n = fmt->p;
@@ -4983,8 +5398,9 @@ get_max_float (const struct real_format *fmt, char *buf, size_t len)
     *p++ = 'f';
   if (i < n)
     *p++ = "08ce"[n - i];
-  sprintf (p, "p%d", fmt->emax);
-  if (fmt->pnan < fmt->p)
+  sprintf (p, "p%d",
+          (is_ibm_extended && norm_max) ? fmt->emax - 1 : fmt->emax);
+  if (is_ibm_extended && !norm_max)
     {
       /* This is an IBM extended double format made up of two IEEE
         doubles.  The value of the long double is the sum of the
@@ -4998,6 +5414,19 @@ get_max_float (const struct real_format *fmt, char *buf, size_t len)
   gcc_assert (strlen (buf) < len);
 }
 
+/* True if all values of integral type can be represented
+   by this floating-point type exactly.  */
+
+bool format_helper::can_represent_integral_type_p (tree type) const
+{
+  gcc_assert (! decimal_p () && INTEGRAL_TYPE_P (type));
+
+  /* INT?_MIN is power-of-two so it takes
+     only one mantissa bit.  */
+  bool signed_p = TYPE_SIGN (type) == SIGNED;
+  return TYPE_PRECISION (type) - signed_p <= significand_size (*this);
+}
+
 /* True if mode M has a NaN representation and
    the treatment of NaN operands is important.  */
 
@@ -5101,3 +5530,29 @@ HONOR_SIGN_DEPENDENT_ROUNDING (const_rtx x)
 {
   return HONOR_SIGN_DEPENDENT_ROUNDING (GET_MODE (x));
 }
+
+/* Fills r with the largest value such that 1 + r*r won't overflow.
+   This is used in both sin (atan (x)) and cos (atan(x)) optimizations. */
+
+void
+build_sinatan_real (REAL_VALUE_TYPE * r, tree type)
+{
+  REAL_VALUE_TYPE maxval;
+  mpfr_t mpfr_const1, mpfr_c, mpfr_maxval;
+  machine_mode mode = TYPE_MODE (type);
+  const struct real_format * fmt = REAL_MODE_FORMAT (mode);
+
+  real_maxval (&maxval, 0, mode);
+
+  mpfr_inits (mpfr_const1, mpfr_c, mpfr_maxval, NULL);
+
+  mpfr_from_real (mpfr_const1, &dconst1, MPFR_RNDN);
+  mpfr_from_real (mpfr_maxval, &maxval,  MPFR_RNDN);
+
+  mpfr_sub (mpfr_c, mpfr_maxval, mpfr_const1, MPFR_RNDN);
+  mpfr_sqrt (mpfr_c, mpfr_c, MPFR_RNDZ);
+
+  real_from_mpfr (r, mpfr_c, fmt, MPFR_RNDZ);
+  
+  mpfr_clears (mpfr_const1, mpfr_c, mpfr_maxval, NULL);
+}