summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Support
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2010-02-28 02:51:25 +0000
committerJohn McCall <rjmccall@apple.com>2010-02-28 02:51:25 +0000
commitdcb9a7ad3d2db5f6f4dd9d1632c78645656ff678 (patch)
tree7c4c61e7a7fdf82e76ac20e04481dbb5f6aeea21 /llvm/lib/Support
parentabb1c7912ecdc61f04635ad46fce2f5a830d3670 (diff)
downloadbcm5719-llvm-dcb9a7ad3d2db5f6f4dd9d1632c78645656ff678.tar.gz
bcm5719-llvm-dcb9a7ad3d2db5f6f4dd9d1632c78645656ff678.zip
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. llvm-svn: 97364
Diffstat (limited to 'llvm/lib/Support')
-rw-r--r--llvm/lib/Support/APFloat.cpp47
-rw-r--r--llvm/lib/Support/APInt.cpp10
2 files changed, 45 insertions, 12 deletions
diff --git a/llvm/lib/Support/APFloat.cpp b/llvm/lib/Support/APFloat.cpp
index f90973feab8..4f1b85431cc 100644
--- a/llvm/lib/Support/APFloat.cpp
+++ b/llvm/lib/Support/APFloat.cpp
@@ -626,17 +626,37 @@ APFloat::copySignificand(const APFloat &rhs)
/* 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 @@ APFloat::APFloat(const fltSemantics &ourSemantics) {
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 @@ APFloat::APFloat(const fltSemantics &ourSemantics,
if (category == fcNormal)
category = fcZero;
else if (ourCategory == fcNaN)
- makeNaN(type);
+ makeNaN();
}
APFloat::APFloat(const fltSemantics &ourSemantics, const StringRef& text)
diff --git a/llvm/lib/Support/APInt.cpp b/llvm/lib/Support/APInt.cpp
index 3bce3f3ed3f..6a6384aa3f4 100644
--- a/llvm/lib/Support/APInt.cpp
+++ b/llvm/lib/Support/APInt.cpp
@@ -2344,13 +2344,21 @@ APInt::tcExtractBit(const integerPart *parts, unsigned int bit)
& ((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
OpenPOWER on IntegriCloud