Skip to content

Commit

Permalink
compiler: avoid negative zero in float constants
Browse files Browse the repository at this point in the history
    
    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/91915


git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@257390 138bc75d-0d04-0410-961f-82ee72b054a4
  • Loading branch information
ian committed Feb 5, 2018
1 parent a9a9828 commit cba143a
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 3 deletions.
2 changes: 1 addition & 1 deletion gcc/go/gofrontend/MERGE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
36594b69b94326014c331fe50a5a345ef4f8de16
7eebd495df915ab87926b8dd88f554674cfdacea

The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
52 changes: 50 additions & 2 deletions gcc/go/gofrontend/expressions.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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_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);
Expand All @@ -16175,8 +16181,50 @@ 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_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_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 zero. BITS may be
// zero in which case it is ignored.

bool
Numeric_constant::is_float_zero(const mpfr_t val, int bits)
{
if (mpfr_zero_p(val))
return true;
switch (bits)
{
case 0:
return false;
case 32:
return mpfr_get_flt(val, GMP_RNDN) == 0;
case 64:
return mpfr_get_d(val, GMP_RNDN) == 0;
default:
go_unreachable();
}
}

// Get an int value.
Expand Down
3 changes: 3 additions & 0 deletions gcc/go/gofrontend/expressions.h
Original file line number Diff line number Diff line change
Expand Up @@ -4220,6 +4220,9 @@ class Numeric_constant
bool
check_complex_type(Complex_type*, bool, Location);

static bool
is_float_zero(const mpfr_t, int bits);

// The kinds of constants.
enum Classification
{
Expand Down

0 comments on commit cba143a

Please sign in to comment.