[llvm-commits] [llvm] r97382 - /llvm/trunk/lib/Support/APFloat.cpp

John McCall rjmccall at apple.com
Sun Feb 28 04:49:50 PST 2010


Author: rjmccall
Date: Sun Feb 28 06:49:50 2010
New Revision: 97382

URL: http://llvm.org/viewvc/llvm-project?rev=97382&view=rev
Log:
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.


Modified:
    llvm/trunk/lib/Support/APFloat.cpp

Modified: llvm/trunk/lib/Support/APFloat.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/APFloat.cpp?rev=97382&r1=97381&r2=97382&view=diff
==============================================================================
--- llvm/trunk/lib/Support/APFloat.cpp (original)
+++ llvm/trunk/lib/Support/APFloat.cpp Sun Feb 28 06:49:50 2010
@@ -631,25 +631,45 @@
   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,





More information about the llvm-commits mailing list