diff options
Diffstat (limited to 'gcc/real.cc')
-rw-r--r-- | gcc/real.cc | 27 |
1 files changed, 15 insertions, 12 deletions
diff --git a/gcc/real.cc b/gcc/real.cc index b64bad0..95a9332 100644 --- a/gcc/real.cc +++ b/gcc/real.cc @@ -2230,7 +2230,6 @@ real_from_integer (REAL_VALUE_TYPE *r, format_helper fmt, { unsigned int len = val_in.get_precision (); int i, j, e = 0; - int maxbitlen = MAX_BITSIZE_MODE_ANY_INT + HOST_BITS_PER_WIDE_INT; const unsigned int realmax = (SIGNIFICAND_BITS / HOST_BITS_PER_WIDE_INT * HOST_BITS_PER_WIDE_INT); @@ -2238,12 +2237,6 @@ real_from_integer (REAL_VALUE_TYPE *r, format_helper fmt, r->cl = rvc_normal; r->sign = wi::neg_p (val_in, sgn); - /* We have to ensure we can negate the largest negative number. */ - wide_int val = wide_int::from (val_in, maxbitlen, sgn); - - if (r->sign) - val = -val; - /* Ensure a multiple of HOST_BITS_PER_WIDE_INT, ceiling, as elt won't work with precisions that are not a multiple of HOST_BITS_PER_WIDE_INT. */ @@ -2252,7 +2245,13 @@ real_from_integer (REAL_VALUE_TYPE *r, format_helper fmt, /* Ensure we can represent the largest negative number. */ len += 1; - len = len/HOST_BITS_PER_WIDE_INT * HOST_BITS_PER_WIDE_INT; + len = len / HOST_BITS_PER_WIDE_INT * HOST_BITS_PER_WIDE_INT; + + /* We have to ensure we can negate the largest negative number. */ + wide_int val = wide_int::from (val_in, len, sgn); + + if (r->sign) + val = -val; /* Cap the size to the size allowed by real.h. */ if (len > realmax) @@ -2260,14 +2259,18 @@ real_from_integer (REAL_VALUE_TYPE *r, format_helper fmt, HOST_WIDE_INT cnt_l_z; cnt_l_z = wi::clz (val); - if (maxbitlen - cnt_l_z > realmax) + if (len - cnt_l_z > realmax) { - e = maxbitlen - cnt_l_z - realmax; + e = len - cnt_l_z - realmax; /* This value is too large, we must shift it right to preserve all the bits we can, and then bump the - exponent up by that amount. */ - val = wi::lrshift (val, e); + exponent up by that amount, but or in 1 if any of + the shifted out bits are non-zero. */ + if (wide_int::from (val, e, UNSIGNED) != 0) + val = wi::set_bit (wi::lrshift (val, e), 0); + else + val = wi::lrshift (val, e); } len = realmax; } |