llvm.org GIT mirror llvm / e12b738
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 John McCall 10 years ago
6 changed file(s) with 107 addition(s) and 17 deletion(s). Raw diff Collapse all Expand all
172172 fcZero
173173 };
174174
175 enum uninitializedTag {
176 uninitialized
177 };
178
175179 // Constructors.
176180 APFloat(const fltSemantics &); // Default construct to 0.0
177181 APFloat(const fltSemantics &, const StringRef &);
178182 APFloat(const fltSemantics &, integerPart);
179 APFloat(const fltSemantics &, fltCategory, bool negative, unsigned type=0);
183 APFloat(const fltSemantics &, fltCategory, bool negative);
184 APFloat(const fltSemantics &, uninitializedTag);
180185 explicit APFloat(double d);
181186 explicit APFloat(float f);
182187 explicit APFloat(const APInt &, bool isIEEE = false);
198203 /// default. The value is truncated as necessary.
199204 static APFloat getNaN(const fltSemantics &Sem, bool Negative = false,
200205 unsigned type = 0) {
201 return APFloat(Sem, fcNaN, Negative, type);
206 if (type) {
207 APInt fill(64, type);
208 return getQNaN(Sem, Negative, &fill);
209 } else {
210 return getQNaN(Sem, Negative, 0);
211 }
212 }
213
214 /// getQNan - Factory for QNaN values.
215 static APFloat getQNaN(const fltSemantics &Sem,
216 bool Negative = false,
217 const APInt *payload = 0) {
218 return makeNaN(Sem, false, Negative, payload);
219 }
220
221 /// getSNan - Factory for SNaN values.
222 static APFloat getSNaN(const fltSemantics &Sem,
223 bool Negative = false,
224 const APInt *payload = 0) {
225 return makeNaN(Sem, true, Negative, payload);
202226 }
203227
204228 /// getLargest - Returns the largest finite number in the given
349373 opStatus modSpecials(const APFloat &);
350374
351375 /* Miscellany. */
352 void makeNaN(unsigned = 0);
376 static APFloat makeNaN(const fltSemantics &Sem, bool SNaN, bool Negative,
377 const APInt *fill);
378 void makeNaN(bool SNaN = false, bool Neg = false, const APInt *fill = 0);
353379 opStatus normalize(roundingMode, lostFraction);
354380 opStatus addOrSubtract(const APFloat &, roundingMode, bool subtract);
355381 cmpResult compareAbsoluteValue(const APFloat &) const;
13071307 /// Set the given bit of a bignum. Zero-based.
13081308 static void tcSetBit(integerPart *, unsigned int bit);
13091309
1310 /// Clear the given bit of a bignum. Zero-based.
1311 static void tcClearBit(integerPart *, unsigned int bit);
1312
13101313 /// Returns the bit number of the least or most significant set bit
13111314 /// of a number. If the input number has no bits set -1U is
13121315 /// returned.
625625 /* Make this number a NaN, with an arbitrary but deterministic value
626626 for the significand. If double or longer, this is a signalling NaN,
627627 which may not be ideal. If float, this is QNaN(0). */
628 void
629 APFloat::makeNaN(unsigned type)
628 void APFloat::makeNaN(bool SNaN, bool Negative, const APInt *fill)
630629 {
631630 category = fcNaN;
632 // FIXME: Add double and long double support for QNaN(0).
633 if (semantics->precision == 24 && semantics->maxExponent == 127) {
634 type |= 0x7fc00000U;
635 type &= ~0x80000000U;
636 } else
637 type = ~0U;
638 APInt::tcSet(significandParts(), type, partCount());
631 sign = Negative;
632
633 // Set the significand bits to the fill.
634 if (!fill || fill->getNumWords() < partCount())
635 APInt::tcSet(significandParts(), 0, partCount());
636 if (fill)
637 APInt::tcAssign(significandParts(), fill->getRawData(), partCount());
638
639 if (SNaN) {
640 // We always have to clear the QNaN bit to make it an SNaN.
641 APInt::tcClearBit(significandParts(), semantics->precision - 2);
642
643 // If there are no bits set in the payload, we have to set
644 // *something* to make it a NaN instead of an infinity;
645 // conventionally, this is the next bit down from the QNaN bit.
646 if (APInt::tcIsZero(significandParts(), partCount()))
647 APInt::tcSetBit(significandParts(), semantics->precision - 3);
648 } else {
649 // We always have to set the QNaN bit to make it a QNaN.
650 APInt::tcSetBit(significandParts(), semantics->precision - 2);
651 }
652 }
653
654 APFloat APFloat::makeNaN(const fltSemantics &Sem, bool SNaN, bool Negative,
655 const APInt *fill) {
656 APFloat value(Sem, uninitialized);
657 value.makeNaN(SNaN, Negative, fill);
658 return value;
639659 }
640660
641661 APFloat &
700720 sign = false;
701721 }
702722
723 APFloat::APFloat(const fltSemantics &ourSemantics, uninitializedTag tag) {
724 assertArithmeticOK(ourSemantics);
725 // Allocates storage if necessary but does not initialize it.
726 initialize(&ourSemantics);
727 }
703728
704729 APFloat::APFloat(const fltSemantics &ourSemantics,
705 fltCategory ourCategory, bool negative, unsigned type)
730 fltCategory ourCategory, bool negative)
706731 {
707732 assertArithmeticOK(ourSemantics);
708733 initialize(&ourSemantics);
711736 if (category == fcNormal)
712737 category = fcZero;
713738 else if (ourCategory == fcNaN)
714 makeNaN(type);
739 makeNaN();
715740 }
716741
717742 APFloat::APFloat(const fltSemantics &ourSemantics, const StringRef& text)
23432343 & ((integerPart) 1 << bit % integerPartWidth)) != 0;
23442344 }
23452345
2346 /* Set the given bit of a bignum. */
2346 /* Set the given bit of a bignum. */
23472347 void
23482348 APInt::tcSetBit(integerPart *parts, unsigned int bit)
23492349 {
23502350 parts[bit / integerPartWidth] |= (integerPart) 1 << (bit % integerPartWidth);
2351 }
2352
2353 /* Clears the given bit of a bignum. */
2354 void
2355 APInt::tcClearBit(integerPart *parts, unsigned int bit)
2356 {
2357 parts[bit / integerPartWidth] &=
2358 ~((integerPart) 1 << (bit % integerPartWidth));
23512359 }
23522360
23532361 /* Returns the bit number of the least significant set bit of a
None ; RUN: opt < %s -simplifycfg -instcombine -S | grep 0x7FF8000000000000 | count 7
1 ; RUN: opt < %s -simplifycfg -instcombine -S | grep 0x7FF00000FFFFFFFF | count 5
0 ; RUN: opt < %s -simplifycfg -instcombine -S | grep 0x7FF8000000000000 | count 12
21 ; RUN: opt < %s -simplifycfg -instcombine -S | grep {0\\.0} | count 3
32 ; RUN: opt < %s -simplifycfg -instcombine -S | grep {3\\.5} | count 1
43 ;
343343 ASSERT_EQ("8.731834E+2", convertToString(873.1834, 0, 0));
344344 }
345345
346 static APInt nanbits(const fltSemantics &Sem,
347 bool SNaN, bool Negative, uint64_t fill) {
348 APInt apfill(64, fill);
349 if (SNaN)
350 return APFloat::getSNaN(Sem, Negative, &apfill).bitcastToAPInt();
351 else
352 return APFloat::getQNaN(Sem, Negative, &apfill).bitcastToAPInt();
353 }
354
355 TEST(APFloatTest, makeNaN) {
356 ASSERT_EQ(0x7fc00000, nanbits(APFloat::IEEEsingle, false, false, 0));
357 ASSERT_EQ(0xffc00000, nanbits(APFloat::IEEEsingle, false, true, 0));
358 ASSERT_EQ(0x7fc0ae72, nanbits(APFloat::IEEEsingle, false, false, 0xae72));
359 ASSERT_EQ(0x7fffae72, nanbits(APFloat::IEEEsingle, false, false, 0xffffae72));
360 ASSERT_EQ(0x7fa00000, nanbits(APFloat::IEEEsingle, true, false, 0));
361 ASSERT_EQ(0xffa00000, nanbits(APFloat::IEEEsingle, true, true, 0));
362 ASSERT_EQ(0x7f80ae72, nanbits(APFloat::IEEEsingle, true, false, 0xae72));
363 ASSERT_EQ(0x7fbfae72, nanbits(APFloat::IEEEsingle, true, false, 0xffffae72));
364
365 ASSERT_EQ(0x7ff8000000000000ULL, nanbits(APFloat::IEEEdouble, false, false, 0));
366 ASSERT_EQ(0xfff8000000000000ULL, nanbits(APFloat::IEEEdouble, false, true, 0));
367 ASSERT_EQ(0x7ff800000000ae72ULL, nanbits(APFloat::IEEEdouble, false, false, 0xae72));
368 ASSERT_EQ(0x7fffffffffffae72ULL, nanbits(APFloat::IEEEdouble, false, false, 0xffffffffffffae72ULL));
369 ASSERT_EQ(0x7ff4000000000000ULL, nanbits(APFloat::IEEEdouble, true, false, 0));
370 ASSERT_EQ(0xfff4000000000000ULL, nanbits(APFloat::IEEEdouble, true, true, 0));
371 ASSERT_EQ(0x7ff000000000ae72ULL, nanbits(APFloat::IEEEdouble, true, false, 0xae72));
372 ASSERT_EQ(0x7ff7ffffffffae72ULL, nanbits(APFloat::IEEEdouble, true, false, 0xffffffffffffae72ULL));
373 }
374
346375 #ifdef GTEST_HAS_DEATH_TEST
347376 TEST(APFloatTest, SemanticsDeath) {
348377 EXPECT_DEATH(APFloat(APFloat::IEEEsingle, 0.0f).convertToDouble(), "Float semantics are not IEEEdouble");