diff options
author | John McCall <rjmccall@apple.com> | 2010-02-28 02:51:25 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2010-02-28 02:51:25 +0000 |
commit | dcb9a7ad3d2db5f6f4dd9d1632c78645656ff678 (patch) | |
tree | 7c4c61e7a7fdf82e76ac20e04481dbb5f6aeea21 /llvm/lib/Support | |
parent | abb1c7912ecdc61f04635ad46fce2f5a830d3670 (diff) | |
download | bcm5719-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.cpp | 47 | ||||
-rw-r--r-- | llvm/lib/Support/APInt.cpp | 10 |
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 |