From 165e96bd25200ccabe4539aaf29a249b61074d11 Mon Sep 17 00:00:00 2001 From: John McCall Date: Sun, 28 Feb 2010 12:49:50 +0000 Subject: [PATCH] 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 --- lib/Support/APFloat.cpp | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/lib/Support/APFloat.cpp b/lib/Support/APFloat.cpp index 4f1b85431cc..16a0c232927 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,