compiler: avoid negative zero in float constants
authorIan Lance Taylor <ian@gcc.gnu.org>
Tue, 6 Feb 2018 15:30:06 +0000 (15:30 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Tue, 6 Feb 2018 15:30:06 +0000 (15:30 +0000)
    Check for negative numbers with very small magnitudes that will round
    to negative zero, and force them to positive zero instead.

    This implements the spec clarification in https://golang.org/cl/14727.
    The test is in https://golang.org/cl/91895.

    Fixes golang/go#12621

    Reviewed-on: https://go-review.googlesource.com/92175

From-SVN: r257415

gcc/go/gofrontend/MERGE
gcc/go/gofrontend/expressions.cc
gcc/go/gofrontend/expressions.h

index 91bebe5d232bb74305baeb7e52310eec404e6751..8c49b2b12da37b23d2934adce35ef1ccf315267b 100644 (file)
@@ -1,4 +1,4 @@
-1927b40e59e7c2067ecb03384b331d1be3cb5eea
+02f11a2d5cf0db2c2675c13d92bb69529f2175dd
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
index 8555c052980812559fc21c62eb36150ce555f6a0..f50de0a500448e4d95d2d22013193179cb010521 100644 (file)
@@ -16158,10 +16158,16 @@ Numeric_constant::set_float(Type* type, const mpfr_t val)
   this->clear();
   this->classification_ = NC_FLOAT;
   this->type_ = type;
+
   // Numeric constants do not have negative zero values, so remove
   // them here.  They also don't have infinity or NaN values, but we
   // should never see them here.
-  if (mpfr_zero_p(val))
+  int bits = 0;
+  if (type != NULL
+      && type->float_type() != NULL
+      && !type->float_type()->is_abstract())
+    bits = type->float_type()->bits();
+  if (Numeric_constant::is_float_neg_zero(val, bits))
     mpfr_init_set_ui(this->u_.float_val, 0, GMP_RNDN);
   else
     mpfr_init_set(this->u_.float_val, val, GMP_RNDN);
@@ -16175,8 +16181,60 @@ Numeric_constant::set_complex(Type* type, const mpc_t val)
   this->clear();
   this->classification_ = NC_COMPLEX;
   this->type_ = type;
+
+  // Avoid negative zero as in set_float.
+  int bits = 0;
+  if (type != NULL
+      && type->complex_type() != NULL
+      && !type->complex_type()->is_abstract())
+    bits = type->complex_type()->bits() / 2;
+
+  mpfr_t real;
+  mpfr_init_set(real, mpc_realref(val), GMP_RNDN);
+  if (Numeric_constant::is_float_neg_zero(real, bits))
+    mpfr_set_ui(real, 0, GMP_RNDN);
+
+  mpfr_t imag;
+  mpfr_init_set(imag, mpc_imagref(val), GMP_RNDN);
+  if (Numeric_constant::is_float_neg_zero(imag, bits))
+    mpfr_set_ui(imag, 0, GMP_RNDN);
+
   mpc_init2(this->u_.complex_val, mpc_precision);
-  mpc_set(this->u_.complex_val, val, MPC_RNDNN);
+  mpc_set_fr_fr(this->u_.complex_val, real, imag, MPC_RNDNN);
+
+  mpfr_clear(real);
+  mpfr_clear(imag);
+}
+
+// Return whether VAL, at a precision of BITS, is a negative zero.
+// BITS may be zero in which case it is ignored.
+
+bool
+Numeric_constant::is_float_neg_zero(const mpfr_t val, int bits)
+{
+  if (!mpfr_signbit(val))
+    return false;
+  if (mpfr_zero_p(val))
+    return true;
+  mp_exp_t min_exp;
+  switch (bits)
+    {
+    case 0:
+      return false;
+    case 32:
+      // In a denormalized float32 the exponent is -126, and there are
+      // 24 bits of which at least the last must be 1, so the smallest
+      // representable non-zero exponent is -126 - (24 - 1) == -149.
+      min_exp = -149;
+      break;
+    case 64:
+      // Minimum exponent is -1022, there are 53 bits.
+      min_exp = -1074;
+      break;
+    default:
+      go_unreachable();
+    }
+  return mpfr_get_exp(val) < min_exp;
 }
 
 // Get an int value.
index d16a284b6b04c766430f7b0c6ee3c4ad11b0480c..a58c79c7b1512c7f99e47bbe3cb6831b18227159 100644 (file)
@@ -4220,6 +4220,9 @@ class Numeric_constant
   bool
   check_complex_type(Complex_type*, bool, Location);
 
+  static bool
+  is_float_neg_zero(const mpfr_t, int bits);
+
   // The kinds of constants.
   enum Classification
   {