]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/real.c
Update copyright years.
[thirdparty/gcc.git] / gcc / real.c
index 25f0a5b1466300cc966f0ca8b03736934987de98..a57e5df113fb5c9dad5c909294918566a0009b74 100644 (file)
@@ -1,5 +1,5 @@
 /* real.c - software floating point emulation.
-   Copyright (C) 1993-2016 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>
 
@@ -960,12 +960,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))
@@ -2104,7 +2104,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));
@@ -2120,7 +2120,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
@@ -2266,7 +2266,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);
 }
 
@@ -2431,9 +2431,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);
 
     }
@@ -2474,8 +2474,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;
@@ -2887,7 +2887,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:
@@ -3043,6 +3043,7 @@ const struct real_format ieee_single_format =
     128,
     31,
     31,
+    32,
     false,
     true,
     true,
@@ -3065,6 +3066,7 @@ const struct real_format mips_single_format =
     128,
     31,
     31,
+    32,
     false,
     true,
     true,
@@ -3087,6 +3089,7 @@ const struct real_format motorola_single_format =
     128,
     31,
     31,
+    32,
     false,
     true,
     true,
@@ -3120,6 +3123,7 @@ const struct real_format spu_single_format =
     129,
     31,
     31,
+    0,
     true,
     false,
     false,
@@ -3330,6 +3334,7 @@ const struct real_format ieee_double_format =
     1024,
     63,
     63,
+    64,
     false,
     true,
     true,
@@ -3352,6 +3357,7 @@ const struct real_format mips_double_format =
     1024,
     63,
     63,
+    64,
     false,
     true,
     true,
@@ -3374,6 +3380,7 @@ const struct real_format motorola_double_format =
     1024,
     63,
     63,
+    64,
     false,
     true,
     true,
@@ -3719,6 +3726,7 @@ const struct real_format ieee_extended_motorola_format =
     16384,
     95,
     95,
+    0,
     false,
     true,
     true,
@@ -3741,6 +3749,7 @@ const struct real_format ieee_extended_intel_96_format =
     16384,
     79,
     79,
+    65,
     false,
     true,
     true,
@@ -3763,6 +3772,7 @@ const struct real_format ieee_extended_intel_128_format =
     16384,
     79,
     79,
+    65,
     false,
     true,
     true,
@@ -3787,6 +3797,7 @@ const struct real_format ieee_extended_intel_96_round_53_format =
     16384,
     79,
     79,
+    33,
     false,
     true,
     true,
@@ -3876,6 +3887,7 @@ const struct real_format ibm_extended_format =
     1024,
     127,
     -1,
+    0,
     false,
     true,
     true,
@@ -3898,6 +3910,7 @@ const struct real_format mips_extended_format =
     1024,
     127,
     -1,
+    0,
     false,
     true,
     true,
@@ -4162,6 +4175,7 @@ const struct real_format ieee_quad_format =
     16384,
     127,
     127,
+    128,
     false,
     true,
     true,
@@ -4184,6 +4198,7 @@ const struct real_format mips_quad_format =
     16384,
     127,
     127,
+    128,
     false,
     true,
     true,
@@ -4485,6 +4500,7 @@ const struct real_format vax_f_format =
     127,
     15,
     15,
+    0,
     false,
     false,
     false,
@@ -4507,6 +4523,7 @@ const struct real_format vax_d_format =
     127,
     15,
     15,
+    0,
     false,
     false,
     false,
@@ -4529,6 +4546,7 @@ const struct real_format vax_g_format =
     1023,
     15,
     15,
+    0,
     false,
     false,
     false,
@@ -4606,6 +4624,7 @@ const struct real_format decimal_single_format =
     97,
     31,
     31,
+    32,
     false,
     true,
     true,
@@ -4629,6 +4648,7 @@ const struct real_format decimal_double_format =
     385,
     63,
     63,
+    64,
     false,
     true,
     true,
@@ -4652,6 +4672,7 @@ const struct real_format decimal_quad_format =
     6145,
     127,
     127,
+    128,
     false,
     true,
     true,
@@ -4778,6 +4799,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 =
   {
@@ -4790,6 +4921,7 @@ const struct real_format ieee_half_format =
     16,
     15,
     15,
+    16,
     false,
     true,
     true,
@@ -4815,6 +4947,7 @@ const struct real_format arm_half_format =
     17,
     15,
     15,
+    0,
     false,
     true,
     false,
@@ -4825,6 +4958,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.
@@ -4861,6 +5021,7 @@ const struct real_format real_internal_format =
     MAX_EXP,
     -1,
     -1,
+    0,
     false,
     false,
     true,
@@ -4986,6 +5147,101 @@ 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.  */
+
+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.  The function is not valid for rvc_inf and rvc_nan classes.  */
+
+bool
+is_halfway_below (const REAL_VALUE_TYPE *r)
+{
+  gcc_assert (r->cl != rvc_inf);
+  gcc_assert (r->cl != rvc_nan);
+  int i;
+
+  if (r->cl == rvc_zero)
+    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 (i = 0; i < w; ++i)
+       if (r->sig[i] != 0)
+         return false;
+
+      unsigned long num = ((unsigned long)1 << (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
@@ -5024,16 +5280,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;
@@ -5041,8 +5399,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
@@ -5056,6 +5415,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.  */
 
@@ -5159,3 +5531,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);
+}