Message ID | 20180511004345.26708-5-richard.henderson@linaro.org |
---|---|
State | New |
Headers | show |
Series | softfloat: Clean up NaN handling | expand |
Richard Henderson <richard.henderson@linaro.org> writes: > Shift the NaN fraction to a canonical position, much like we do > for the fraction of normal numbers. Immediately, this simplifies > the float-to-float conversion. Later, this will facilitate > manipulation of NaNs within the shared code paths. > > Signed-off-by: Richard Henderson <richard.henderson@linaro.org> > --- > fpu/softfloat.c | 13 ++++++------- > 1 file changed, 6 insertions(+), 7 deletions(-) > > diff --git a/fpu/softfloat.c b/fpu/softfloat.c > index 5e4982b035..df377b6314 100644 > --- a/fpu/softfloat.c > +++ b/fpu/softfloat.c > @@ -329,10 +329,11 @@ static FloatParts canonicalize(FloatParts part, const FloatFmt *parm, > if (part.frac == 0) { > part.cls = float_class_inf; > } else { > + part.frac <<= parm->frac_shift; > #ifdef NO_SIGNALING_NANS > part.cls = float_class_qnan; > #else > - int64_t msb = part.frac << (parm->frac_shift + 2); > + int64_t msb = part.frac << 2; > if ((msb < 0) == status->snan_bit_is_one) { > part.cls = float_class_snan; > } else { > @@ -498,6 +499,7 @@ static FloatParts round_canonical(FloatParts p, float_status *s, > case float_class_qnan: > case float_class_snan: > exp = exp_max; > + frac >>= parm->frac_shift; Unfortunately we now miss this step when we handle: case float_class_msnan: return float64_maybe_silence_nan(float64_pack_raw(p), s); This seems to fix that: recanonicalise frac before packing and sending 1 file changed, 3 insertions(+) fpu/softfloat.c | 3 +++ modified fpu/softfloat.c @@ -532,6 +532,7 @@ static float16 float16a_round_pack_canonical(const FloatFmt *params, case float_class_dnan: return float16_default_nan(s); case float_class_msnan: + p.frac >>= params->frac_shift; return float16_maybe_silence_nan(float16_pack_raw(p), s); default: p = round_canonical(p, s, params); @@ -555,6 +556,7 @@ static float32 float32_round_pack_canonical(FloatParts p, float_status *s) case float_class_dnan: return float32_default_nan(s); case float_class_msnan: + p.frac >>= float32_params.frac_shift; return float32_maybe_silence_nan(float32_pack_raw(p), s); default: p = round_canonical(p, s, &float32_params); @@ -573,6 +575,7 @@ static float64 float64_round_pack_canonical(FloatParts p, float_status *s) case float_class_dnan: return float64_default_nan(s); case float_class_msnan: + p.frac >>= float64_params.frac_shift; return float64_maybe_silence_nan(float64_pack_raw(p), s); default: p = round_canonical(p, s, &float64_params); -- Alex Bennée
On 05/11/2018 09:26 AM, Alex Bennée wrote: > > Richard Henderson <richard.henderson@linaro.org> writes: > >> Shift the NaN fraction to a canonical position, much like we do >> for the fraction of normal numbers. Immediately, this simplifies >> the float-to-float conversion. Later, this will facilitate >> manipulation of NaNs within the shared code paths. >> >> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> >> --- >> fpu/softfloat.c | 13 ++++++------- >> 1 file changed, 6 insertions(+), 7 deletions(-) >> >> diff --git a/fpu/softfloat.c b/fpu/softfloat.c >> index 5e4982b035..df377b6314 100644 >> --- a/fpu/softfloat.c >> +++ b/fpu/softfloat.c >> @@ -329,10 +329,11 @@ static FloatParts canonicalize(FloatParts part, const FloatFmt *parm, >> if (part.frac == 0) { >> part.cls = float_class_inf; >> } else { >> + part.frac <<= parm->frac_shift; >> #ifdef NO_SIGNALING_NANS >> part.cls = float_class_qnan; >> #else >> - int64_t msb = part.frac << (parm->frac_shift + 2); >> + int64_t msb = part.frac << 2; >> if ((msb < 0) == status->snan_bit_is_one) { >> part.cls = float_class_snan; >> } else { >> @@ -498,6 +499,7 @@ static FloatParts round_canonical(FloatParts p, float_status *s, >> case float_class_qnan: >> case float_class_snan: >> exp = exp_max; >> + frac >>= parm->frac_shift; > > Unfortunately we now miss this step when we handle: > > case float_class_msnan: > return float64_maybe_silence_nan(float64_pack_raw(p), s); > > This seems to fix that: > > recanonicalise frac before packing and sending Good catch. Merged for bisection. r~
diff --git a/fpu/softfloat.c b/fpu/softfloat.c index 5e4982b035..df377b6314 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -329,10 +329,11 @@ static FloatParts canonicalize(FloatParts part, const FloatFmt *parm, if (part.frac == 0) { part.cls = float_class_inf; } else { + part.frac <<= parm->frac_shift; #ifdef NO_SIGNALING_NANS part.cls = float_class_qnan; #else - int64_t msb = part.frac << (parm->frac_shift + 2); + int64_t msb = part.frac << 2; if ((msb < 0) == status->snan_bit_is_one) { part.cls = float_class_snan; } else { @@ -498,6 +499,7 @@ static FloatParts round_canonical(FloatParts p, float_status *s, case float_class_qnan: case float_class_snan: exp = exp_max; + frac >>= parm->frac_shift; break; default: @@ -1264,13 +1266,10 @@ static FloatParts float_to_float(FloatParts a, } /* - * Our only option now is to "re-pack" the NaN. As the - * canonilization process doesn't mess with fraction bits for - * NaNs we do it all here. We also reset a.exp to the - * destination format exp_max as the maybe_silence_nan code - * assumes it is correct (which is would be for non-conversions). + * Reset a.exp to the destination format exp_max as + * the maybe_silence_nan code assumes it is correct + * (which it would be for non-conversions). */ - a.frac = a.frac << (64 - srcf->frac_size) >> (64 - dstf->frac_size); a.exp = dstf->exp_max; a.cls = float_class_msnan; }
Shift the NaN fraction to a canonical position, much like we do for the fraction of normal numbers. Immediately, this simplifies the float-to-float conversion. Later, this will facilitate manipulation of NaNs within the shared code paths. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> --- fpu/softfloat.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) -- 2.17.0