diff options
author | John McCall <rjmccall@apple.com> | 2010-02-28 12:49:50 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2010-02-28 12:49:50 +0000 |
commit | 165e96bd25200ccabe4539aaf29a249b61074d11 (patch) | |
tree | 4b55e2f5d26b248d827d1da784f8e3ff16c182e5 /lib/Support/APFloat.cpp | |
parent | 1e7ad3993d8700488895fa372ecad55443f53485 (diff) | |
download | external_llvm-165e96bd25200ccabe4539aaf29a249b61074d11.zip external_llvm-165e96bd25200ccabe4539aaf29a249b61074d11.tar.gz external_llvm-165e96bd25200ccabe4539aaf29a249b61074d11.tar.bz2 |
Properly clear all the extra bits in a significand when making a NaN from an
APInt. Be certain to set the integer bit in an x87 extended-precision
significand so that we don't accidentally make a pseudo-NaN.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@97382 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Support/APFloat.cpp')
-rw-r--r-- | lib/Support/APFloat.cpp | 36 |
1 files changed, 28 insertions, 8 deletions
diff --git a/lib/Support/APFloat.cpp b/lib/Support/APFloat.cpp index 4f1b854..16a0c23 100644 --- a/lib/Support/APFloat.cpp +++ b/lib/Support/APFloat.cpp @@ -631,25 +631,45 @@ void APFloat::makeNaN(bool SNaN, bool Negative, const APInt *fill) category = fcNaN; sign = Negative; + integerPart *significand = significandParts(); + unsigned numParts = partCount(); + // Set the significand bits to the fill. - if (!fill || fill->getNumWords() < partCount()) - APInt::tcSet(significandParts(), 0, partCount()); - if (fill) - APInt::tcAssign(significandParts(), fill->getRawData(), partCount()); + if (!fill || fill->getNumWords() < numParts) + APInt::tcSet(significand, 0, numParts); + if (fill) { + APInt::tcAssign(significand, fill->getRawData(), partCount()); + + // Zero out the excess bits of the significand. + unsigned bitsToPreserve = semantics->precision - 1; + unsigned part = bitsToPreserve / 64; + bitsToPreserve %= 64; + significand[part] &= ((1ULL << bitsToPreserve) - 1); + for (part++; part != numParts; ++part) + significand[part] = 0; + } + + unsigned QNaNBit = semantics->precision - 2; if (SNaN) { // We always have to clear the QNaN bit to make it an SNaN. - APInt::tcClearBit(significandParts(), semantics->precision - 2); + APInt::tcClearBit(significand, QNaNBit); // If there are no bits set in the payload, we have to set // *something* to make it a NaN instead of an infinity; // conventionally, this is the next bit down from the QNaN bit. - if (APInt::tcIsZero(significandParts(), partCount())) - APInt::tcSetBit(significandParts(), semantics->precision - 3); + if (APInt::tcIsZero(significand, numParts)) + APInt::tcSetBit(significand, QNaNBit - 1); } else { // We always have to set the QNaN bit to make it a QNaN. - APInt::tcSetBit(significandParts(), semantics->precision - 2); + APInt::tcSetBit(significand, QNaNBit); } + + // For x87 extended precision, we want to make a NaN, not a + // pseudo-NaN. Maybe we should expose the ability to make + // pseudo-NaNs? + if (semantics == &APFloat::x87DoubleExtended) + APInt::tcSetBit(significand, QNaNBit + 1); } APFloat APFloat::makeNaN(const fltSemantics &Sem, bool SNaN, bool Negative, |