diff options
Diffstat (limited to 'contrib/llvm/lib/Support/APFloat.cpp')
-rw-r--r-- | contrib/llvm/lib/Support/APFloat.cpp | 712 |
1 files changed, 518 insertions, 194 deletions
diff --git a/contrib/llvm/lib/Support/APFloat.cpp b/contrib/llvm/lib/Support/APFloat.cpp index 4cfbbf8..deb76cb 100644 --- a/contrib/llvm/lib/Support/APFloat.cpp +++ b/contrib/llvm/lib/Support/APFloat.cpp @@ -26,6 +26,15 @@ #include <cstring> #include <limits.h> +#define APFLOAT_DISPATCH_ON_SEMANTICS(METHOD_CALL) \ + do { \ + if (usesLayout<IEEEFloat>(getSemantics())) \ + return U.IEEE.METHOD_CALL; \ + if (usesLayout<DoubleAPFloat>(getSemantics())) \ + return U.Double.METHOD_CALL; \ + llvm_unreachable("Unexpected semantics"); \ + } while (false) + using namespace llvm; /// A macro used to combine two fcCategory enums into one key which can be used @@ -38,7 +47,7 @@ using namespace llvm; /* Assumed in hexadecimal significand parsing, and conversion to hexadecimal strings. */ -static_assert(integerPartWidth % 4 == 0, "Part width must be divisible by 4!"); +static_assert(APFloatBase::integerPartWidth % 4 == 0, "Part width must be divisible by 4!"); namespace llvm { /* Represents floating point arithmetic semantics. */ @@ -66,33 +75,43 @@ namespace llvm { static const fltSemantics semX87DoubleExtended = {16383, -16382, 64, 80}; static const fltSemantics semBogus = {0, 0, 0, 0}; - /* The PowerPC format consists of two doubles. It does not map cleanly - onto the usual format above. It is approximated using twice the - mantissa bits. Note that for exponents near the double minimum, - we no longer can represent the full 106 mantissa bits, so those - will be treated as denormal numbers. - - FIXME: While this approximation is equivalent to what GCC uses for - compile-time arithmetic on PPC double-double numbers, it is not able - to represent all possible values held by a PPC double-double number, - for example: (long double) 1.0 + (long double) 0x1p-106 - Should this be replaced by a full emulation of PPC double-double? + /* The IBM double-double semantics. Such a number consists of a pair of IEEE + 64-bit doubles (Hi, Lo), where |Hi| > |Lo|, and if normal, + (double)(Hi + Lo) == Hi. The numeric value it's modeling is Hi + Lo. + Therefore it has two 53-bit mantissa parts that aren't necessarily adjacent + to each other, and two 11-bit exponents. Note: we need to make the value different from semBogus as otherwise an unsafe optimization may collapse both values to a single address, and we heavily rely on them having distinct addresses. */ static const fltSemantics semPPCDoubleDouble = {-1, 0, 0, 0}; - /* There are temporary semantics for the real PPCDoubleDouble implementation. - Currently, APFloat of PPCDoubleDouble holds one PPCDoubleDoubleImpl as the - high part of double double, and one IEEEdouble as the low part, so that - the old operations operate on PPCDoubleDoubleImpl, while the newly added - operations also populate the IEEEdouble. + /* These are legacy semantics for the fallback, inaccrurate implementation of + IBM double-double, if the accurate semPPCDoubleDouble doesn't handle the + operation. It's equivalent to having an IEEE number with consecutive 106 + bits of mantissa and 11 bits of exponent. + + It's not equivalent to IBM double-double. For example, a legit IBM + double-double, 1 + epsilon: + + 1 + epsilon = 1 + (1 >> 1076) + + is not representable by a consecutive 106 bits of mantissa. - TODO: Once all functions support DoubleAPFloat mode, we'll change all - PPCDoubleDoubleImpl to IEEEdouble and remove PPCDoubleDoubleImpl. */ - static const fltSemantics semPPCDoubleDoubleImpl = {1023, -1022 + 53, 53 + 53, - 128}; + Currently, these semantics are used in the following way: + + semPPCDoubleDouble -> (IEEEdouble, IEEEdouble) -> + (64-bit APInt, 64-bit APInt) -> (128-bit APInt) -> + semPPCDoubleDoubleLegacy -> IEEE operations + + We use bitcastToAPInt() to get the bit representation (in APInt) of the + underlying IEEEdouble, then use the APInt constructor to construct the + legacy IEEE float. + + TODO: Implement all operations in semPPCDoubleDouble, and delete these + semantics. */ + static const fltSemantics semPPCDoubleDoubleLegacy = {1023, -1022 + 53, + 53 + 53, 128}; const fltSemantics &APFloatBase::IEEEhalf() { return semIEEEhalf; @@ -130,8 +149,7 @@ namespace llvm { const unsigned int maxExponent = 16383; const unsigned int maxPrecision = 113; const unsigned int maxPowerOfFiveExponent = maxExponent + maxPrecision - 1; - const unsigned int maxPowerOfFiveParts = 2 + ((maxPowerOfFiveExponent * 815) - / (351 * integerPartWidth)); + const unsigned int maxPowerOfFiveParts = 2 + ((maxPowerOfFiveExponent * 815) / (351 * APFloatBase::integerPartWidth)); unsigned int APFloatBase::semanticsPrecision(const fltSemantics &semantics) { return semantics.precision; @@ -157,7 +175,7 @@ namespace llvm { static inline unsigned int partCountForBits(unsigned int bits) { - return ((bits) + integerPartWidth - 1) / integerPartWidth; + return ((bits) + APFloatBase::integerPartWidth - 1) / APFloatBase::integerPartWidth; } /* Returns 0U-9U. Return values >= 10U are not digits. */ @@ -397,7 +415,7 @@ trailingHexadecimalFraction(StringRef::iterator p, StringRef::iterator end, /* Return the fraction lost were a bignum truncated losing the least significant BITS bits. */ static lostFraction -lostFractionThroughTruncation(const integerPart *parts, +lostFractionThroughTruncation(const APFloatBase::integerPart *parts, unsigned int partCount, unsigned int bits) { @@ -410,7 +428,7 @@ lostFractionThroughTruncation(const integerPart *parts, return lfExactlyZero; if (bits == lsb + 1) return lfExactlyHalf; - if (bits <= partCount * integerPartWidth && + if (bits <= partCount * APFloatBase::integerPartWidth && APInt::tcExtractBit(parts, bits - 1)) return lfMoreThanHalf; @@ -419,7 +437,7 @@ lostFractionThroughTruncation(const integerPart *parts, /* Shift DST right BITS bits noting lost fraction. */ static lostFraction -shiftRight(integerPart *dst, unsigned int parts, unsigned int bits) +shiftRight(APFloatBase::integerPart *dst, unsigned int parts, unsigned int bits) { lostFraction lost_fraction; @@ -466,22 +484,22 @@ HUerrBound(bool inexactMultiply, unsigned int HUerr1, unsigned int HUerr2) /* The number of ulps from the boundary (zero, or half if ISNEAREST) when the least significant BITS are truncated. BITS cannot be zero. */ -static integerPart -ulpsFromBoundary(const integerPart *parts, unsigned int bits, bool isNearest) -{ +static APFloatBase::integerPart +ulpsFromBoundary(const APFloatBase::integerPart *parts, unsigned int bits, + bool isNearest) { unsigned int count, partBits; - integerPart part, boundary; + APFloatBase::integerPart part, boundary; assert(bits != 0); bits--; - count = bits / integerPartWidth; - partBits = bits % integerPartWidth + 1; + count = bits / APFloatBase::integerPartWidth; + partBits = bits % APFloatBase::integerPartWidth + 1; - part = parts[count] & (~(integerPart) 0 >> (integerPartWidth - partBits)); + part = parts[count] & (~(APFloatBase::integerPart) 0 >> (APFloatBase::integerPartWidth - partBits)); if (isNearest) - boundary = (integerPart) 1 << (partBits - 1); + boundary = (APFloatBase::integerPart) 1 << (partBits - 1); else boundary = 0; @@ -495,32 +513,30 @@ ulpsFromBoundary(const integerPart *parts, unsigned int bits, bool isNearest) if (part == boundary) { while (--count) if (parts[count]) - return ~(integerPart) 0; /* A lot. */ + return ~(APFloatBase::integerPart) 0; /* A lot. */ return parts[0]; } else if (part == boundary - 1) { while (--count) if (~parts[count]) - return ~(integerPart) 0; /* A lot. */ + return ~(APFloatBase::integerPart) 0; /* A lot. */ return -parts[0]; } - return ~(integerPart) 0; /* A lot. */ + return ~(APFloatBase::integerPart) 0; /* A lot. */ } /* Place pow(5, power) in DST, and return the number of parts used. DST must be at least one part larger than size of the answer. */ static unsigned int -powerOf5(integerPart *dst, unsigned int power) -{ - static const integerPart firstEightPowers[] = { 1, 5, 25, 125, 625, 3125, - 15625, 78125 }; - integerPart pow5s[maxPowerOfFiveParts * 2 + 5]; +powerOf5(APFloatBase::integerPart *dst, unsigned int power) { + static const APFloatBase::integerPart firstEightPowers[] = { 1, 5, 25, 125, 625, 3125, 15625, 78125 }; + APFloatBase::integerPart pow5s[maxPowerOfFiveParts * 2 + 5]; pow5s[0] = 78125 * 5; unsigned int partsCount[16] = { 1 }; - integerPart scratch[maxPowerOfFiveParts], *p1, *p2, *pow5; + APFloatBase::integerPart scratch[maxPowerOfFiveParts], *p1, *p2, *pow5; unsigned int result; assert(power <= maxExponent); @@ -549,7 +565,7 @@ powerOf5(integerPart *dst, unsigned int power) } if (power & 1) { - integerPart *tmp; + APFloatBase::integerPart *tmp; APInt::tcFullMultiply(p2, p1, pow5, result, pc); result += pc; @@ -585,14 +601,14 @@ static const char NaNU[] = "NAN"; significant nibble. Write out exactly COUNT hexdigits, return COUNT. */ static unsigned int -partAsHex (char *dst, integerPart part, unsigned int count, +partAsHex (char *dst, APFloatBase::integerPart part, unsigned int count, const char *hexDigitChars) { unsigned int result = count; - assert(count != 0 && count <= integerPartWidth / 4); + assert(count != 0 && count <= APFloatBase::integerPartWidth / 4); - part >>= (integerPartWidth - 4 * count); + part >>= (APFloatBase::integerPartWidth - 4 * count); while (count--) { dst[count] = hexDigitChars[part & 0xf]; part >>= 4; @@ -742,7 +758,7 @@ IEEEFloat &IEEEFloat::operator=(IEEEFloat &&rhs) { bool IEEEFloat::isDenormal() const { return isFiniteNonZero() && (exponent == semantics->minExponent) && - (APInt::tcExtractBit(significandParts(), + (APInt::tcExtractBit(significandParts(), semantics->precision - 1) == 0); } @@ -862,20 +878,15 @@ IEEEFloat::IEEEFloat(IEEEFloat &&rhs) : semantics(&semBogus) { IEEEFloat::~IEEEFloat() { freeSignificand(); } -// Profile - This method 'profiles' an APFloat for use with FoldingSet. -void IEEEFloat::Profile(FoldingSetNodeID &ID) const { - ID.Add(bitcastToAPInt()); -} - unsigned int IEEEFloat::partCount() const { return partCountForBits(semantics->precision + 1); } -const integerPart *IEEEFloat::significandParts() const { +const IEEEFloat::integerPart *IEEEFloat::significandParts() const { return const_cast<IEEEFloat *>(this)->significandParts(); } -integerPart *IEEEFloat::significandParts() { +IEEEFloat::integerPart *IEEEFloat::significandParts() { if (partCount() > 1) return significand.parts; else @@ -898,7 +909,7 @@ void IEEEFloat::incrementSignificand() { } /* Add the significand of the RHS. Returns the carry flag. */ -integerPart IEEEFloat::addSignificand(const IEEEFloat &rhs) { +IEEEFloat::integerPart IEEEFloat::addSignificand(const IEEEFloat &rhs) { integerPart *parts; parts = significandParts(); @@ -911,8 +922,8 @@ integerPart IEEEFloat::addSignificand(const IEEEFloat &rhs) { /* Subtract the significand of the RHS with a borrow flag. Returns the borrow flag. */ -integerPart IEEEFloat::subtractSignificand(const IEEEFloat &rhs, - integerPart borrow) { +IEEEFloat::integerPart IEEEFloat::subtractSignificand(const IEEEFloat &rhs, + integerPart borrow) { integerPart *parts; parts = significandParts(); @@ -966,14 +977,14 @@ lostFraction IEEEFloat::multiplySignificand(const IEEEFloat &rhs, // rhs = b23 . b22 ... b0 * 2^e2 // the result of multiplication is: // *this = c48 c47 c46 . c45 ... c0 * 2^(e1+e2) - // Note that there are three significant bits at the left-hand side of the + // Note that there are three significant bits at the left-hand side of the // radix point: two for the multiplication, and an overflow bit for the // addition (that will always be zero at this point). Move the radix point // toward left by two bits, and adjust exponent accordingly. exponent += 2; if (addend && addend->isNonZero()) { - // The intermediate result of the multiplication has "2 * precision" + // The intermediate result of the multiplication has "2 * precision" // signicant bit; adjust the addend to be consistent with mul result. // Significand savedSignificand = significand; @@ -1025,7 +1036,7 @@ lostFraction IEEEFloat::multiplySignificand(const IEEEFloat &rhs, } // Convert the result having "2 * precision" significant-bits back to the one - // having "precision" significant-bits. First, move the radix point from + // having "precision" significant-bits. First, move the radix point from // poision "2*precision - 1" to "precision - 1". The exponent need to be // adjusted by "2*precision - 1" - "precision - 1" = "precision". exponent -= precision + 1; @@ -1541,11 +1552,13 @@ IEEEFloat::opStatus IEEEFloat::divideSpecials(const IEEEFloat &rhs) { case PackCategoriesIntoKey(fcInfinity, fcNaN): category = fcNaN; copySignificand(rhs); + LLVM_FALLTHROUGH; case PackCategoriesIntoKey(fcNaN, fcZero): case PackCategoriesIntoKey(fcNaN, fcNormal): case PackCategoriesIntoKey(fcNaN, fcInfinity): case PackCategoriesIntoKey(fcNaN, fcNaN): sign = false; + LLVM_FALLTHROUGH; case PackCategoriesIntoKey(fcInfinity, fcZero): case PackCategoriesIntoKey(fcInfinity, fcNormal): case PackCategoriesIntoKey(fcZero, fcInfinity): @@ -1611,16 +1624,6 @@ void IEEEFloat::changeSign() { sign = !sign; } -void IEEEFloat::clearSign() { - /* So is this one. */ - sign = 0; -} - -void IEEEFloat::copySign(const IEEEFloat &rhs) { - /* And this one. */ - sign = rhs.sign; -} - /* Normalized addition or subtraction. */ IEEEFloat::opStatus IEEEFloat::addOrSubtract(const IEEEFloat &rhs, roundingMode rounding_mode, @@ -1712,9 +1715,10 @@ IEEEFloat::opStatus IEEEFloat::remainder(const IEEEFloat &rhs) { int parts = partCount(); integerPart *x = new integerPart[parts]; bool ignored; - fs = V.convertToInteger(x, parts * integerPartWidth, true, - rmNearestTiesToEven, &ignored); - if (fs==opInvalidOp) { + fs = V.convertToInteger(makeMutableArrayRef(x, parts), + parts * integerPartWidth, true, rmNearestTiesToEven, + &ignored); + if (fs == opInvalidOp) { delete[] x; return fs; } @@ -1735,43 +1739,20 @@ IEEEFloat::opStatus IEEEFloat::remainder(const IEEEFloat &rhs) { return fs; } -/* Normalized llvm frem (C fmod). - This is not currently correct in all cases. */ +/* Normalized llvm frem (C fmod). */ IEEEFloat::opStatus IEEEFloat::mod(const IEEEFloat &rhs) { opStatus fs; fs = modSpecials(rhs); - if (isFiniteNonZero() && rhs.isFiniteNonZero()) { - IEEEFloat V = *this; - unsigned int origSign = sign; - - fs = V.divide(rhs, rmNearestTiesToEven); - if (fs == opDivByZero) - return fs; - - int parts = partCount(); - integerPart *x = new integerPart[parts]; - bool ignored; - fs = V.convertToInteger(x, parts * integerPartWidth, true, - rmTowardZero, &ignored); - if (fs==opInvalidOp) { - delete[] x; - return fs; - } - - fs = V.convertFromZeroExtendedInteger(x, parts * integerPartWidth, true, - rmNearestTiesToEven); - assert(fs==opOK); // should always work - - fs = V.multiply(rhs, rmNearestTiesToEven); - assert(fs==opOK || fs==opInexact); // should not overflow or underflow - + while (isFiniteNonZero() && rhs.isFiniteNonZero() && + compareAbsoluteValue(rhs) != cmpLessThan) { + IEEEFloat V = scalbn(rhs, ilogb(*this) - ilogb(rhs), rmNearestTiesToEven); + if (compareAbsoluteValue(V) == cmpLessThan) + V = scalbn(V, -1, rmNearestTiesToEven); + V.sign = sign; + fs = subtract(V, rmNearestTiesToEven); - assert(fs==opOK || fs==opInexact); // likewise - - if (isZero()) - sign = origSign; // IEEE754 requires this - delete[] x; + assert(fs==opOK); } return fs; } @@ -1840,7 +1821,7 @@ IEEEFloat::opStatus IEEEFloat::roundToIntegral(roundingMode rounding_mode) { IEEEFloat MagicConstant(*semantics); fs = MagicConstant.convertFromAPInt(IntegerConstant, false, rmNearestTiesToEven); - MagicConstant.copySign(*this); + MagicConstant.sign = sign; if (fs != opOK) return fs; @@ -2047,7 +2028,7 @@ IEEEFloat::opStatus IEEEFloat::convert(const fltSemantics &toSemantics, Note that for conversions to integer type the C standard requires round-to-zero to always be used. */ IEEEFloat::opStatus IEEEFloat::convertToSignExtendedInteger( - integerPart *parts, unsigned int width, bool isSigned, + MutableArrayRef<integerPart> parts, unsigned int width, bool isSigned, roundingMode rounding_mode, bool *isExact) const { lostFraction lost_fraction; const integerPart *src; @@ -2060,9 +2041,10 @@ IEEEFloat::opStatus IEEEFloat::convertToSignExtendedInteger( return opInvalidOp; dstPartsCount = partCountForBits(width); + assert(dstPartsCount <= parts.size() && "Integer too big"); if (category == fcZero) { - APInt::tcSet(parts, 0, dstPartsCount); + APInt::tcSet(parts.data(), 0, dstPartsCount); // Negative zero can't be represented as an int. *isExact = !sign; return opOK; @@ -2074,7 +2056,7 @@ IEEEFloat::opStatus IEEEFloat::convertToSignExtendedInteger( the destination. */ if (exponent < 0) { /* Our absolute value is less than one; truncate everything. */ - APInt::tcSet(parts, 0, dstPartsCount); + APInt::tcSet(parts.data(), 0, dstPartsCount); /* For exponent -1 the integer bit represents .5, look at that. For smaller exponents leftmost truncated bit is 0. */ truncatedBits = semantics->precision -1U - exponent; @@ -2090,11 +2072,13 @@ IEEEFloat::opStatus IEEEFloat::convertToSignExtendedInteger( if (bits < semantics->precision) { /* We truncate (semantics->precision - bits) bits. */ truncatedBits = semantics->precision - bits; - APInt::tcExtract(parts, dstPartsCount, src, bits, truncatedBits); + APInt::tcExtract(parts.data(), dstPartsCount, src, bits, truncatedBits); } else { /* We want at least as many bits as are available. */ - APInt::tcExtract(parts, dstPartsCount, src, semantics->precision, 0); - APInt::tcShiftLeft(parts, dstPartsCount, bits - semantics->precision); + APInt::tcExtract(parts.data(), dstPartsCount, src, semantics->precision, + 0); + APInt::tcShiftLeft(parts.data(), dstPartsCount, + bits - semantics->precision); truncatedBits = 0; } } @@ -2106,7 +2090,7 @@ IEEEFloat::opStatus IEEEFloat::convertToSignExtendedInteger( truncatedBits); if (lost_fraction != lfExactlyZero && roundAwayFromZero(rounding_mode, lost_fraction, truncatedBits)) { - if (APInt::tcIncrement(parts, dstPartsCount)) + if (APInt::tcIncrement(parts.data(), dstPartsCount)) return opInvalidOp; /* Overflow. */ } } else { @@ -2114,7 +2098,7 @@ IEEEFloat::opStatus IEEEFloat::convertToSignExtendedInteger( } /* Step 3: check if we fit in the destination. */ - unsigned int omsb = APInt::tcMSB(parts, dstPartsCount) + 1; + unsigned int omsb = APInt::tcMSB(parts.data(), dstPartsCount) + 1; if (sign) { if (!isSigned) { @@ -2125,7 +2109,8 @@ IEEEFloat::opStatus IEEEFloat::convertToSignExtendedInteger( /* It takes omsb bits to represent the unsigned integer value. We lose a bit for the sign, but care is needed as the maximally negative integer is a special case. */ - if (omsb == width && APInt::tcLSB(parts, dstPartsCount) + 1 != omsb) + if (omsb == width && + APInt::tcLSB(parts.data(), dstPartsCount) + 1 != omsb) return opInvalidOp; /* This case can happen because of rounding. */ @@ -2133,7 +2118,7 @@ IEEEFloat::opStatus IEEEFloat::convertToSignExtendedInteger( return opInvalidOp; } - APInt::tcNegate (parts, dstPartsCount); + APInt::tcNegate (parts.data(), dstPartsCount); } else { if (omsb >= width + !isSigned) return opInvalidOp; @@ -2155,11 +2140,10 @@ IEEEFloat::opStatus IEEEFloat::convertToSignExtendedInteger( the original value. This is almost equivalent to result==opOK, except for negative zeroes. */ -IEEEFloat::opStatus IEEEFloat::convertToInteger(integerPart *parts, - unsigned int width, - bool isSigned, - roundingMode rounding_mode, - bool *isExact) const { +IEEEFloat::opStatus +IEEEFloat::convertToInteger(MutableArrayRef<integerPart> parts, + unsigned int width, bool isSigned, + roundingMode rounding_mode, bool *isExact) const { opStatus fs; fs = convertToSignExtendedInteger(parts, width, isSigned, rounding_mode, @@ -2169,6 +2153,7 @@ IEEEFloat::opStatus IEEEFloat::convertToInteger(integerPart *parts, unsigned int bits, dstPartsCount; dstPartsCount = partCountForBits(width); + assert(dstPartsCount <= parts.size() && "Integer too big"); if (category == fcNaN) bits = 0; @@ -2177,30 +2162,14 @@ IEEEFloat::opStatus IEEEFloat::convertToInteger(integerPart *parts, else bits = width - isSigned; - APInt::tcSetLeastSignificantBits(parts, dstPartsCount, bits); + APInt::tcSetLeastSignificantBits(parts.data(), dstPartsCount, bits); if (sign && isSigned) - APInt::tcShiftLeft(parts, dstPartsCount, width - 1); + APInt::tcShiftLeft(parts.data(), dstPartsCount, width - 1); } return fs; } -/* Same as convertToInteger(integerPart*, ...), except the result is returned in - an APSInt, whose initial bit-width and signed-ness are used to determine the - precision of the conversion. - */ -IEEEFloat::opStatus IEEEFloat::convertToInteger(APSInt &result, - roundingMode rounding_mode, - bool *isExact) const { - unsigned bitWidth = result.getBitWidth(); - SmallVector<uint64_t, 4> parts(result.getNumWords()); - opStatus status = convertToInteger( - parts.data(), bitWidth, result.isSigned(), rounding_mode, isExact); - // Keeps the original signed-ness. - result = APInt(bitWidth, parts); - return status; -} - /* Convert an unsigned integer SRC to a floating point number, rounding according to ROUNDING_MODE. The sign of the floating point number is not modified. */ @@ -2484,7 +2453,7 @@ IEEEFloat::convertFromDecimalString(StringRef str, roundingMode rounding_mode) { // Test if we have a zero number allowing for strings with no null terminators // and zero decimals with non-zero exponents. - // + // // We computed firstSigDigit by ignoring all zeros and dots. Thus if // D->firstSigDigit equals str.end(), every digit must be a zero and there can // be at most one dot. On the other hand, if we have a zero with a non-zero @@ -2852,7 +2821,7 @@ APInt IEEEFloat::convertF80LongDoubleAPFloatToAPInt() const { } APInt IEEEFloat::convertPPCDoubleDoubleAPFloatToAPInt() const { - assert(semantics == (const llvm::fltSemantics *)&semPPCDoubleDoubleImpl); + assert(semantics == (const llvm::fltSemantics *)&semPPCDoubleDoubleLegacy); assert(partCount()==2); uint64_t words[2]; @@ -3033,7 +3002,7 @@ APInt IEEEFloat::bitcastToAPInt() const { if (semantics == (const llvm::fltSemantics*)&semIEEEquad) return convertQuadrupleAPFloatToAPInt(); - if (semantics == (const llvm::fltSemantics *)&semPPCDoubleDoubleImpl) + if (semantics == (const llvm::fltSemantics *)&semPPCDoubleDoubleLegacy) return convertPPCDoubleDoubleAPFloatToAPInt(); assert(semantics == (const llvm::fltSemantics*)&semX87DoubleExtended && @@ -3103,14 +3072,14 @@ void IEEEFloat::initFromPPCDoubleDoubleAPInt(const APInt &api) { // Get the first double and convert to our format. initFromDoubleAPInt(APInt(64, i1)); - fs = convert(semPPCDoubleDoubleImpl, rmNearestTiesToEven, &losesInfo); + fs = convert(semPPCDoubleDoubleLegacy, rmNearestTiesToEven, &losesInfo); assert(fs == opOK && !losesInfo); (void)fs; // Unless we have a special case, add in second double. if (isFiniteNonZero()) { IEEEFloat v(semIEEEdouble, APInt(64, i2)); - fs = v.convert(semPPCDoubleDoubleImpl, rmNearestTiesToEven, &losesInfo); + fs = v.convert(semPPCDoubleDoubleLegacy, rmNearestTiesToEven, &losesInfo); assert(fs == opOK && !losesInfo); (void)fs; @@ -3264,7 +3233,7 @@ void IEEEFloat::initFromAPInt(const fltSemantics *Sem, const APInt &api) { return initFromF80LongDoubleAPInt(api); if (Sem == &semIEEEquad) return initFromQuadrupleAPInt(api); - if (Sem == &semPPCDoubleDoubleImpl) + if (Sem == &semPPCDoubleDoubleLegacy) return initFromPPCDoubleDoubleAPInt(api); llvm_unreachable(nullptr); @@ -3419,7 +3388,7 @@ namespace { } void IEEEFloat::toString(SmallVectorImpl<char> &Str, unsigned FormatPrecision, - unsigned FormatMaxPadding) const { + unsigned FormatMaxPadding, bool TruncateZero) const { switch (category) { case fcInfinity: if (isNegative()) @@ -3433,9 +3402,16 @@ void IEEEFloat::toString(SmallVectorImpl<char> &Str, unsigned FormatPrecision, if (isNegative()) Str.push_back('-'); - if (!FormatMaxPadding) - append(Str, "0.0E+0"); - else + if (!FormatMaxPadding) { + if (TruncateZero) + append(Str, "0.0E+0"); + else { + append(Str, "0.0"); + if (FormatPrecision > 1) + Str.append(FormatPrecision - 1, '0'); + append(Str, "e+00"); + } + } else Str.push_back('0'); return; @@ -3468,7 +3444,7 @@ void IEEEFloat::toString(SmallVectorImpl<char> &Str, unsigned FormatPrecision, // Ignore trailing binary zeros. int trailingZeros = significand.countTrailingZeros(); exp += trailingZeros; - significand = significand.lshr(trailingZeros); + significand.lshrInPlace(trailingZeros); // Change the exponent from 2^e to 10^e. if (exp == 0) { @@ -3569,12 +3545,16 @@ void IEEEFloat::toString(SmallVectorImpl<char> &Str, unsigned FormatPrecision, Str.push_back(buffer[NDigits-1]); Str.push_back('.'); - if (NDigits == 1) + if (NDigits == 1 && TruncateZero) Str.push_back('0'); else for (unsigned I = 1; I != NDigits; ++I) Str.push_back(buffer[NDigits-1-I]); - Str.push_back('E'); + // Fill with zeros up to FormatPrecision. + if (!TruncateZero && FormatPrecision > NDigits - 1) + Str.append(FormatPrecision - NDigits + 1, '0'); + // For !TruncateZero we use lower 'e'. + Str.push_back(TruncateZero ? 'E' : 'e'); Str.push_back(exp >= 0 ? '+' : '-'); if (exp < 0) exp = -exp; @@ -3583,6 +3563,9 @@ void IEEEFloat::toString(SmallVectorImpl<char> &Str, unsigned FormatPrecision, expbuf.push_back((char) ('0' + (exp % 10))); exp /= 10; } while (exp); + // Exponent always at least two digits if we do not truncate zeros. + if (!TruncateZero && expbuf.size() < 2) + expbuf.push_back('0'); for (unsigned I = 0, E = expbuf.size(); I != E; ++I) Str.push_back(expbuf[E-1-I]); return; @@ -3620,7 +3603,7 @@ void IEEEFloat::toString(SmallVectorImpl<char> &Str, unsigned FormatPrecision, Str.push_back(buffer[NDigits-I-1]); } -bool IEEEFloat::getExactInverse(IEEEFloat *inv) const { +bool IEEEFloat::getExactInverse(APFloat *inv) const { // Special floats and denormals have no exact inverse. if (!isFiniteNonZero()) return false; @@ -3644,7 +3627,7 @@ bool IEEEFloat::getExactInverse(IEEEFloat *inv) const { reciprocal.significandLSB() == reciprocal.semantics->precision - 1); if (inv) - *inv = reciprocal; + *inv = APFloat(reciprocal, *semantics); return true; } @@ -3856,28 +3839,29 @@ IEEEFloat frexp(const IEEEFloat &Val, int &Exp, IEEEFloat::roundingMode RM) { } DoubleAPFloat::DoubleAPFloat(const fltSemantics &S) - : Semantics(&S), Floats(new APFloat[2]{APFloat(semPPCDoubleDoubleImpl), - APFloat(semIEEEdouble)}) { + : Semantics(&S), + Floats(new APFloat[2]{APFloat(semIEEEdouble), APFloat(semIEEEdouble)}) { assert(Semantics == &semPPCDoubleDouble); } DoubleAPFloat::DoubleAPFloat(const fltSemantics &S, uninitializedTag) : Semantics(&S), - Floats(new APFloat[2]{APFloat(semPPCDoubleDoubleImpl, uninitialized), + Floats(new APFloat[2]{APFloat(semIEEEdouble, uninitialized), APFloat(semIEEEdouble, uninitialized)}) { assert(Semantics == &semPPCDoubleDouble); } DoubleAPFloat::DoubleAPFloat(const fltSemantics &S, integerPart I) - : Semantics(&S), Floats(new APFloat[2]{APFloat(semPPCDoubleDoubleImpl, I), + : Semantics(&S), Floats(new APFloat[2]{APFloat(semIEEEdouble, I), APFloat(semIEEEdouble)}) { assert(Semantics == &semPPCDoubleDouble); } DoubleAPFloat::DoubleAPFloat(const fltSemantics &S, const APInt &I) - : Semantics(&S), Floats(new APFloat[2]{ - APFloat(semPPCDoubleDoubleImpl, I), - APFloat(semIEEEdouble, APInt(64, I.getRawData()[1]))}) { + : Semantics(&S), + Floats(new APFloat[2]{ + APFloat(semIEEEdouble, APInt(64, I.getRawData()[0])), + APFloat(semIEEEdouble, APInt(64, I.getRawData()[1]))}) { assert(Semantics == &semPPCDoubleDouble); } @@ -3886,9 +3870,7 @@ DoubleAPFloat::DoubleAPFloat(const fltSemantics &S, APFloat &&First, : Semantics(&S), Floats(new APFloat[2]{std::move(First), std::move(Second)}) { assert(Semantics == &semPPCDoubleDouble); - // TODO Check for First == &IEEEdouble once the transition is done. - assert(&Floats[0].getSemantics() == &semPPCDoubleDoubleImpl || - &Floats[0].getSemantics() == &semIEEEdouble); + assert(&Floats[0].getSemantics() == &semIEEEdouble); assert(&Floats[1].getSemantics() == &semIEEEdouble); } @@ -3917,6 +3899,7 @@ DoubleAPFloat &DoubleAPFloat::operator=(const DoubleAPFloat &RHS) { return *this; } +// Implement addition, subtraction, multiplication and division based on: // "Software for Doubled-Precision Floating-Point Computations", // by Seppo Linnainmaa, ACM TOMS vol 7 no 3, September 1981, pages 272-283. APFloat::opStatus DoubleAPFloat::addImpl(const APFloat &a, const APFloat &aa, @@ -3928,7 +3911,7 @@ APFloat::opStatus DoubleAPFloat::addImpl(const APFloat &a, const APFloat &aa, if (!z.isFinite()) { if (!z.isInfinity()) { Floats[0] = std::move(z); - Floats[1].makeZero(false); + Floats[1].makeZero(/* Neg = */ false); return (opStatus)Status; } Status = opOK; @@ -3946,7 +3929,7 @@ APFloat::opStatus DoubleAPFloat::addImpl(const APFloat &a, const APFloat &aa, } if (!z.isFinite()) { Floats[0] = std::move(z); - Floats[1].makeZero(false); + Floats[1].makeZero(/* Neg = */ false); return (opStatus)Status; } Floats[0] = z; @@ -3982,13 +3965,13 @@ APFloat::opStatus DoubleAPFloat::addImpl(const APFloat &a, const APFloat &aa, Status |= zz.add(cc, RM); if (zz.isZero() && !zz.isNegative()) { Floats[0] = std::move(z); - Floats[1].makeZero(false); + Floats[1].makeZero(/* Neg = */ false); return opOK; } Floats[0] = z; Status |= Floats[0].add(zz, RM); if (!Floats[0].isFinite()) { - Floats[1].makeZero(false); + Floats[1].makeZero(/* Neg = */ false); return (opStatus)Status; } Floats[1] = std::move(z); @@ -4033,25 +4016,15 @@ APFloat::opStatus DoubleAPFloat::addWithSpecial(const DoubleAPFloat &LHS, } assert(LHS.getCategory() == fcNormal && RHS.getCategory() == fcNormal); - // These conversions will go away once PPCDoubleDoubleImpl goes away. - // (PPCDoubleDoubleImpl, IEEEDouble) -> (IEEEDouble, IEEEDouble) - APFloat A(semIEEEdouble, - APInt(64, LHS.Floats[0].bitcastToAPInt().getRawData()[0])), - AA(LHS.Floats[1]), - C(semIEEEdouble, APInt(64, RHS.Floats[0].bitcastToAPInt().getRawData()[0])), + APFloat A(LHS.Floats[0]), AA(LHS.Floats[1]), C(RHS.Floats[0]), CC(RHS.Floats[1]); + assert(&A.getSemantics() == &semIEEEdouble); assert(&AA.getSemantics() == &semIEEEdouble); + assert(&C.getSemantics() == &semIEEEdouble); assert(&CC.getSemantics() == &semIEEEdouble); - Out.Floats[0] = APFloat(semIEEEdouble); + assert(&Out.Floats[0].getSemantics() == &semIEEEdouble); assert(&Out.Floats[1].getSemantics() == &semIEEEdouble); - - auto Ret = Out.addImpl(A, AA, C, CC, RM); - - // (IEEEDouble, IEEEDouble) -> (PPCDoubleDoubleImpl, IEEEDouble) - uint64_t Buffer[] = {Out.Floats[0].bitcastToAPInt().getRawData()[0], - Out.Floats[1].bitcastToAPInt().getRawData()[0]}; - Out.Floats[0] = APFloat(semPPCDoubleDoubleImpl, APInt(128, 2, Buffer)); - return Ret; + return Out.addImpl(A, AA, C, CC, RM); } APFloat::opStatus DoubleAPFloat::add(const DoubleAPFloat &RHS, @@ -4067,6 +4040,140 @@ APFloat::opStatus DoubleAPFloat::subtract(const DoubleAPFloat &RHS, return Ret; } +APFloat::opStatus DoubleAPFloat::multiply(const DoubleAPFloat &RHS, + APFloat::roundingMode RM) { + const auto &LHS = *this; + auto &Out = *this; + /* Interesting observation: For special categories, finding the lowest + common ancestor of the following layered graph gives the correct + return category: + + NaN + / \ + Zero Inf + \ / + Normal + + e.g. NaN * NaN = NaN + Zero * Inf = NaN + Normal * Zero = Zero + Normal * Inf = Inf + */ + if (LHS.getCategory() == fcNaN) { + Out = LHS; + return opOK; + } + if (RHS.getCategory() == fcNaN) { + Out = RHS; + return opOK; + } + if ((LHS.getCategory() == fcZero && RHS.getCategory() == fcInfinity) || + (LHS.getCategory() == fcInfinity && RHS.getCategory() == fcZero)) { + Out.makeNaN(false, false, nullptr); + return opOK; + } + if (LHS.getCategory() == fcZero || LHS.getCategory() == fcInfinity) { + Out = LHS; + return opOK; + } + if (RHS.getCategory() == fcZero || RHS.getCategory() == fcInfinity) { + Out = RHS; + return opOK; + } + assert(LHS.getCategory() == fcNormal && RHS.getCategory() == fcNormal && + "Special cases not handled exhaustively"); + + int Status = opOK; + APFloat A = Floats[0], B = Floats[1], C = RHS.Floats[0], D = RHS.Floats[1]; + // t = a * c + APFloat T = A; + Status |= T.multiply(C, RM); + if (!T.isFiniteNonZero()) { + Floats[0] = T; + Floats[1].makeZero(/* Neg = */ false); + return (opStatus)Status; + } + + // tau = fmsub(a, c, t), that is -fmadd(-a, c, t). + APFloat Tau = A; + T.changeSign(); + Status |= Tau.fusedMultiplyAdd(C, T, RM); + T.changeSign(); + { + // v = a * d + APFloat V = A; + Status |= V.multiply(D, RM); + // w = b * c + APFloat W = B; + Status |= W.multiply(C, RM); + Status |= V.add(W, RM); + // tau += v + w + Status |= Tau.add(V, RM); + } + // u = t + tau + APFloat U = T; + Status |= U.add(Tau, RM); + + Floats[0] = U; + if (!U.isFinite()) { + Floats[1].makeZero(/* Neg = */ false); + } else { + // Floats[1] = (t - u) + tau + Status |= T.subtract(U, RM); + Status |= T.add(Tau, RM); + Floats[1] = T; + } + return (opStatus)Status; +} + +APFloat::opStatus DoubleAPFloat::divide(const DoubleAPFloat &RHS, + APFloat::roundingMode RM) { + assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics"); + APFloat Tmp(semPPCDoubleDoubleLegacy, bitcastToAPInt()); + auto Ret = + Tmp.divide(APFloat(semPPCDoubleDoubleLegacy, RHS.bitcastToAPInt()), RM); + *this = DoubleAPFloat(semPPCDoubleDouble, Tmp.bitcastToAPInt()); + return Ret; +} + +APFloat::opStatus DoubleAPFloat::remainder(const DoubleAPFloat &RHS) { + assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics"); + APFloat Tmp(semPPCDoubleDoubleLegacy, bitcastToAPInt()); + auto Ret = + Tmp.remainder(APFloat(semPPCDoubleDoubleLegacy, RHS.bitcastToAPInt())); + *this = DoubleAPFloat(semPPCDoubleDouble, Tmp.bitcastToAPInt()); + return Ret; +} + +APFloat::opStatus DoubleAPFloat::mod(const DoubleAPFloat &RHS) { + assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics"); + APFloat Tmp(semPPCDoubleDoubleLegacy, bitcastToAPInt()); + auto Ret = Tmp.mod(APFloat(semPPCDoubleDoubleLegacy, RHS.bitcastToAPInt())); + *this = DoubleAPFloat(semPPCDoubleDouble, Tmp.bitcastToAPInt()); + return Ret; +} + +APFloat::opStatus +DoubleAPFloat::fusedMultiplyAdd(const DoubleAPFloat &Multiplicand, + const DoubleAPFloat &Addend, + APFloat::roundingMode RM) { + assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics"); + APFloat Tmp(semPPCDoubleDoubleLegacy, bitcastToAPInt()); + auto Ret = Tmp.fusedMultiplyAdd( + APFloat(semPPCDoubleDoubleLegacy, Multiplicand.bitcastToAPInt()), + APFloat(semPPCDoubleDoubleLegacy, Addend.bitcastToAPInt()), RM); + *this = DoubleAPFloat(semPPCDoubleDouble, Tmp.bitcastToAPInt()); + return Ret; +} + +APFloat::opStatus DoubleAPFloat::roundToIntegral(APFloat::roundingMode RM) { + assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics"); + APFloat Tmp(semPPCDoubleDoubleLegacy, bitcastToAPInt()); + auto Ret = Tmp.roundToIntegral(RM); + *this = DoubleAPFloat(semPPCDoubleDouble, Tmp.bitcastToAPInt()); + return Ret; +} + void DoubleAPFloat::changeSign() { Floats[0].changeSign(); Floats[1].changeSign(); @@ -4101,12 +4208,201 @@ bool DoubleAPFloat::isNegative() const { return Floats[0].isNegative(); } void DoubleAPFloat::makeInf(bool Neg) { Floats[0].makeInf(Neg); - Floats[1].makeZero(false); + Floats[1].makeZero(/* Neg = */ false); +} + +void DoubleAPFloat::makeZero(bool Neg) { + Floats[0].makeZero(Neg); + Floats[1].makeZero(/* Neg = */ false); +} + +void DoubleAPFloat::makeLargest(bool Neg) { + assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics"); + Floats[0] = APFloat(semIEEEdouble, APInt(64, 0x7fefffffffffffffull)); + Floats[1] = APFloat(semIEEEdouble, APInt(64, 0x7c8ffffffffffffeull)); + if (Neg) + changeSign(); +} + +void DoubleAPFloat::makeSmallest(bool Neg) { + assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics"); + Floats[0].makeSmallest(Neg); + Floats[1].makeZero(/* Neg = */ false); +} + +void DoubleAPFloat::makeSmallestNormalized(bool Neg) { + assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics"); + Floats[0] = APFloat(semIEEEdouble, APInt(64, 0x0360000000000000ull)); + if (Neg) + Floats[0].changeSign(); + Floats[1].makeZero(/* Neg = */ false); } void DoubleAPFloat::makeNaN(bool SNaN, bool Neg, const APInt *fill) { Floats[0].makeNaN(SNaN, Neg, fill); - Floats[1].makeZero(false); + Floats[1].makeZero(/* Neg = */ false); +} + +APFloat::cmpResult DoubleAPFloat::compare(const DoubleAPFloat &RHS) const { + auto Result = Floats[0].compare(RHS.Floats[0]); + // |Float[0]| > |Float[1]| + if (Result == APFloat::cmpEqual) + return Floats[1].compare(RHS.Floats[1]); + return Result; +} + +bool DoubleAPFloat::bitwiseIsEqual(const DoubleAPFloat &RHS) const { + return Floats[0].bitwiseIsEqual(RHS.Floats[0]) && + Floats[1].bitwiseIsEqual(RHS.Floats[1]); +} + +hash_code hash_value(const DoubleAPFloat &Arg) { + if (Arg.Floats) + return hash_combine(hash_value(Arg.Floats[0]), hash_value(Arg.Floats[1])); + return hash_combine(Arg.Semantics); +} + +APInt DoubleAPFloat::bitcastToAPInt() const { + assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics"); + uint64_t Data[] = { + Floats[0].bitcastToAPInt().getRawData()[0], + Floats[1].bitcastToAPInt().getRawData()[0], + }; + return APInt(128, 2, Data); +} + +APFloat::opStatus DoubleAPFloat::convertFromString(StringRef S, + roundingMode RM) { + assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics"); + APFloat Tmp(semPPCDoubleDoubleLegacy); + auto Ret = Tmp.convertFromString(S, RM); + *this = DoubleAPFloat(semPPCDoubleDouble, Tmp.bitcastToAPInt()); + return Ret; +} + +APFloat::opStatus DoubleAPFloat::next(bool nextDown) { + assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics"); + APFloat Tmp(semPPCDoubleDoubleLegacy, bitcastToAPInt()); + auto Ret = Tmp.next(nextDown); + *this = DoubleAPFloat(semPPCDoubleDouble, Tmp.bitcastToAPInt()); + return Ret; +} + +APFloat::opStatus +DoubleAPFloat::convertToInteger(MutableArrayRef<integerPart> Input, + unsigned int Width, bool IsSigned, + roundingMode RM, bool *IsExact) const { + assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics"); + return APFloat(semPPCDoubleDoubleLegacy, bitcastToAPInt()) + .convertToInteger(Input, Width, IsSigned, RM, IsExact); +} + +APFloat::opStatus DoubleAPFloat::convertFromAPInt(const APInt &Input, + bool IsSigned, + roundingMode RM) { + assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics"); + APFloat Tmp(semPPCDoubleDoubleLegacy); + auto Ret = Tmp.convertFromAPInt(Input, IsSigned, RM); + *this = DoubleAPFloat(semPPCDoubleDouble, Tmp.bitcastToAPInt()); + return Ret; +} + +APFloat::opStatus +DoubleAPFloat::convertFromSignExtendedInteger(const integerPart *Input, + unsigned int InputSize, + bool IsSigned, roundingMode RM) { + assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics"); + APFloat Tmp(semPPCDoubleDoubleLegacy); + auto Ret = Tmp.convertFromSignExtendedInteger(Input, InputSize, IsSigned, RM); + *this = DoubleAPFloat(semPPCDoubleDouble, Tmp.bitcastToAPInt()); + return Ret; +} + +APFloat::opStatus +DoubleAPFloat::convertFromZeroExtendedInteger(const integerPart *Input, + unsigned int InputSize, + bool IsSigned, roundingMode RM) { + assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics"); + APFloat Tmp(semPPCDoubleDoubleLegacy); + auto Ret = Tmp.convertFromZeroExtendedInteger(Input, InputSize, IsSigned, RM); + *this = DoubleAPFloat(semPPCDoubleDouble, Tmp.bitcastToAPInt()); + return Ret; +} + +unsigned int DoubleAPFloat::convertToHexString(char *DST, + unsigned int HexDigits, + bool UpperCase, + roundingMode RM) const { + assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics"); + return APFloat(semPPCDoubleDoubleLegacy, bitcastToAPInt()) + .convertToHexString(DST, HexDigits, UpperCase, RM); +} + +bool DoubleAPFloat::isDenormal() const { + return getCategory() == fcNormal && + (Floats[0].isDenormal() || Floats[1].isDenormal() || + // (double)(Hi + Lo) == Hi defines a normal number. + Floats[0].compare(Floats[0] + Floats[1]) != cmpEqual); +} + +bool DoubleAPFloat::isSmallest() const { + if (getCategory() != fcNormal) + return false; + DoubleAPFloat Tmp(*this); + Tmp.makeSmallest(this->isNegative()); + return Tmp.compare(*this) == cmpEqual; +} + +bool DoubleAPFloat::isLargest() const { + if (getCategory() != fcNormal) + return false; + DoubleAPFloat Tmp(*this); + Tmp.makeLargest(this->isNegative()); + return Tmp.compare(*this) == cmpEqual; +} + +bool DoubleAPFloat::isInteger() const { + assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics"); + APFloat Tmp(semPPCDoubleDoubleLegacy); + (void)Tmp.add(Floats[0], rmNearestTiesToEven); + (void)Tmp.add(Floats[1], rmNearestTiesToEven); + return Tmp.isInteger(); +} + +void DoubleAPFloat::toString(SmallVectorImpl<char> &Str, + unsigned FormatPrecision, + unsigned FormatMaxPadding, + bool TruncateZero) const { + assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics"); + APFloat(semPPCDoubleDoubleLegacy, bitcastToAPInt()) + .toString(Str, FormatPrecision, FormatMaxPadding, TruncateZero); +} + +bool DoubleAPFloat::getExactInverse(APFloat *inv) const { + assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics"); + APFloat Tmp(semPPCDoubleDoubleLegacy, bitcastToAPInt()); + if (!inv) + return Tmp.getExactInverse(nullptr); + APFloat Inv(semPPCDoubleDoubleLegacy); + auto Ret = Tmp.getExactInverse(&Inv); + *inv = APFloat(semPPCDoubleDouble, Inv.bitcastToAPInt()); + return Ret; +} + +DoubleAPFloat scalbn(DoubleAPFloat Arg, int Exp, APFloat::roundingMode RM) { + assert(Arg.Semantics == &semPPCDoubleDouble && "Unexpected Semantics"); + return DoubleAPFloat(semPPCDoubleDouble, scalbn(Arg.Floats[0], Exp, RM), + scalbn(Arg.Floats[1], Exp, RM)); +} + +DoubleAPFloat frexp(const DoubleAPFloat &Arg, int &Exp, + APFloat::roundingMode RM) { + assert(Arg.Semantics == &semPPCDoubleDouble && "Unexpected Semantics"); + APFloat First = frexp(Arg.Floats[0], Exp, RM); + APFloat Second = Arg.Floats[1]; + if (Arg.getCategory() == APFloat::fcNormal) + Second = scalbn(Second, -Exp, RM); + return DoubleAPFloat(semPPCDoubleDouble, std::move(First), std::move(Second)); } } // End detail namespace @@ -4126,10 +4422,16 @@ APFloat::Storage::Storage(IEEEFloat F, const fltSemantics &Semantics) { } APFloat::opStatus APFloat::convertFromString(StringRef Str, roundingMode RM) { - return getIEEE().convertFromString(Str, RM); + APFLOAT_DISPATCH_ON_SEMANTICS(convertFromString(Str, RM)); } -hash_code hash_value(const APFloat &Arg) { return hash_value(Arg.getIEEE()); } +hash_code hash_value(const APFloat &Arg) { + if (APFloat::usesLayout<detail::IEEEFloat>(Arg.getSemantics())) + return hash_value(Arg.U.IEEE); + if (APFloat::usesLayout<detail::DoubleAPFloat>(Arg.getSemantics())) + return hash_value(Arg.U.Double); + llvm_unreachable("Unexpected semantics"); +} APFloat::APFloat(const fltSemantics &Semantics, StringRef S) : APFloat(Semantics) { @@ -4146,10 +4448,8 @@ APFloat::opStatus APFloat::convert(const fltSemantics &ToSemantics, if (usesLayout<IEEEFloat>(getSemantics()) && usesLayout<DoubleAPFloat>(ToSemantics)) { assert(&ToSemantics == &semPPCDoubleDouble); - auto Ret = U.IEEE.convert(semPPCDoubleDoubleImpl, RM, losesInfo); - *this = APFloat(DoubleAPFloat(semPPCDoubleDouble, std::move(*this), - APFloat(semIEEEdouble)), - ToSemantics); + auto Ret = U.IEEE.convert(semPPCDoubleDoubleLegacy, RM, losesInfo); + *this = APFloat(ToSemantics, U.IEEE.bitcastToAPInt()); return Ret; } if (usesLayout<DoubleAPFloat>(getSemantics()) && @@ -4189,6 +4489,30 @@ void APFloat::print(raw_ostream &OS) const { OS << Buffer << "\n"; } -void APFloat::dump() const { print(dbgs()); } +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) +LLVM_DUMP_METHOD void APFloat::dump() const { print(dbgs()); } +#endif + +void APFloat::Profile(FoldingSetNodeID &NID) const { + NID.Add(bitcastToAPInt()); +} + +/* Same as convertToInteger(integerPart*, ...), except the result is returned in + an APSInt, whose initial bit-width and signed-ness are used to determine the + precision of the conversion. + */ +APFloat::opStatus APFloat::convertToInteger(APSInt &result, + roundingMode rounding_mode, + bool *isExact) const { + unsigned bitWidth = result.getBitWidth(); + SmallVector<uint64_t, 4> parts(result.getNumWords()); + opStatus status = convertToInteger(parts, bitWidth, result.isSigned(), + rounding_mode, isExact); + // Keeps the original signed-ness. + result = APInt(bitWidth, parts); + return status; +} } // End llvm namespace + +#undef APFLOAT_DISPATCH_ON_SEMANTICS |