[llvm-commits] [llvm] r97364 - in /llvm/trunk: include/llvm/ADT/APFloat.h include/llvm/ADT/APInt.h lib/Support/APFloat.cpp lib/Support/APInt.cpp test/Transforms/InstCombine/2009-01-19-fmod-constant-float-specials.ll unittests/ADT/APFloatTest.cpp

John McCall rjmccall at apple.com
Sat Feb 27 18:51:25 PST 2010


Author: rjmccall
Date: Sat Feb 27 20:51:25 2010
New Revision: 97364

URL: http://llvm.org/viewvc/llvm-project?rev=97364&view=rev
Log:
Teach APFloat how to create both QNaNs and SNaNs and with arbitrary-width
payloads.  APFloat's internal folding routines always make QNaNs now,
instead of sometimes making QNaNs and sometimes SNaNs depending on the
type.


Modified:
    llvm/trunk/include/llvm/ADT/APFloat.h
    llvm/trunk/include/llvm/ADT/APInt.h
    llvm/trunk/lib/Support/APFloat.cpp
    llvm/trunk/lib/Support/APInt.cpp
    llvm/trunk/test/Transforms/InstCombine/2009-01-19-fmod-constant-float-specials.ll
    llvm/trunk/unittests/ADT/APFloatTest.cpp

Modified: llvm/trunk/include/llvm/ADT/APFloat.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/APFloat.h?rev=97364&r1=97363&r2=97364&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ADT/APFloat.h (original)
+++ llvm/trunk/include/llvm/ADT/APFloat.h Sat Feb 27 20:51:25 2010
@@ -173,11 +173,16 @@
       fcZero
     };
 
+    enum uninitializedTag {
+      uninitialized
+    };
+
     // Constructors.
     APFloat(const fltSemantics &); // Default construct to 0.0
     APFloat(const fltSemantics &, const StringRef &);
     APFloat(const fltSemantics &, integerPart);
-    APFloat(const fltSemantics &, fltCategory, bool negative, unsigned type=0);
+    APFloat(const fltSemantics &, fltCategory, bool negative);
+    APFloat(const fltSemantics &, uninitializedTag);
     explicit APFloat(double d);
     explicit APFloat(float f);
     explicit APFloat(const APInt &, bool isIEEE = false);
@@ -199,7 +204,26 @@
     /// default.  The value is truncated as necessary.
     static APFloat getNaN(const fltSemantics &Sem, bool Negative = false,
                           unsigned type = 0) {
-      return APFloat(Sem, fcNaN, Negative, type);
+      if (type) {
+        APInt fill(64, type);
+        return getQNaN(Sem, Negative, &fill);
+      } else {
+        return getQNaN(Sem, Negative, 0);
+      }
+    }
+
+    /// getQNan - Factory for QNaN values.
+    static APFloat getQNaN(const fltSemantics &Sem,
+                           bool Negative = false,
+                           const APInt *payload = 0) {
+      return makeNaN(Sem, false, Negative, payload);
+    }
+
+    /// getSNan - Factory for SNaN values.
+    static APFloat getSNaN(const fltSemantics &Sem,
+                           bool Negative = false,
+                           const APInt *payload = 0) {
+      return makeNaN(Sem, true, Negative, payload);
     }
 
     /// getLargest - Returns the largest finite number in the given
@@ -350,7 +374,9 @@
     opStatus modSpecials(const APFloat &);
 
     /* Miscellany.  */
-    void makeNaN(unsigned = 0);
+    static APFloat makeNaN(const fltSemantics &Sem, bool SNaN, bool Negative,
+                           const APInt *fill);
+    void makeNaN(bool SNaN = false, bool Neg = false, const APInt *fill = 0);
     opStatus normalize(roundingMode, lostFraction);
     opStatus addOrSubtract(const APFloat &, roundingMode, bool subtract);
     cmpResult compareAbsoluteValue(const APFloat &) const;

Modified: llvm/trunk/include/llvm/ADT/APInt.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/APInt.h?rev=97364&r1=97363&r2=97364&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ADT/APInt.h (original)
+++ llvm/trunk/include/llvm/ADT/APInt.h Sat Feb 27 20:51:25 2010
@@ -1308,6 +1308,9 @@
   /// Set the given bit of a bignum.  Zero-based.
   static void tcSetBit(integerPart *, unsigned int bit);
 
+  /// Clear the given bit of a bignum.  Zero-based.
+  static void tcClearBit(integerPart *, unsigned int bit);
+
   /// Returns the bit number of the least or most significant set bit
   /// of a number.  If the input number has no bits set -1U is
   /// returned.

Modified: llvm/trunk/lib/Support/APFloat.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/APFloat.cpp?rev=97364&r1=97363&r2=97364&view=diff
==============================================================================
--- llvm/trunk/lib/Support/APFloat.cpp (original)
+++ llvm/trunk/lib/Support/APFloat.cpp Sat Feb 27 20:51:25 2010
@@ -626,17 +626,37 @@
 /* Make this number a NaN, with an arbitrary but deterministic value
    for the significand.  If double or longer, this is a signalling NaN,
    which may not be ideal.  If float, this is QNaN(0).  */
-void
-APFloat::makeNaN(unsigned type)
+void APFloat::makeNaN(bool SNaN, bool Negative, const APInt *fill)
 {
   category = fcNaN;
-  // FIXME: Add double and long double support for QNaN(0).
-  if (semantics->precision == 24 && semantics->maxExponent == 127) {
-    type |=  0x7fc00000U;
-    type &= ~0x80000000U;
-  } else
-    type = ~0U;
-  APInt::tcSet(significandParts(), type, partCount());
+  sign = Negative;
+
+  // 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 (SNaN) {
+    // We always have to clear the QNaN bit to make it an SNaN.
+    APInt::tcClearBit(significandParts(), semantics->precision - 2);
+
+    // 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);
+  } else {
+    // We always have to set the QNaN bit to make it a QNaN.
+    APInt::tcSetBit(significandParts(), semantics->precision - 2);
+  }
+}
+
+APFloat APFloat::makeNaN(const fltSemantics &Sem, bool SNaN, bool Negative,
+                         const APInt *fill) {
+  APFloat value(Sem, uninitialized);
+  value.makeNaN(SNaN, Negative, fill);
+  return value;
 }
 
 APFloat &
@@ -701,9 +721,14 @@
   sign = false;
 }
 
+APFloat::APFloat(const fltSemantics &ourSemantics, uninitializedTag tag) {
+  assertArithmeticOK(ourSemantics);
+  // Allocates storage if necessary but does not initialize it.
+  initialize(&ourSemantics);
+}
 
 APFloat::APFloat(const fltSemantics &ourSemantics,
-                 fltCategory ourCategory, bool negative, unsigned type)
+                 fltCategory ourCategory, bool negative)
 {
   assertArithmeticOK(ourSemantics);
   initialize(&ourSemantics);
@@ -712,7 +737,7 @@
   if (category == fcNormal)
     category = fcZero;
   else if (ourCategory == fcNaN)
-    makeNaN(type);
+    makeNaN();
 }
 
 APFloat::APFloat(const fltSemantics &ourSemantics, const StringRef& text)

Modified: llvm/trunk/lib/Support/APInt.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/APInt.cpp?rev=97364&r1=97363&r2=97364&view=diff
==============================================================================
--- llvm/trunk/lib/Support/APInt.cpp (original)
+++ llvm/trunk/lib/Support/APInt.cpp Sat Feb 27 20:51:25 2010
@@ -2344,13 +2344,21 @@
          & ((integerPart) 1 << bit % integerPartWidth)) != 0;
 }
 
-/* Set the given bit of a bignum.  */
+/* Set the given bit of a bignum. */
 void
 APInt::tcSetBit(integerPart *parts, unsigned int bit)
 {
   parts[bit / integerPartWidth] |= (integerPart) 1 << (bit % integerPartWidth);
 }
 
+/* Clears the given bit of a bignum. */
+void
+APInt::tcClearBit(integerPart *parts, unsigned int bit)
+{
+  parts[bit / integerPartWidth] &=
+    ~((integerPart) 1 << (bit % integerPartWidth));
+}
+
 /* Returns the bit number of the least significant set bit of a
    number.  If the input number has no bits set -1U is returned.  */
 unsigned int

Modified: llvm/trunk/test/Transforms/InstCombine/2009-01-19-fmod-constant-float-specials.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/2009-01-19-fmod-constant-float-specials.ll?rev=97364&r1=97363&r2=97364&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/2009-01-19-fmod-constant-float-specials.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/2009-01-19-fmod-constant-float-specials.ll Sat Feb 27 20:51:25 2010
@@ -1,5 +1,4 @@
-; RUN: opt < %s -simplifycfg -instcombine -S | grep 0x7FF8000000000000 | count 7
-; RUN: opt < %s -simplifycfg -instcombine -S | grep 0x7FF00000FFFFFFFF | count 5
+; RUN: opt < %s -simplifycfg -instcombine -S | grep 0x7FF8000000000000 | count 12
 ; RUN: opt < %s -simplifycfg -instcombine -S | grep {0\\.0} | count 3
 ; RUN: opt < %s -simplifycfg -instcombine -S | grep {3\\.5} | count 1
 ;

Modified: llvm/trunk/unittests/ADT/APFloatTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ADT/APFloatTest.cpp?rev=97364&r1=97363&r2=97364&view=diff
==============================================================================
--- llvm/trunk/unittests/ADT/APFloatTest.cpp (original)
+++ llvm/trunk/unittests/ADT/APFloatTest.cpp Sat Feb 27 20:51:25 2010
@@ -344,6 +344,35 @@
   ASSERT_EQ("8.731834E+2", convertToString(873.1834, 0, 0));
 }
 
+static APInt nanbits(const fltSemantics &Sem,
+                     bool SNaN, bool Negative, uint64_t fill) {
+  APInt apfill(64, fill);
+  if (SNaN)
+    return APFloat::getSNaN(Sem, Negative, &apfill).bitcastToAPInt();
+  else
+    return APFloat::getQNaN(Sem, Negative, &apfill).bitcastToAPInt();
+}
+
+TEST(APFloatTest, makeNaN) {
+  ASSERT_EQ(0x7fc00000, nanbits(APFloat::IEEEsingle, false, false, 0));
+  ASSERT_EQ(0xffc00000, nanbits(APFloat::IEEEsingle, false, true, 0));
+  ASSERT_EQ(0x7fc0ae72, nanbits(APFloat::IEEEsingle, false, false, 0xae72));
+  ASSERT_EQ(0x7fffae72, nanbits(APFloat::IEEEsingle, false, false, 0xffffae72));
+  ASSERT_EQ(0x7fa00000, nanbits(APFloat::IEEEsingle, true, false, 0));
+  ASSERT_EQ(0xffa00000, nanbits(APFloat::IEEEsingle, true, true, 0));
+  ASSERT_EQ(0x7f80ae72, nanbits(APFloat::IEEEsingle, true, false, 0xae72));
+  ASSERT_EQ(0x7fbfae72, nanbits(APFloat::IEEEsingle, true, false, 0xffffae72));
+
+  ASSERT_EQ(0x7ff8000000000000ULL, nanbits(APFloat::IEEEdouble, false, false, 0));
+  ASSERT_EQ(0xfff8000000000000ULL, nanbits(APFloat::IEEEdouble, false, true, 0));
+  ASSERT_EQ(0x7ff800000000ae72ULL, nanbits(APFloat::IEEEdouble, false, false, 0xae72));
+  ASSERT_EQ(0x7fffffffffffae72ULL, nanbits(APFloat::IEEEdouble, false, false, 0xffffffffffffae72ULL));
+  ASSERT_EQ(0x7ff4000000000000ULL, nanbits(APFloat::IEEEdouble, true, false, 0));
+  ASSERT_EQ(0xfff4000000000000ULL, nanbits(APFloat::IEEEdouble, true, true, 0));
+  ASSERT_EQ(0x7ff000000000ae72ULL, nanbits(APFloat::IEEEdouble, true, false, 0xae72));
+  ASSERT_EQ(0x7ff7ffffffffae72ULL, nanbits(APFloat::IEEEdouble, true, false, 0xffffffffffffae72ULL));
+}
+
 #ifdef GTEST_HAS_DEATH_TEST
 TEST(APFloatTest, SemanticsDeath) {
   EXPECT_DEATH(APFloat(APFloat::IEEEsingle, 0.0f).convertToDouble(), "Float semantics are not IEEEdouble");





More information about the llvm-commits mailing list