aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/Support/APFloat.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2020-10-01 19:06:07 +0000
committerDimitry Andric <dim@FreeBSD.org>2020-10-01 19:06:07 +0000
commit8833aad7befe90716c7526ce6858344ba635582f (patch)
tree9aec57adb104344fd9f314fea15790c7e414a677 /contrib/llvm-project/llvm/lib/Support/APFloat.cpp
parentba2548b7bfbd9edfa706bf562349e713e6d8bab0 (diff)
parentd189cf5a4676d763c4e28d7a597c55761e356832 (diff)
Notes
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Support/APFloat.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/Support/APFloat.cpp15
1 files changed, 15 insertions, 0 deletions
diff --git a/contrib/llvm-project/llvm/lib/Support/APFloat.cpp b/contrib/llvm-project/llvm/lib/Support/APFloat.cpp
index 569cac790af9..362595d8f8b1 100644
--- a/contrib/llvm-project/llvm/lib/Support/APFloat.cpp
+++ b/contrib/llvm-project/llvm/lib/Support/APFloat.cpp
@@ -2242,6 +2242,21 @@ IEEEFloat::opStatus IEEEFloat::convert(const fltSemantics &toSemantics,
if (!X86SpecialNan && semantics == &semX87DoubleExtended)
APInt::tcSetBit(significandParts(), semantics->precision - 1);
+ // If we are truncating NaN, it is possible that we shifted out all of the
+ // set bits in a signalling NaN payload. But NaN must remain NaN, so some
+ // bit in the significand must be set (otherwise it is Inf).
+ // This can only happen with sNaN. Set the 1st bit after the quiet bit,
+ // so that we still have an sNaN.
+ // FIXME: Set quiet and return opInvalidOp (on convert of any sNaN).
+ // But this requires fixing LLVM to parse 32-bit hex FP or ignoring
+ // conversions while parsing IR.
+ if (APInt::tcIsZero(significandParts(), newPartCount)) {
+ assert(shift < 0 && "Should not lose NaN payload on extend");
+ assert(semantics->precision >= 3 && "Unexpectedly narrow significand");
+ assert(*losesInfo && "Missing payload should have set lost info");
+ APInt::tcSetBit(significandParts(), semantics->precision - 3);
+ }
+
// gcc forces the Quiet bit on, which means (float)(double)(float_sNan)
// does not give you back the same bits. This is dubious, and we
// don't currently do it. You're really supposed to get