mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-28 19:31:58 +00:00
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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@97364 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
6281cda673
commit
e12b73816b
@ -173,11 +173,16 @@ namespace llvm {
|
||||
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 @@ namespace llvm {
|
||||
/// 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 @@ namespace llvm {
|
||||
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;
|
||||
|
@ -1308,6 +1308,9 @@ public:
|
||||
/// 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.
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
;
|
||||
|
@ -344,6 +344,35 @@ TEST(APFloatTest, toString) {
|
||||
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");
|
||||
|
Loading…
Reference in New Issue
Block a user