diff --git a/builtins-test/tests/addsub.rs b/builtins-test/tests/addsub.rs index 859de3e42..65bafec37 100644 --- a/builtins-test/tests/addsub.rs +++ b/builtins-test/tests/addsub.rs @@ -108,6 +108,25 @@ macro_rules! float_sum { ); } }); + + // Quiet sNaN by setting the top significand bit. `sub(x, nan)` + // flips that sign because sub is add with b's sign bit inverted. + let one = <$f as Float>::ONE; + for input in [ + <$f as Float>::SNAN, + <$f as Float>::NAN, + <$f as Float>::NEG_SNAN, + <$f as Float>::NEG_NAN, + ] { + let expected = + <$f>::from_bits(input.to_bits() | <$f as Float>::SIG_TOP_BIT); + assert_eq!($fn_add(input, one).to_bits(), expected.to_bits()); + assert_eq!($fn_add(one, input).to_bits(), expected.to_bits()); + assert_eq!($fn_sub(input, one).to_bits(), expected.to_bits()); + let flipped = + <$f>::from_bits(expected.to_bits() ^ <$f as Float>::SIGN_MASK); + assert_eq!($fn_sub(one, input).to_bits(), flipped.to_bits()); + } } )* } diff --git a/compiler-builtins/src/float/add.rs b/compiler-builtins/src/float/add.rs index 6503bc37d..6481610d9 100644 --- a/compiler-builtins/src/float/add.rs +++ b/compiler-builtins/src/float/add.rs @@ -33,11 +33,11 @@ where if a_abs.wrapping_sub(one) >= inf_rep - one || b_abs.wrapping_sub(one) >= inf_rep - one { // NaN + anything = qNaN if a_abs > inf_rep { - return F::from_bits(a_abs | quiet_bit); + return F::from_bits(a_rep | quiet_bit); } // anything + NaN = qNaN if b_abs > inf_rep { - return F::from_bits(b_abs | quiet_bit); + return F::from_bits(b_rep | quiet_bit); } if a_abs == inf_rep {