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 | c12b133d00f9797c19fe8a9e2c8aadda3353e2fd (patch) | |
tree | ce0b3b35a161bae2a550cfcab17f281f4ae99e27 /llvm/lib/Support | |
parent | 512b65021089807a06a5cdd209b8c5b6f5d64b1f (diff) | |
download | bcm5719-llvm-c12b133d00f9797c19fe8a9e2c8aadda3353e2fd.tar.gz bcm5719-llvm-c12b133d00f9797c19fe8a9e2c8aadda3353e2fd.zip |
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.
llvm-svn: 97382
Diffstat (limited to 'llvm/lib/Support')
-rw-r--r-- | llvm/lib/Support/APFloat.cpp | 36 |
1 files changed, 28 insertions, 8 deletions
diff --git a/llvm/lib/Support/APFloat.cpp b/llvm/lib/Support/APFloat.cpp index 4f1b85431cc..16a0c232927 100644 --- a/llvm/lib/Support/APFloat.cpp +++ b/llvm/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, |